================================================== FILE PATH: ./lib/device_compatibility_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/foundation.dart' show kIsWeb, defaultTargetPlatform, TargetPlatform; import 'controller/functions/device_analyzer.dart'; // --- CompatibilityDetailCard Widget (كما هو) --- class CompatibilityDetailCard extends StatelessWidget { final Map detail; const CompatibilityDetailCard({super.key, required this.detail}); Color _getStatusColor(bool status, int achieved, int max) { if (!status) return Colors.red.shade400; if (achieved < max) return Colors.orange.shade600; return Colors.teal; } IconData _getIconForLabel(String label) { if (label.contains('رام')) return Icons.memory; if (label.contains('معالج') || label.contains('CPU')) return Icons.developer_board; if (label.contains('تخزين') || label.contains('كتابة')) return Icons.sd_storage_outlined; if (label.contains('أندرويد')) return Icons.android; if (label.contains('خدمات')) return Icons.g_mobiledata; if (label.contains('حساسات') || label.contains('Gyroscope')) return Icons.sensors; return Icons.smartphone; } @override Widget build(BuildContext context) { final bool status = detail['status'] ?? false; final String label = detail['label'] ?? ""; final int achievedScore = detail['achieved_score'] ?? 0; final int maxScore = detail['max_score'] ?? 1; final Color color = _getStatusColor(status, achievedScore, maxScore); final double progress = (maxScore > 0) ? (achievedScore / maxScore).clamp(0.0, 1.0) : 0.0; return Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 7), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.08), blurRadius: 15, offset: const Offset(0, 5)) ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(_getIconForLabel(label), color: Colors.grey.shade600, size: 20), const SizedBox(width: 8), Expanded( child: Text(label, style: TextStyle( fontSize: 15, color: Colors.grey.shade800, fontWeight: FontWeight.w600)), ), Text("$achievedScore/$maxScore نقطة", style: TextStyle( color: color, fontWeight: FontWeight.bold, fontSize: 14)), ], ), const SizedBox(height: 12), LinearProgressIndicator( value: progress, backgroundColor: Colors.grey.shade200, color: color, minHeight: 6, borderRadius: BorderRadius.circular(3), ), ], ), ); } } // --- Main Page Widget (Android-only) --- class DeviceCompatibilityPage extends StatefulWidget { const DeviceCompatibilityPage({super.key}); @override State createState() => _DeviceCompatibilityPageState(); } class _DeviceCompatibilityPageState extends State { int score = 0; List> details = []; bool isLoading = true; bool get _isAndroid => !kIsWeb && defaultTargetPlatform == TargetPlatform.android; @override void initState() { super.initState(); if (_isAndroid) { _initializePage(); } else { // منصّة غير أندرويد: لا تعمل أي تحليلات setState(() => isLoading = false); } } Future _initializePage() async { final result = await DeviceAnalyzer().analyzeDevice(); if (!mounted) return; setState(() { score = result['score']; details = List>.from(result['details']); isLoading = false; }); } Color _getColorForScore(int value) { if (value >= 80) return Colors.teal; if (value >= 60) return Colors.orange.shade700; return Colors.red.shade600; } String _getScoreMessage(int value) { if (value >= 80) return "جهازك يقدم أداءً ممتازاً"; if (value >= 60) return "جهازك جيد ومناسب جداً"; if (value >= 40) return "متوافق، قد تلاحظ بعض البطء"; return "قد لا يعمل التطبيق بالشكل الأمثل"; } @override Widget build(BuildContext context) { // حظر الصفحة على غير أندرويد if (!_isAndroid) { return Scaffold( backgroundColor: const Color(0xFFF7F8FC), appBar: AppBar( title: const Text("توافق الجهاز", style: TextStyle( color: Colors.black87, fontWeight: FontWeight.bold)), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, iconTheme: const IconThemeData(color: Colors.black87), ), body: Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.phone_iphone, size: 56, color: Colors.grey), const SizedBox(height: 12), const Text("هذه الصفحة متاحة لأجهزة أندرويد فقط", style: TextStyle(fontSize: 16)), const SizedBox(height: 8), ElevatedButton( onPressed: () => Get.back(), child: const Text("رجوع"), ), ], ), ), ), ); } return Scaffold( backgroundColor: const Color(0xFFF7F8FC), appBar: AppBar( title: const Text("توافق الجهاز", style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold)), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, iconTheme: const IconThemeData(color: Colors.black87), ), body: isLoading ? const Center(child: CircularProgressIndicator(color: Colors.teal)) : Column( children: [ _buildScoreHeader(), Expanded( child: ListView.builder( padding: const EdgeInsets.only(top: 10, bottom: 20), itemCount: details.length, itemBuilder: (context, i) => CompatibilityDetailCard(detail: details[i]), ), ), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 24), child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.teal, minimumSize: const Size(double.infinity, 50), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), elevation: 0, ), onPressed: () => Get.back(), child: const Text("المتابعة إلى التطبيق", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white)), ), ), ], ), ); } /// الهيدر Widget _buildScoreHeader() { return Container( margin: const EdgeInsets.symmetric(horizontal: 16), height: 220, child: Stack( alignment: Alignment.center, children: [ PieChart( PieChartData( sectionsSpace: 4, centerSpaceRadius: 80, startDegreeOffset: -90, sections: [ PieChartSectionData( color: _getColorForScore(score), value: score.toDouble(), title: '', radius: 25), PieChartSectionData( color: Colors.grey.shade200, value: (100 - score).toDouble().clamp(0, 100), title: '', radius: 25), ], ), ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("$score%", style: TextStyle( fontSize: 52, fontWeight: FontWeight.bold, color: _getColorForScore(score))), const SizedBox(height: 4), Text(_getScoreMessage(score), textAlign: TextAlign.center, style: TextStyle( color: Colors.grey.shade700, fontSize: 16, fontWeight: FontWeight.w500)), ], ), ], ), ); } } ================================================== FILE PATH: ./lib/print.dart ================================================== import 'dart:developer' as developer; class Log { Log._(); static void print(String value, {StackTrace? stackTrace}) { developer.log(value, name: 'LOG', stackTrace: stackTrace); } static Object? inspect(Object? object) { return developer.inspect(object); } } ================================================== FILE PATH: ./lib/splash_screen_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'controller/home/splash_screen_controlle.dart'; import 'main.dart'; class SplashScreen extends StatelessWidget { const SplashScreen({super.key}); @override Widget build(BuildContext context) { final SplashScreenController splashScreenController = Get.put(SplashScreenController()); final textTheme = Theme.of(context).textTheme; final size = MediaQuery.of(context).size; // A modern, elegant color palette const Color primaryDark = Color(0xFF0D1B2A); const Color secondaryDark = Color(0xFF1B263B); const Color accentColor = Color(0xFF4ECDC4); const Color textColor = Colors.white; return Scaffold( body: Container( width: double.infinity, height: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ primaryDark, secondaryDark, ], ), ), child: Stack( children: [ // Center-aligned animated content Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ // Logo with Scale and Fade animation ScaleTransition( scale: splashScreenController.animation, child: FadeTransition( opacity: splashScreenController.animation, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.95), boxShadow: [ BoxShadow( color: accentColor.withOpacity(0.2), blurRadius: 25, spreadRadius: 5, ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(100), child: Image.asset( 'assets/images/logo.gif', width: size.width * 0.3, // Responsive size height: size.width * 0.3, ), ), ), ), ), const SizedBox(height: 30), // App Name and Slogan with staggered animation _AnimatedText( text: 'Intaleq', // Your App Name animation: splashScreenController.animation, style: textTheme.headlineMedium?.copyWith( color: textColor, fontWeight: FontWeight.bold, letterSpacing: 3, ), beginOffset: const Offset(0, 0.5), ), const SizedBox(height: 12), _AnimatedText( text: 'Your Journey Begins Here'.tr, animation: splashScreenController.animation, style: textTheme.titleMedium?.copyWith( color: textColor.withOpacity(0.8), fontWeight: FontWeight.w300, ), beginOffset: const Offset(0, 0.8), startDelay: 0.2, // Start after the title ), ], ), ), // Bottom Version Info and Progress Bar Align( alignment: Alignment.bottomCenter, child: Padding( padding: EdgeInsets.only( bottom: size.height * 0.06, left: 40, right: 40, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Obx( () => ClipRRect( borderRadius: BorderRadius.circular(10), child: LinearProgressIndicator( value: splashScreenController.progress.value, backgroundColor: primaryDark.withOpacity(0.5), valueColor: const AlwaysStoppedAnimation(accentColor), minHeight: 6, ), ), ), const SizedBox(height: 20), GetBuilder( builder: (controller) => Text( 'Version: ${controller.packageInfo.isNotEmpty ? controller.packageInfo : '...'}', style: textTheme.bodySmall?.copyWith( color: textColor.withOpacity(0.5), letterSpacing: 1, ), ), ), ], ), ), ), ], ), ), ); } } /// A helper widget for creating staggered text animations. class _AnimatedText extends StatelessWidget { const _AnimatedText({ required this.animation, required this.text, required this.style, required this.beginOffset, this.startDelay = 0.0, }); final Animation animation; final String text; final TextStyle? style; final Offset beginOffset; final double startDelay; @override Widget build(BuildContext context) { return FadeTransition( opacity: CurvedAnimation( parent: animation, curve: Interval(startDelay, 1.0, curve: Curves.easeOut), ), child: SlideTransition( position: Tween( begin: beginOffset, end: Offset.zero, ).animate(CurvedAnimation( parent: animation, curve: Interval(startDelay, 1.0, curve: Curves.easeOut), )), child: Text(text, style: style), ), ); } } ================================================== FILE PATH: ./lib/onbording_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'constant/colors.dart'; import 'controller/auth/onboarding_controller.dart'; import 'models/model/onboarding_model.dart'; // The main PageView widget, now cleaner. class CustomSliderOnBoarding extends GetView { const CustomSliderOnBoarding({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return PageView.builder( controller: controller.pageController, onPageChanged: (val) { controller.onPageChanged(val); }, itemCount: onBoardingList.length, itemBuilder: (context, i) => OnBoardingPageContent( model: onBoardingList[i], ), ); } } // This is the new widget for the content of each onboarding page. class OnBoardingPageContent extends StatelessWidget { final OnBoardingModel model; const OnBoardingPageContent({Key? key, required this.model}) : super(key: key); @override Widget build(BuildContext context) { // Use the app's text theme for consistent styling final textTheme = Theme.of(context).textTheme; return Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const Spacer(flex: 2), // Pushes content down ClipRRect( borderRadius: BorderRadius.circular(20.0), // Rounded corners for the image child: Image.asset( model.image!, height: Get.width * 0.6, // Slightly larger image width: Get.width * 0.8, fit: BoxFit.cover, // BoxFit.cover prevents image distortion ), ), const Spacer(flex: 2), Text( model.title!, textAlign: TextAlign.center, style: textTheme.displayLarge?.copyWith( color: AppColor.primaryColor, fontWeight: FontWeight.bold, fontSize: 24, // Consistent font size ), ), const SizedBox(height: 16), Text( model.body!, textAlign: TextAlign.center, style: textTheme.titleMedium?.copyWith( color: AppColor.accentColor, height: 1.5, // Improved line spacing fontSize: 16), ), const Spacer(flex: 3), // Pushes the content up from the dots ], ), ); } } // The refined dot controller. class CustomDotControllerOnBoarding extends StatelessWidget { const CustomDotControllerOnBoarding({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) => Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ...List.generate( onBoardingList.length, (index) => AnimatedContainer( margin: const EdgeInsets.only(right: 8), // Increased spacing duration: const Duration(milliseconds: 400), width: controller.currentPage == index ? 25 : 8, // More distinct width change height: 8, decoration: BoxDecoration( // Use a lighter color for inactive dots color: controller.currentPage == index ? AppColor.primaryColor : AppColor.primaryColor.withOpacity(0.3), borderRadius: BorderRadius.circular(10), ), ), ) ], ), ); } } ================================================== FILE PATH: ./lib/firebase_options.dart ================================================== // File generated by FlutterFire CLI. // ignore_for_file: type=lint import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform; /// Default [FirebaseOptions] for use with your Firebase apps. /// /// Example: /// ```dart /// import 'firebase_options.dart'; /// // ... /// await Firebase.initializeApp( /// options: DefaultFirebaseOptions.currentPlatform, /// ); /// ``` class DefaultFirebaseOptions { static FirebaseOptions get currentPlatform { if (kIsWeb) { throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for web - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); } switch (defaultTargetPlatform) { case TargetPlatform.android: return android; case TargetPlatform.iOS: return ios; case TargetPlatform.macOS: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for macos - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); case TargetPlatform.windows: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for windows - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); case TargetPlatform.linux: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for linux - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); default: throw UnsupportedError( 'DefaultFirebaseOptions are not supported for this platform.', ); } } static const FirebaseOptions android = FirebaseOptions( apiKey: 'AIzaSyCFsWBqvkXzk1Gb-bCGxwqTwJQKIeHjH64', appId: '1:1086900987150:android:e3daebe53bf691de77a35f', messagingSenderId: '1086900987150', projectId: 'intaleq-d48a7', storageBucket: 'intaleq-d48a7.firebasestorage.app', ); static const FirebaseOptions ios = FirebaseOptions( apiKey: 'AIzaSyAwG09AeehwBfktpKKJwCKQOtEUpHtr-p0', appId: '1:1086900987150:ios:4de021170777304677a35f', messagingSenderId: '1086900987150', projectId: 'intaleq-d48a7', storageBucket: 'intaleq-d48a7.firebasestorage.app', androidClientId: '1086900987150-060srlmdjocdcav377rbur4ka14m90b7.apps.googleusercontent.com', iosClientId: '1086900987150-litln2luehoflug5ild2vfkc9fh1mcfs.apps.googleusercontent.com', iosBundleId: 'com.example.intaleqDriver', ); } ================================================== FILE PATH: ./lib/main.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'constant/api_key.dart'; import 'constant/info.dart'; import 'constant/notification.dart'; import 'controller/firebase/firbase_messge.dart'; import 'controller/firebase/local_notification.dart'; import 'controller/functions/add_error.dart'; import 'controller/functions/battery_status.dart'; import 'controller/functions/crud.dart'; import 'controller/functions/encrypt_decrypt.dart'; import 'controller/functions/secure_storage.dart'; import 'controller/local/local_controller.dart'; import 'controller/local/translations.dart'; import 'firebase_options.dart'; import 'models/db_sql.dart'; import 'print.dart'; import 'splash_screen_page.dart'; import 'views/home/Captin/orderCaptin/order_request_page.dart'; import 'views/home/Captin/driver_map_page.dart'; import 'views/home/Captin/orderCaptin/order_over_lay.dart'; final box = GetStorage(); const storage = FlutterSecureStorage(); DbSql sql = DbSql.instance; final GlobalKey navigatorKey = GlobalKey(); const platform = MethodChannel('com.example.intaleq_driver/app_control'); /// تهيئة Firebase بوعي لمنع تهيئة مكرّرة على أندرويد (isolates متعددة) Future initFirebaseIfNeeded() async { if (Firebase.apps.isEmpty) { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform); } else { Firebase.app(); } } /// ============ Handlers: Background ============ @pragma('vm:entry-point') Future backgroundMessageHandler(RemoteMessage message) async { WidgetsFlutterBinding.ensureInitialized(); await initFirebaseIfNeeded(); await GetStorage.init(); if (!Get.isRegistered()) { Get.put(NotificationController()); } if (!Get.isRegistered()) { Get.put(FirebaseMessagesController()); } if (!await FlutterOverlayWindow.isPermissionGranted()) { Log.print("Overlay permission not granted; showing only notification."); } if (Platform.isAndroid) { String category = message.data['category'] ?? ''; if (message.notification != null) { Log.print('message.notification!.title: ${message.notification!.title}'); if (category == 'Order' || category == 'OrderSpeed') { final myListString = message.data['DriverList'] ?? '[]'; Log.print('myListString: $myListString'); List myList; try { myList = jsonDecode(myListString) as List; } catch (e) { Log.print('Error decoding JSON: $e'); myList = []; } final isOverlayActive = await FlutterOverlayWindow.isActive(); if (isOverlayActive) { await FlutterOverlayWindow.shareData(myList); } else { await FlutterOverlayWindow.showOverlay( enableDrag: true, flag: OverlayFlag.focusPointer, positionGravity: PositionGravity.auto, height: WindowSize.matchParent, width: WindowSize.matchParent, startPosition: const OverlayPosition(0, -30), ); await FlutterOverlayWindow.shareData(myList); } NotificationController().showNotification( message.notification!.title.toString(), message.notification!.body.toString(), 'order', myListString, ); } else { FirebaseMessagesController().fireBaseTitles(message); } } } } @pragma('vm:entry-point') void notificationTapBackground(NotificationResponse notificationResponse) { Log.print('Notification tapped in background!'); NotificationController().handleNotificationResponse(notificationResponse); } /// ============ Entrypoint: Overlay ============ @pragma('vm:entry-point') void overlayMain() async { WidgetsFlutterBinding.ensureInitialized(); await GetStorage.init(); // await initFirebaseIfNeeded(); if (!Get.isRegistered()) { Get.put(NotificationController()); } runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: OrderOverlay(), )); } /// إغلاق الـ Overlay عند الحاجة Future closeOverLay() async { final isOverlayActive = await FlutterOverlayWindow.isActive(); if (isOverlayActive) { await FlutterOverlayWindow.closeOverlay(); } } /// ============ Entrypoint: App ============ void main() { runZonedGuarded(() async { WidgetsFlutterBinding.ensureInitialized(); await initFirebaseIfNeeded(); await WakelockPlus.enable(); await GetStorage.init(); await initializeDateFormatting(); Stripe.publishableKey = AK.publishableKeyStripe; await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); // سجل الهاندلر تبع رسائل الخلفية (لازم يكون Top-Level ومع @pragma) FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); runApp(const MyApp()); }, (error, stack) { // ==== START: ERROR FILTER ==== final errorString = error.toString(); // اطبع كل شيء محلياً // (يمكنك استبدال print بـ Log.print إن رغبت) print("Caught Dart error: $error"); print(stack); // تجاهُل بعض الأخطاء المعروفة final isIgnoredError = errorString.contains('PERMISSION_DENIED') || errorString.contains('FormatException') || errorString.contains('Null check operator used on a null value'); if (!isIgnoredError) { // أرسل فقط ما ليس ضمن قائمة التجاهل CRUD.addError(error.toString(), stack.toString(), 'main'); } else { print("Ignoring error and not sending to server: $errorString"); } // ==== END: ERROR FILTER ==== }); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _initApp(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } Future _initApp() async { try { if (!Get.isRegistered()) { Get.put(NotificationController()); } if (!Get.isRegistered()) { Get.put(FirebaseMessagesController()).getToken(); } await FirebaseMessaging.instance.requestPermission(); // يمكن أيضاً تفعيل foreground presentation options هنا لو احتجت await NotificationController().initNotifications(); // Generate a random index to pick a message final random = Random(); final randomMessage = syrianDriverMessages[random.nextInt(syrianDriverMessages.length)]; // Schedule the notification with the random message NotificationController().scheduleNotificationsForSevenDays( randomMessage.split(':')[0], randomMessage.split(':')[1], "tone1", ); } catch (e) { Log.print("Error during _initApp: $e"); } } @override Widget build(BuildContext context) { final LocaleController localController = Get.put(LocaleController()); return GetMaterialApp( navigatorKey: navigatorKey, title: AppInformation.appName, translations: MyTranslation(), debugShowCheckedModeBanner: false, locale: localController.language, theme: localController.appTheme, initialRoute: '/', getPages: [ GetPage(name: '/', page: () => SplashScreen()), GetPage(name: '/order-page', page: () => OrderRequestPage()), GetPage( name: '/passenger-location-map', page: () => PassengerLocationMapPage(), ), ], ); } } ================================================== FILE PATH: ./lib/models/db_sql.dart ================================================== import 'package:sefer_driver/constant/table_names.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class DbSql { static final DbSql instance = DbSql._(); static Database? _database; DbSql._(); Future get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future _initDatabase() async { String path = join(await getDatabasesPath(), 'my_database.db'); return await openDatabase( path, version: 3, onCreate: (db, version) async => await _createTables(db), onUpgrade: (db, oldVersion, newVersion) async => await _createTables(db), ); } Future _createTables(Database db) async { await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.carLocations}( id INTEGER PRIMARY KEY AUTOINCREMENT, driver_id TEXT, latitude REAL, longitude REAL, created_at TEXT, updated_at TEXT ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.placesFavorite}( id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL, longitude REAL, name TEXT UNIQUE, rate TEXT ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.recentLocations}( id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL, longitude REAL, name TEXT , rate TEXT ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.driverOrdersRefuse}( id INTEGER PRIMARY KEY AUTOINCREMENT, order_id TEXT UNIQUE, created_at TEXT, driver_id TEXT ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.rideLocation}( id INTEGER PRIMARY KEY AUTOINCREMENT, order_id TEXT , created_at TEXT, lat TEXT, lng TEXT ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.faceDetectTimes}( id INTEGER PRIMARY KEY AUTOINCREMENT, faceDetectTimes INTEGER ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.behavior} ( id INTEGER PRIMARY KEY AUTOINCREMENT, driver_id TEXT, latitude REAL, longitude REAL, acceleration REAL, created_at TEXT, updated_at TEXT ); '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.captainNotification}( id INTEGER PRIMARY KEY AUTOINCREMENT, faceDetectTimes INTEGER ) '''); await db.execute(''' CREATE TABLE IF NOT EXISTS ${TableName.applyRideFromOverLay}( id INTEGER PRIMARY KEY AUTOINCREMENT, start_location_lat TEXT, start_location_lng TEXT, end_location_lat TEXT, end_location_lng TEXT, total_passenger TEXT, total_driver TEXT, duration_to_ride TEXT, distance TEXT, driver_id TEXT, passenger_id TEXT, passenger_name TEXT, passenger_token_fcm TEXT, passenger_phone TEXT, duration_by_passenger TEXT, distance_by_passenger TEXT, is_wallet_checked TEXT, driver_token TEXT, duration_to_passenger TEXT, ride_id TEXT, ride_timer_begin TEXT, driver_id_duplicate TEXT, duration_to_ride_duplicate TEXT, way_points TEXT, place_coordinate_0 TEXT, place_coordinate_1 TEXT, place_coordinate_2 TEXT, place_coordinate_3 TEXT, place_coordinate_4 TEXT, cost_for_driver TEXT, passenger_wallet_total TEXT, passenger_email TEXT, start_name_address TEXT, end_name_address TEXT, car_type TEXT, kazan TEXT, passenger_rate TEXT ) '''); } Future>> getAllData(String table) async { Database db = await instance.database; return await db.query(table); } Future>> getCustomQuery(String query) async { Database db = await instance.database; return await db.rawQuery(query); } Future insertData(Map map, String table) async { Database db = await instance.database; return await db.insert(table, map); } Future updateData(Map map, String table, int id) async { Database db = await instance.database; return await db.update(table, map, where: 'id = ?', whereArgs: [id]); } Future deleteData(String table, int id) async { Database db = await instance.database; return await db.delete(table, where: 'id = ?', whereArgs: [id]); } Future deleteAllData(String table) async { Database db = await instance.database; return await db.delete(table); } } ================================================== FILE PATH: ./lib/models/overlay_service.dart ================================================== import 'package:flutter/services.dart'; class OverlayMethodChannel { static const _channel = MethodChannel('com.sefer_driver/app_control'); static Future bringToForeground() async { try { await _channel.invokeMethod('bringToForeground'); } on PlatformException catch (e) { print('Error bringing app to foreground: $e'); } } } ================================================== FILE PATH: ./lib/models/model/order_data.dart ================================================== // lib/models/model/order_data.dart class OrderData { final String customerName; final String customerToken; final double tripDistanceKm; // The total trip distance in kilometers final String price; final String startLocationAddress; final String endLocationAddress; final double distanceToPassengerKm; // The distance to the passenger in kilometers final int tripDurationMinutes; // Total trip duration in minutes (rounded up) final int durationToPassengerMinutes; // Duration to reach the passenger in minutes (rounded up) final String rideType; final String orderId; final String passengerId; final String passengerRate; final String? rawStartCoordinates; final String? rawEndCoordinates; OrderData({ required this.customerName, required this.customerToken, required this.tripDistanceKm, required this.price, required this.startLocationAddress, required this.endLocationAddress, required this.distanceToPassengerKm, required this.tripDurationMinutes, required this.durationToPassengerMinutes, required this.rideType, required this.orderId, required this.passengerId, required this.passengerRate, this.rawStartCoordinates, this.rawEndCoordinates, }); // --- NEW: Factory constructor to create an instance from a Map --- // This is the missing method that was causing the error. factory OrderData.fromMap(Map map) { return OrderData( // For strings, provide a default value in case the map key is null customerName: map['customerName']?.toString() ?? 'Unknown Customer', customerToken: map['customerToken']?.toString() ?? 'Unknown token', // For numbers, cast from 'num' to handle both int and double, with a default value tripDistanceKm: (map['tripDistanceKm'] as num?)?.toDouble() ?? 0.0, price: map['price']?.toString() ?? '0', startLocationAddress: map['startLocationAddress']?.toString() ?? 'Unknown Address', endLocationAddress: map['endLocationAddress']?.toString() ?? 'Unknown Address', distanceToPassengerKm: (map['distanceToPassengerKm'] as num?)?.toDouble() ?? 0.0, tripDurationMinutes: (map['tripDurationMinutes'] as num?)?.toInt() ?? 0, durationToPassengerMinutes: (map['durationToPassengerMinutes'] as num?)?.toInt() ?? 0, rideType: map['rideType']?.toString() ?? 'Unknown', orderId: map['orderId']?.toString() ?? 'N/A', passengerId: map['passengerId']?.toString() ?? 'N/A', passengerRate: map['passengerRate']?.toString() ?? 'N/A', // For nullable strings, direct access is fine as it returns null if the key doesn't exist rawStartCoordinates: map['rawStartCoordinates'], rawEndCoordinates: map['rawEndCoordinates'], ); } // A helper function to convert seconds to rounded-up minutes static int _secondsToRoundedUpMinutes(String secondsString) { final seconds = double.tryParse(secondsString) ?? 0.0; if (seconds <= 0) return 0; return (seconds / 60) .ceil(); // .ceil() rounds up (e.g., 0.1 minutes becomes 1 minute) } // Your existing factory for creating an instance from a List factory OrderData.fromList(List list) { double distanceToPassengerMeters = list.length > 12 ? (double.tryParse(list[12].toString()) ?? 0.0) : 0.0; return OrderData( customerName: list.length > 8 ? list[8].toString() : 'Unknown Customer', customerToken: list.length > 9 ? list[9].toString() : 'Unknown token', tripDistanceKm: list.length > 5 ? (double.tryParse(list[5].toString()) ?? 0.0) : 0.0, price: list.length > 2 ? list[2].toString().split('.')[0] : '0', startLocationAddress: list.length > 29 ? list[29].toString() : 'Unknown Address', endLocationAddress: list.length > 30 ? list[30].toString() : 'Unknown Address', distanceToPassengerKm: distanceToPassengerMeters / 1000.0, // Convert meters to kilometers tripDurationMinutes: list.length > 4 ? _secondsToRoundedUpMinutes(list[4].toString()) : 0, durationToPassengerMinutes: list.length > 15 ? _secondsToRoundedUpMinutes(list[15].toString()) : 0, rideType: list.length > 31 ? _getRideType(list[31].toString()) : 'Unknown', orderId: list.length > 16 ? list[16].toString() : 'N/A', passengerId: list.length > 7 ? list[7].toString() : 'N/A', passengerRate: list.length > 33 ? list[33].toString() : 'N/A', rawStartCoordinates: list.isNotEmpty ? list[0].toString() : null, rawEndCoordinates: list.length > 1 ? list[1].toString() : null, ); } static String _getRideType(String type) { switch (type) { case 'Comfort': return '‏كمفورت ❄️'; case 'Lady': return '‏ليدي 👩'; case 'Speed': return '‏‏‏سبيد 🔻'; case 'Mashwari': return '‏مشواري'; case 'Rayeh Gai': return 'رايح جاي'; default: return type; } } // Getter to parse start coordinates Map? get startCoordinates { if (rawStartCoordinates == null) return null; final parts = rawStartCoordinates!.split(','); if (parts.length == 2) { return { 'lat': double.tryParse(parts[0].trim()), 'lng': double.tryParse(parts[1].trim()) }; } return null; } // Getter to parse end coordinates Map? get endCoordinates { if (rawEndCoordinates == null) return null; final parts = rawEndCoordinates!.split(','); if (parts.length == 2) { return { 'lat': double.tryParse(parts[0].trim()), 'lng': double.tryParse(parts[1].trim()) }; } return null; } // Your existing method to convert the object TO a Map. // This is used to pass the data from the overlay to the main app. Map toMap() { return { 'customerName': customerName, 'tripDistanceKm': tripDistanceKm, 'price': price, 'startLocationAddress': startLocationAddress, 'endLocationAddress': endLocationAddress, 'distanceToPassengerKm': distanceToPassengerKm, 'tripDurationMinutes': tripDurationMinutes, 'durationToPassengerMinutes': durationToPassengerMinutes, 'rideType': rideType, 'orderId': orderId, 'passengerId': passengerId, 'passengerRate': passengerRate, 'rawStartCoordinates': rawStartCoordinates, 'rawEndCoordinates': rawEndCoordinates, }; } } ================================================== FILE PATH: ./lib/models/model/onboarding_model.dart ================================================== import 'package:get/get.dart'; List onBoardingList = [ OnBoardingModel( title: 'Welcome to Intaleq!'.tr, image: 'assets/images/on1.png', body: 'Intaleq is the ride-hailing app that is safe, reliable, and accessible.' .tr, ), OnBoardingModel( title: 'Get to your destination quickly and easily.'.tr, image: 'assets/images/on2.png', body: 'With Intaleq, you can get a ride to your destination in minutes.'.tr, ), OnBoardingModel( title: 'Enjoy a safe and comfortable ride.'.tr, image: 'assets/images/on3.png', body: 'Intaleq is committed to safety, and all of our captains are carefully screened and background checked.' .tr, ), ]; class OnBoardingModel { final String? title; final String? image; final String? body; OnBoardingModel({this.body, this.title, this.image}); } ================================================== FILE PATH: ./lib/models/model/locations.dart ================================================== class CarLocationModel { String id; String driverId; double latitude; double heading; double speed; double longitude; DateTime createdAt; DateTime updatedAt; CarLocationModel({ required this.id, required this.driverId, required this.latitude, required this.longitude, required this.heading, required this.speed, required this.createdAt, required this.updatedAt, }); factory CarLocationModel.fromJson(Map json) { return CarLocationModel( id: json['id'], driverId: json['driver_id'], latitude: double.parse(json['latitude'].toString()), longitude: double.parse(json['longitude'].toString()), heading: double.parse(json['heading'].toString()), speed: double.parse(json['speed'].toString()), createdAt: DateTime.parse(json['created_at']), updatedAt: DateTime.parse(json['updated_at']), ); } } ================================================== FILE PATH: ./lib/models/model/driver/rides_summary_model.dart ================================================== class MonthlyDataModel { int day; int totalDuration; MonthlyDataModel({required this.day, required this.totalDuration}); factory MonthlyDataModel.fromJson(Map json) => MonthlyDataModel( day: int.parse(json['day'].toString().split('-')[2]), totalDuration: int.parse(json['total_duration'].toString().split(':')[0])); } class MonthlyRideModel { int day; int countRide; int totalCount; MonthlyRideModel( {required this.day, required this.countRide, required this.totalCount}); factory MonthlyRideModel.fromJson(Map json) => MonthlyRideModel( day: int.parse(json['day'].toString().split('-')[2]), countRide: int.parse(json['countRide'].toString()), totalCount: int.parse(json['totalCount'].toString()), ); } class MonthlyPriceDriverModel { int day; // int price; double pricePerDay; MonthlyPriceDriverModel({required this.day, required this.pricePerDay}); factory MonthlyPriceDriverModel.fromJson(Map json) => MonthlyPriceDriverModel( day: int.parse(json['day'].toString().split('-')[2]), // price: int.parse(json['price'].toString()), pricePerDay: double.parse(json['pricePerDay'].toString()), ); } ================================================== FILE PATH: ./lib/models/model/admin/passenger_model.dart ================================================== class Passenger { String id; String phone; String email; String gender; String status; String birthdate; String site; String firstName; String lastName; String sosPhone; String education; String employmentType; String maritalStatus; String createdAt; String updatedAt; int countPassenger; int countFeedback; double ratingPassenger; int countDriverRate; int countPassengerCancel; double passengerAverageRating; int countPassengerRate; int countPassengerRide; Passenger({ required this.id, required this.phone, required this.email, required this.gender, required this.status, required this.birthdate, required this.site, required this.firstName, required this.lastName, required this.sosPhone, required this.education, required this.employmentType, required this.maritalStatus, required this.createdAt, required this.updatedAt, required this.countPassenger, required this.countFeedback, required this.ratingPassenger, required this.countDriverRate, required this.countPassengerCancel, required this.passengerAverageRating, required this.countPassengerRate, required this.countPassengerRide, }); factory Passenger.fromJson(Map json) { return Passenger( id: json['id'], phone: json['phone'], email: json['email'], gender: json['gender'], status: json['status'], birthdate: json['birthdate'], site: json['site'], firstName: json['first_name'], lastName: json['last_name'], sosPhone: json['sosPhone'], education: json['education'], employmentType: json['employmentType'], maritalStatus: json['maritalStatus'], createdAt: json['created_at'], updatedAt: json['updated_at'], countPassenger: json['countPassenger'], countFeedback: json['countFeedback'], ratingPassenger: json['ratingPassenger'].toDouble(), countDriverRate: json['countDriverRate'], countPassengerCancel: json['countPassengerCancel'], passengerAverageRating: json['passengerAverageRating'].toDouble(), countPassengerRate: json['countPassengerRate'], countPassengerRide: json['countPassengerRide'], ); } } ================================================== FILE PATH: ./lib/models/model/admin/monthly_ride.dart ================================================== class MonthlyDataModel { final int year; final int month; final int day; final int ridesCount; MonthlyDataModel({ required this.year, required this.month, required this.day, required this.ridesCount, }); factory MonthlyDataModel.fromJson(Map json) => MonthlyDataModel( year: json['year'] as int, month: json['month'] as int, day: json['day'] as int, ridesCount: json['rides_count'] as int, ); } ================================================== FILE PATH: ./lib/controller/home/points_for_rider_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:sefer_driver/constant/style.dart'; import '../../constant/api_key.dart'; import '../../constant/links.dart'; import '../functions/crud.dart'; import '../functions/location_controller.dart'; class PointsForRiderController extends GetxController { List locations = []; String hintTextDestinationPoint = 'Search for your destination'.tr; TextEditingController placeStartController = TextEditingController(); void addLocation(String location) { locations.add(location); update(); } void getTextFromList(String location) { locations.add(location); update(); Get.back(); } void removeLocation(int index) { locations.removeAt(index); update(); } void onReorder(int oldIndex, int newIndex) { if (newIndex > oldIndex) { newIndex -= 1; update(); } final item = locations.removeAt(oldIndex); locations.insert(newIndex, item); update(); } } class LocationModel { String name; double lat, lon; LocationModel({required this.name, required this.lat, required this.lon}); } class WayPointController extends GetxController { // A list of text editing controllers for each text field // final textFields = [TextEditingController()].obs; List wayPoints = []; List> placeListResponse = []; double wayPointHeight = 400; String hintTextDestinationPoint = 'Search for your destination'.tr; TextEditingController textSearchCotroller = TextEditingController(); // A list of places corresponding to each text field final places = []; final hintTextPointList = []; late LatLng myLocation; void addWayPoints() { String wayPoint = 'Add a Stop'.tr; if (wayPoints.length < 5) { wayPoints.add(wayPoint); update(); } else { Get.defaultDialog( title: 'This is most WayPoints', titleStyle: AppStyle.title, middleText: ''); } update(); } void removeTextField(int index) { wayPoints.removeAt(index); update(); } // A method to reorder the text fields and the places void reorderTextFields(int oldIndex, int newIndex) { if (newIndex > oldIndex) { newIndex -= 1; } final wayPoint = wayPoints.removeAt(oldIndex); wayPoints.insert(newIndex, wayPoint); update(); } void updatePlace(int index, String input) async { var url = '${AppLink.googleMapsLink}place/nearbysearch/json?keyword=$input&location=${myLocation.latitude},${myLocation.longitude}&radius=50000&language=en&key=${AK.mapAPIKEY.toString()}'; var response = await CRUD().getGoogleApi(link: url, payload: {}); // final place = input; // if (index == 0) { List newList = []; placeListResponse.add(newList); newList = response['results']; placeListResponse[index].add(newList); update(); // } update(); } @override void onInit() { Get.put(LocationController()); addWayPoints(); myLocation = Get.find().myLocation; super.onInit(); } } class PlaceList extends StatelessWidget { // Get the controller instance final controller = Get.put(WayPointController()); @override Widget build(BuildContext context) { // Use the Obx widget to rebuild the widget when the controller changes return Obx(() { // Use the ListView widget to display the list of places return ListView( // The children of the list are the places children: [ // Loop through the places in the controller for (final place in controller.places) // Create a text widget for each place Text( // Use the place as the text place, // Add some style and padding style: const TextStyle(fontSize: 18.0), ), ], ); }); } } ================================================== FILE PATH: ./lib/controller/home/menu_controller.dart ================================================== import 'package:get/get.dart'; class MyMenuController extends GetxController { bool isDrawerOpen = true; void getDrawerMenu() { if (isDrawerOpen == true) { isDrawerOpen = false; } else { isDrawerOpen = true; } update(); } } ================================================== FILE PATH: ./lib/controller/home/splash_screen_controlle.dart ================================================== import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/views/auth/captin/login_captin.dart'; import 'package:sefer_driver/views/home/on_boarding_page.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; import '../../print.dart'; import '../functions/encrypt_decrypt.dart'; import '../functions/secure_storage.dart'; // Assuming you have a home page to navigate to after successful login. // If not, you might need to adjust the navigation target. // import 'package:sefer_driver/views/home/home_page.dart'; class SplashScreenController extends GetxController with GetTickerProviderStateMixin { late AnimationController _animationController; late Animation animation; final progress = 0.0.obs; Timer? _progressTimer; String packageInfo = ''; @override void onInit() { super.onInit(); _setupAnimations(); _initializeAndNavigate(); } void _setupAnimations() { _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1500), ); animation = CurvedAnimation(parent: _animationController, curve: Curves.easeInOut); _animationController.forward(); } /// This is the core function that initializes the app. /// It runs two tasks simultaneously and navigates only when necessary. Future _initializeAndNavigate() async { // Start getting package info, no need to wait for it. _getPackageInfo(); const minSplashDurationMs = 4000; _animateProgressBar(minSplashDurationMs); // Define the two concurrent tasks final minDuration = Future.delayed(const Duration(milliseconds: minSplashDurationMs)); final navigationTargetFuture = _getNavigationTarget(); // Wait for both tasks to complete await Future.wait([minDuration, navigationTargetFuture]); // The future now returns a nullable Widget (Widget?) final Widget? targetPage = await navigationTargetFuture; // *** FIX: Only navigate if the targetPage is not null. *** // This prevents navigating again if the login function already handled it. if (targetPage != null) { Get.off(() => targetPage, transition: Transition.fadeIn, duration: const Duration(milliseconds: 500)); } else { Log.print( "Navigation was handled internally by the login process. Splash screen will not navigate."); } } /// Animates the progress bar over a given duration. void _animateProgressBar(int totalMilliseconds) { const interval = 50; int elapsed = 0; _progressTimer?.cancel(); _progressTimer = Timer.periodic(const Duration(milliseconds: interval), (timer) { elapsed += interval; progress.value = (elapsed / totalMilliseconds).clamp(0.0, 1.0); if (elapsed >= totalMilliseconds) { timer.cancel(); } }); } /// Determines the correct page to navigate to, or returns null if navigation /// is expected to be handled by an internal process (like login). Future _getNavigationTarget() async { try { // ... (التحقق من OnBoarding) final isDriverDataAvailable = box.read(BoxName.phoneDriver) != null; // final isPhoneVerified = box.read(BoxName.phoneVerified).toString() == '1'; // <-- ⛔️ تم حذف هذا السطر final loginController = Get.put(LoginDriverController()); // ✅ --- (الحل) --- // تم حذف التحقق من "isPhoneVerified" // هذا يسمح لـ "loginWithGoogleCredential" بتحديد الحالة والتوجيه الصحيح // (إلى Home أو DriverVerificationScreen أو PhoneNumberScreen) if (isDriverDataAvailable) { Log.print('المستخدم مسجل. جارٍ تهيئة الجلسة...'); // الخطوة 1: ضمان جلب الـ JWT أولاً // (هذا هو الكود الذي كان في main.dart) final AppInitializer initializer = AppInitializer(); await initializer.initializeApp(); await EncryptionHelper.initialize(); // انتظر حتى ينتهي جلب الـ JWT Log.print('تم جلب الـ JWT. جارٍ تسجيل الدخول ببيانات جوجل...'); // الخطوة 2: الآن قم بتسجيل الدخول وأنت متأكد أن الـ JWT موجود // يجب تعديل "loginWithGoogleCredential" لتعيد "bool" (نجاح/فشل) await loginController.loginWithGoogleCredential( box.read(BoxName.driverID).toString(), box.read(BoxName.emailDriver).toString(), ); // إذا نجح تسجيل الدخول (سواء لـ Home أو لـ DriverVerification) // فإن "loginWithGoogleCredential" تقوم بالتوجيه بنفسها // ونحن نُرجع "null" هنا لمنع "SplashScreen" من التوجيه مرة أخرى. } else { Log.print('مستخدم غير مسجل. اذهب لصفحة الدخول.'); return LoginCaptin(); } } catch (e) { Log.print("Error during navigation logic: $e"); // أي خطأ فادح (مثل خطأ في جلب الـ JWT) سيعيدك للدخول return LoginCaptin(); } } Future _getPackageInfo() async { try { final info = await PackageInfo.fromPlatform(); packageInfo = info.version; await box.write(BoxName.packagInfo, packageInfo); update(); // To update any UI element that might be listening } catch (e) { Log.print("Could not get package info: $e"); packageInfo = '1.0.0'; // Default value await box.write(BoxName.packagInfo, packageInfo); } } @override void onClose() { _progressTimer?.cancel(); _animationController.dispose(); super.onClose(); } } ================================================== FILE PATH: ./lib/controller/home/captin/navigation_service.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_polyline_algorithm/google_polyline_algorithm.dart'; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/functions/tts.dart'; import '../../../main.dart'; /// Handles map-related logic: fetching routes, drawing polylines, and managing markers. class NavigationService extends GetxService { final CRUD _crud = CRUD(); final TextToSpeechController _tts = Get.put(TextToSpeechController()); final RxSet markers = {}.obs; final RxSet polylines = {}.obs; final RxString currentInstruction = "".obs; BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor passengerIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker; @override void onInit() { super.onInit(); _loadCustomIcons(); } void _loadCustomIcons() async { carIcon = await _createBitmapDescriptor('assets/images/car.png'); passengerIcon = await _createBitmapDescriptor('assets/images/picker.png'); startIcon = await _createBitmapDescriptor('assets/images/A.png'); endIcon = await _createBitmapDescriptor('assets/images/b.png'); } Future _createBitmapDescriptor(String assetName) { return BitmapDescriptor.fromAssetImage( ImageConfiguration( size: const Size(30, 35), devicePixelRatio: Get.pixelRatio), assetName, ); } Future?> getRoute({ required LatLng origin, required LatLng destination, }) async { final url = '${AppLink.googleMapsLink}directions/json?language=${box.read(BoxName.lang)}&destination=${destination.latitude},${destination.longitude}&origin=${origin.latitude},${origin.longitude}&key=${AK.mapAPIKEY}'; final response = await _crud.getGoogleApi(link: url, payload: {}); if (response != null && response['routes'].isNotEmpty) { return response['routes'][0]; } return null; } void drawRoute(Map routeData, {Color color = Colors.blue}) { final pointsString = routeData["overview_polyline"]["points"]; final points = decodePolyline(pointsString) .map((p) => LatLng(p[0].toDouble(), p[1].toDouble())) .toList(); final polyline = Polyline( polylineId: PolylineId(routeData["summary"] ?? DateTime.now().toString()), points: points, width: 8, color: color, ); polylines.add(polyline); } void updateCarMarker(LatLng position, double heading) { markers.removeWhere((m) => m.markerId.value == 'MyLocation'); markers.add( Marker( markerId: MarkerId('MyLocation'.tr), position: position, icon: carIcon, rotation: heading, anchor: const Offset(0.5, 0.5), flat: true, ), ); } void setInitialMarkers( LatLng passengerLocation, LatLng passengerDestination) { markers.clear(); markers.add(Marker( markerId: const MarkerId('passengerLocation'), position: passengerLocation, icon: passengerIcon, )); markers.add(Marker( markerId: const MarkerId('passengerDestination'), position: passengerDestination, icon: endIcon, )); } void clearRoutes() { polylines.clear(); currentInstruction.value = ""; } } ================================================== FILE PATH: ./lib/controller/home/captin/home_captain_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'dart:ui' as ui; // للألوان // import 'package:google_maps_flutter/google_maps_flutter.dart'; // import 'package:flutter_map/flutter_map.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; // import 'package:latlong2/latlong.dart' // as latlng; // هذا مهم جداً للتعامل مع إحداثيات OSM import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/home/captin/map_driver_controller.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/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; BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; 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; late 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 heatmapPolygons = {}; // سنستخدم Polygon لرسم المربعات على جوجل مابس // Inject the LocationController class // final locationController = Get.put(LocationController()); // الكود الصحيح final locationController = Get.find(); // 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; if (isHeatmapVisible) { await _fetchAndDrawHeatmap(); } else { heatmapPolygons.clear(); } update(); // تحديث الواجهة } // دالة جلب البيانات ورسمها Future _fetchAndDrawHeatmap() async { isLoading = true; update(); // استبدل هذا الرابط برابط ملف JSON الذي يولده كود PHP // مثال: https://your-domain.com/api/driver/heatmap_data.json final String jsonUrl = "https://rides.intaleq.xyz/intaleq/ride/heatmap/heatmap_data.json"; try { final response = await http.get(Uri.parse(jsonUrl)); if (response.statusCode == 200) { final List data = json.decode(response.body); _generateGoogleMapPolygons(data); } else { print("Failed to load heatmap data"); } } catch (e) { print("Error fetching heatmap: $e"); } finally { isLoading = false; update(); } } // تحويل البيانات إلى مربعات على خريطة جوجل void _generateGoogleMapPolygons(List data) { Set tempPolygons = {}; // نصف قطر المربع (تقريباً 0.0005 يعادل 50-60 متر، مما يعطي مربع 100 متر) // يجب أن يتناسب مع الـ precision المستخدم في PHP double offset = 0.005; for (var point in data) { double lat = double.parse(point['lat'].toString()); double lng = double.parse(point['lng'].toString()); int count = int.parse(point['count'].toString()); // تحديد اللون بناءً على الكثافة Color color; if (count >= 5) { color = Colors.red.withOpacity(0.5); // عالي جداً } else if (count >= 3) { color = Colors.orange.withOpacity(0.5); // متوسط } else { color = Colors.green.withOpacity(0.4); // منخفض } // إنشاء المربع tempPolygons.add(Polygon( polygonId: PolygonId("$lat-$lng"), points: [ LatLng(lat - offset, lng - offset), LatLng(lat + offset, lng - offset), LatLng(lat + offset, lng + offset), LatLng(lat - offset, lng + offset), ], fillColor: color, strokeColor: color.withOpacity(0.8), strokeWidth: 1, visible: true, )); } heatmapPolygons = tempPolygons; } void goToWalletFromConnect() { Get.back(); Get.back(); Get.to(() => WalletCaptainRefactored()); } void changeRideId() { rideId = 'rideId'; update(); } void addCustomCarIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 35), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/car.png', // mipmaps: false, ).then((value) { carIcon = value; update(); }); } String stringActiveDuration = ''; void onButtonSelected() { // totalPoints = Get.find().totalPoints; isActive = !isActive; if (isActive) { if (double.parse(totalPoints) > -30000) { locationController.startLocationUpdates(); HapticFeedback.heavyImpact(); // locationBackController.startBackLocation(); activeStartTime = DateTime.now(); activeTimer = Timer.periodic(const Duration(seconds: 1), (timer) { activeDuration = DateTime.now().difference(activeStartTime!); stringActiveDuration = formatDuration(activeDuration); update(); }); } else { locationController.stopLocationUpdates(); activeStartTime = null; activeTimer?.cancel(); savePeriod(activeDuration); activeDuration = Duration.zero; update(); } } else { locationController.stopLocationUpdates(); activeStartTime = null; activeTimer?.cancel(); savePeriod(activeDuration); activeDuration = Duration.zero; update(); } // } } 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> results = await sql.getCustomQuery(customQuery); countRefuse = results[0]['count'].toString(); update(); if (int.parse(countRefuse) > 3 || double.parse(totalPoints) <= -3000) { 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: () { Get.back(); Get.back(); })); } } catch (e) {} } void changeMapType() { mapType = !mapType; // heightButtomSheetShown = isButtomSheetShown == true ? 240 : 0; update(); } void changeMapTraffic() { mapTrafficON = !mapTrafficON; update(); } // late GoogleMapController mapHomeCaptainController; GoogleMapController? mapHomeCaptainController; // final locationController = Get.find(); // --- FIX 2: Smart Map Creation --- void onMapCreated(GoogleMapController controller) { mapHomeCaptainController = controller; // Check actual location before moving camera var currentLoc = locationController.myLocation; if (currentLoc.latitude != 0 && currentLoc.longitude != 0) { controller.animateCamera( CameraUpdate.newLatLng(currentLoc), ); } else { // Optional: Move to default city view instead of ocean controller.animateCamera( CameraUpdate.newLatLngZoom(myLocation, 10), ); } } void savePeriod(Duration period) { final periods = box.read>(BoxName.periods) ?? []; periods.add(period.inSeconds); box.write(BoxName.periods, periods); } Duration calculateTotalDuration() { final periods = box.read>(BoxName.periods) ?? []; Duration totalDuration = Duration.zero; for (dynamic periodInSeconds in periods) { final periodDuration = Duration(seconds: periodInSeconds); totalDuration += periodDuration; } return totalDuration; } void startPeriodicExecution() { Timer.periodic(const Duration(seconds: 30), (timer) async { await getCaptainDurationOnToday(); }); } void stopTimer() { timer?.cancel(); } getlocation() async { isLoading = true; update(); // This ensures we try to get a fix, but map doesn't crash if it fails await Get.find().getLocation(); var loc = Get.find().myLocation; if (loc.latitude != 0) { myLocation = loc; } 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; // إنعاش الخريطة عند العودة if (mapHomeCaptainController != null) { onMapCreated(mapHomeCaptainController!); } update(); } @override void onInit() async { // await locationBackController.requestLocationPermission(); Get.put(FirebaseMessagesController()); addToken(); await getlocation(); onButtonSelected(); getDriverRate(); addCustomCarIcon(); getKazanPercent(); getPaymentToday(); getCountRideToday(); getAllPayment(); startPeriodicExecution(); getCaptainWalletFromBuyPoints(); // onMapCreated(mapHomeCaptainController!); // totalPoints = Get.find().totalPoints.toString(); getRefusedOrderByCaptain(); box.write(BoxName.statusDriverLocation, 'off'); // 2. عدل الليسنر ليصبح مشروطاً locationController.addListener(() { // الشرط الذهبي: إذا كانت الصفحة غير نشطة أو الخريطة غير موجودة، لا تفعل شيئاً if (!isHomeMapActive || mapHomeCaptainController == null || isClosed) return; if (isActive) { // isActive الخاصة بالزر "متصل/غير متصل" var loc = locationController.myLocation; if (loc.latitude != 0 && loc.longitude != 0) { try { mapHomeCaptainController!.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( target: loc, zoom: 17.5, tilt: 50.0, bearing: locationController.heading, ), ), ); } catch (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 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(); } @override void dispose() { activeTimer?.cancel(); stopTimer(); mapHomeCaptainController?.dispose(); // Dispose controller super.dispose(); } } ================================================== FILE PATH: ./lib/controller/home/captin/contact_us_controller.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import '../../../constant/colors.dart'; import '../../functions/launch.dart'; class ContactUsController extends GetxController { final String phone1 = '+963992952235'; final String phone2 = '+963992952235'; final TimeOfDay workStartTime = const TimeOfDay(hour: 12, minute: 0); final TimeOfDay workEndTime = const TimeOfDay(hour: 19, minute: 0); bool _isWithinWorkTime(TimeOfDay now) { return (now.hour > workStartTime.hour || (now.hour == workStartTime.hour && now.minute >= workStartTime.minute)) && (now.hour < workEndTime.hour || (now.hour == workEndTime.hour && now.minute <= workEndTime.minute)); } void showContactDialog(BuildContext context) { TimeOfDay now = TimeOfDay.now(); showCupertinoModalPopup( context: context, builder: (context) => CupertinoActionSheet( title: Text('Contact Us'.tr), message: Text('Choose a contact option'.tr), actions: [ if (_isWithinWorkTime(now)) CupertinoActionSheetAction( child: Text(phone1), onPressed: () => makePhoneCall( phone1, ), ), if (_isWithinWorkTime(now)) CupertinoActionSheetAction( child: Text(phone2), onPressed: () => makePhoneCall(phone2), ), if (!_isWithinWorkTime(now)) CupertinoActionSheetAction( child: Text( 'Work time is from 10:00 - 17:00.\nYou can send a WhatsApp message or email.' .tr), onPressed: () => Navigator.pop(context), ), CupertinoActionSheetAction( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ const Icon( FontAwesome.whatsapp, color: AppColor.greenColor, ), Text('Send WhatsApp Message'.tr), ], ), onPressed: () => launchCommunication('whatsapp', phone1, 'Hello'.tr), ), CupertinoActionSheetAction( child: Text('Send Email'.tr), onPressed: () => launchCommunication('email', 'support@sefer.live', 'Hello'.tr), ), ], cancelButton: CupertinoActionSheetAction( child: Text('Cancel'.tr), onPressed: () => Navigator.pop(context), ), ), ); } } ================================================== FILE PATH: ./lib/controller/home/captin/order_request_controller.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/main.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'dart:math' as math; import '../../../constant/box_name.dart'; import '../../../print.dart'; import '../../functions/audio_controller.dart'; import '../../functions/crud.dart'; import '../../functions/encrypt_decrypt.dart'; import '../../functions/location_controller.dart'; import 'home_captain_controller.dart'; class OrderRequestController extends GetxController { double progress = 0; double progressSpeed = 0; int duration = 15; int durationSpeed = 20; int remainingTime = 0; int remainingTimeSpeed = 0; String countRefuse = '0'; bool applied = false; final locationController = Get.put(LocationController()); BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker; final arguments = Get.arguments; var myList; late int hours; late int minutes; GoogleMapController? mapController; // Make it nullable @override Future onInit() async { print('OrderRequestController onInit called'); await initializeOrderPage(); if (Platform.isAndroid) { bool isOverlayActive = await FlutterOverlayWindow.isActive(); if (isOverlayActive) { await FlutterOverlayWindow.closeOverlay(); } } addCustomStartIcon(); addCustomEndIcon(); startTimer( myList[6].toString(), myList[16].toString(), ); update(); super.onInit(); } // تعديل onClose للتأكد من التخلص من الخريطة والمؤقتات @override void onClose() { endTimer(); // إيقاف المؤقت mapController?.dispose(); // التخلص من خريطة الطلب super.onClose(); } late LatLngBounds bounds; late List pointsDirection; late String body; late double latPassengerLocation; late double lngPassengerLocation; late double lngPassengerDestination; late double latPassengerDestination; Future initializeOrderPage() async { final myListString = Get.arguments['myListString']; Log.print('myListString0000: ${myListString}'); if (Get.arguments['DriverList'] == null || Get.arguments['DriverList'].isEmpty) { myList = jsonDecode(myListString); Log.print('myList from myListString: ${myList}'); } else { myList = Get.arguments['DriverList']; Log.print('myList from DriverList: ${myList}'); } body = Get.arguments['body']; Duration durationToAdd = Duration(seconds: (double.tryParse(myList[4]) ?? 0).toInt()); hours = durationToAdd.inHours; minutes = (durationToAdd.inMinutes % 60).round(); startTimerSpeed(myList[6].toString(), body.toString()); // --- Using the provided logic for initialization --- var cords = myList[0].toString().split(','); var cordDestination = myList[1].toString().split(','); double? parseDouble(String value) { try { return double.parse(value); } catch (e) { Log.print("Error parsing value: $value"); return null; // or handle the error appropriately } } latPassengerLocation = parseDouble(cords[0]) ?? 0.0; lngPassengerLocation = parseDouble(cords[1]) ?? 0.0; latPassengerDestination = parseDouble(cordDestination[0]) ?? 0.0; lngPassengerDestination = parseDouble(cordDestination[1]) ?? 0.0; pointsDirection = [ LatLng(latPassengerLocation, lngPassengerLocation), LatLng(latPassengerDestination, lngPassengerDestination) ]; Log.print('pointsDirection: $pointsDirection'); calculateBounds(); update(); } void onMapCreated(GoogleMapController controller) { mapController = controller; animateCameraToBounds(); } void calculateBounds() { double minLat = math.min(latPassengerLocation, latPassengerDestination); double maxLat = math.max(latPassengerLocation, latPassengerDestination); double minLng = math.min(lngPassengerLocation, lngPassengerDestination); double maxLng = math.max(lngPassengerLocation, lngPassengerDestination); bounds = LatLngBounds( southwest: LatLng(minLat, minLng), northeast: LatLng(maxLat, maxLng), ); Log.print('Calculated Bounds: $bounds'); } void animateCameraToBounds() { if (mapController != null) { mapController!.animateCamera(CameraUpdate.newLatLngBounds(bounds, 80.0)); } else { Log.print('mapController is null, cannot animate camera.'); } } getRideDEtailsForBackgroundOrder(String rideId) async { await CRUD().get(link: AppLink.getRidesDetails, payload: { 'id': rideId, }); } void addCustomStartIcon() async { ImageConfiguration config = const ImageConfiguration(size: Size(30, 30)); BitmapDescriptor.asset( config, 'assets/images/A.png', ).then((value) { startIcon = value; update(); }); } void addCustomEndIcon() { ImageConfiguration config = const ImageConfiguration(size: Size(30, 30)); BitmapDescriptor.asset( config, 'assets/images/b.png', ).then((value) { endIcon = value; update(); }); } void changeApplied() { applied = true; update(); } double mpg = 0; calculateConsumptionFuel() { mpg = Get.find().fuelPrice / 12; } bool _timerActive = false; Future startTimer(String driverID, String orderID) async { _timerActive = true; for (int i = 0; i <= duration && _timerActive; i++) { await Future.delayed(const Duration(seconds: 1)); progress = i / duration; remainingTime = duration - i; update(); } if (remainingTime == 0 && _timerActive) { if (applied == false) { endTimer(); //refuseOrder(orderID); } } } void endTimer() { _timerActive = false; } void startTimerSpeed(String driverID, orderID) async { for (int i = 0; i <= durationSpeed; i++) { await Future.delayed(const Duration(seconds: 1)); progressSpeed = i / durationSpeed; remainingTimeSpeed = durationSpeed - i; update(); } if (remainingTimeSpeed == 0) { if (applied == false) { Get.back(); } } } addRideToNotificationDriverString( orderID, String startLocation, String endLocation, String date, String time, String price, String passengerId, String status, String carType, String passengerRate, String priceForPassenger, String distance, String duration, ) async { await CRUD().post(link: AppLink.addWaitingRide, payload: { 'id': (orderID), 'start_location': startLocation, 'end_location': endLocation, 'date': date, 'time': time, 'price': price, 'passenger_id': (passengerId), 'status': status, 'carType': carType, 'passengerRate': passengerRate, 'price_for_passenger': priceForPassenger, 'distance': distance, 'duration': duration, }); } } ================================================== FILE PATH: ./lib/controller/home/captin/behavior_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import '../../../constant/table_names.dart'; import '../../../main.dart'; import '../../../print.dart'; class DriverBehaviorController extends GetxController { Future>> getAllData() async { return await sql.getAllData(TableName.behavior); } var isLoading = false.obs; var overallScore = 100.0.obs; var lastTrips = [].obs; Future fetchDriverBehavior() async { isLoading.value = true; try { final response = await CRUD().get( link: AppLink.get_driver_behavior, payload: {"driver_id": box.read(BoxName.driverID).toString()}, ); if (response != 'failure') { final json = jsonDecode(response); overallScore.value = double.parse(json['message']['overall_behavior_score'].toString()); lastTrips.value = json['message']['last_10_trips']; } else { // Get.snackbar("Error", json['message'] ?? "Unknown error"); } } catch (e) { // Get.snackbar("Error", "Exception: $e"); Log.print('e: ${e}'); } finally { isLoading.value = false; } } Future> analyzeData() async { final data = await getAllData(); if (data.isEmpty) return {}; double maxSpeed = 0; double totalSpeed = 0; int hardBrakes = 0; double totalDistance = 0; // متغيرات للمقارنة مع النقطة السابقة double? prevLat, prevLng; DateTime? prevTime; // ترتيب البيانات حسب الوقت لضمان دقة الحساب (اختياري لكن مفضل) // data.sort((a, b) => a['created_at'].compareTo(b['created_at'])); for (var item in data) { // 1. قراءة البيانات بالأسماء الصحيحة من الجدول double lat = item['latitude'] ?? item['lat'] ?? 0.0; double lng = item['longitude'] ?? item['lng'] ?? 0.0; double acc = item['acceleration'] ?? 0.0; // قراءة الوقت لحساب السرعة DateTime currentTime = DateTime.tryParse(item['created_at'].toString()) ?? DateTime.now(); double currentSpeed = 0; // 2. حساب السرعة والمسافة إذا وجدت نقطة سابقة if (prevLat != null && prevLng != null && prevTime != null) { double distKm = _calculateDistance(prevLat, prevLng, lat, lng); int timeDiffSeconds = currentTime.difference(prevTime).inSeconds; if (timeDiffSeconds > 0) { // السرعة (كم/س) = (المسافة بالكيلومتر * 3600) / الزمن بالثواني currentSpeed = (distKm * 3600) / timeDiffSeconds; } totalDistance += distKm; } // تحديث القيم الإحصائية if (currentSpeed > maxSpeed) maxSpeed = currentSpeed; totalSpeed += currentSpeed; // حساب الفرملة القوية (يعتمد على التسارع المحفوظ مسبقاً) if (acc.abs() > 3.0) hardBrakes++; // حفظ النقطة الحالية لتكون هي "السابقة" في الدورة التالية prevLat = lat; prevLng = lng; prevTime = currentTime; } // تجنب القسمة على صفر double avgSpeed = (data.length > 1) ? totalSpeed / (data.length - 1) : 0; // حساب تقييم السلوك double behaviorScore = 100 - (hardBrakes * 5) - ((maxSpeed > 100) ? 10 : 0); behaviorScore = behaviorScore.clamp(0.0, 100.0); return { 'max_speed': maxSpeed, 'avg_speed': avgSpeed, 'hard_brakes': hardBrakes, 'total_distance': totalDistance, 'behavior_score': behaviorScore, }; } Future sendSummaryToServer(String driverId, String tripId) async { final summary = await analyzeData(); if (summary.isEmpty) return; final Map body = { 'driver_id': driverId, 'trip_id': tripId, ...summary, // فيه doubles }; // اجبر كل القيم على String final payload = body.map((k, v) => MapEntry(k, v?.toString() ?? '')); await CRUD().post(link: AppLink.saveBehavior, payload: payload); await clearData(); } Future clearData() async { await sql.deleteAllData(TableName.behavior); } double _calculateDistance( double lat1, double lon1, double lat2, double lon2) { const p = 0.017453292519943295; final a = 0.5 - cos((lat2 - lat1) * p) / 2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2; return 12742 * asin(sqrt(a)); // distance in km } } ================================================== FILE PATH: ./lib/controller/home/captin/duration_controller .dart ================================================== import 'dart:convert'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/models/model/driver/rides_summary_model.dart'; class DurationController extends GetxController { final data = DurationData; // late AnimationController animationController; late List rideData; late List rideCountData; late List ridePriceDriverData; Map jsonData1 = {}; Map jsonData2 = {}; bool isLoading = false; String totalDurationToday = ''; var chartData; var chartRideCount; var chartRidePriceDriver; List monthlyList = []; @override void onInit() async { super.onInit(); await fetchData(); await fetchRideDriver(); await getStaticDriver(); } getStaticDriver() async { isLoading = true; update(); var res = await CRUD().get( link: AppLink.driverStatistic, payload: {'driverID': box.read(BoxName.driverID)}); if (res == 'failure') { monthlyList = []; isLoading = false; update(); } else { monthlyList = jsonDecode(res)['message']; isLoading = false; update(); } } Future fetchData() async { isLoading = true; update(); // Notify the observers about the loading state change var res = await CRUD().get( link: AppLink.getTotalDriverDuration, payload: {'driver_id': box.read(BoxName.driverID)}, ); jsonData1 = jsonDecode(res); var jsonResponse = jsonDecode(res) as Map; isLoading = false; final List jsonData = jsonResponse['message']; rideData = jsonData.map((item) { return MonthlyDataModel.fromJson(item); }).toList(); final List spots = rideData .map((data) => FlSpot( data.day.toDouble(), data.totalDuration.toDouble(), )) .toList(); chartData = spots; update(); // Notify the observers about the data and loading state change } Future fetchRideDriver() async { isLoading = true; update(); // Notify the observers about the loading state change var res = await CRUD().get( link: AppLink.getRidesDriverByDay, payload: {'driver_id': box.read(BoxName.driverID)}, ); if (res != 'failure') { jsonData2 = jsonDecode(res); var jsonResponse = jsonDecode(res) as Map; isLoading = false; final List jsonData = jsonResponse['message']; rideCountData = jsonData.map((item) { return MonthlyRideModel.fromJson(item); }).toList(); ridePriceDriverData = jsonData.map((item) { return MonthlyPriceDriverModel.fromJson(item); }).toList(); final List spots = rideCountData .map((data) => FlSpot( data.day.toDouble(), data.countRide.toDouble(), )) .toList(); chartRideCount = spots; final List spotsDriverPrices = ridePriceDriverData .map((data) => FlSpot( data.day.toDouble(), data.pricePerDay.toDouble(), )) .toList(); chartRidePriceDriver = spotsDriverPrices; update(); // Notify the observers about the data and loading state change } else { Get.defaultDialog( title: 'No data yet!'.tr, middleText: '', confirm: MyElevatedButton( title: 'OK'.tr, onPressed: () { Get.back(); Get.back(); })); } } List parseData(List json) { return json.map((entry) { final Map entryMap = entry; final day = DateTime.parse(entryMap['day']); final totalDuration = _parseDuration(entryMap['total_duration']); return DurationData(day, totalDuration); }).toList(); } Duration _parseDuration(String durationString) { final parts = durationString.split(':'); final hours = int.parse(parts[0]); final minutes = int.parse(parts[1]); final seconds = int.parse(parts[2]); return Duration(hours: hours, minutes: minutes, seconds: seconds); } } class DurationData { final DateTime day; final Duration totalDuration; DurationData(this.day, this.totalDuration); } ================================================== FILE PATH: ./lib/controller/home/captin/map_driver_controller.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; import 'dart:math' as math; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:sefer_driver/controller/firebase/local_notification.dart'; import 'package:sefer_driver/controller/home/captin/behavior_controller.dart'; import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:bubble_head/bubble.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_polyline_algorithm/google_polyline_algorithm.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../constant/api_key.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/country_polygons.dart'; import '../../../constant/links.dart'; import '../../../constant/table_names.dart'; import '../../../env/env.dart'; import '../../../main.dart'; import '../../../print.dart'; import '../../../views/Rate/rate_passenger.dart'; import '../../../views/home/Captin/home_captain/home_captin.dart'; import '../../firebase/firbase_messge.dart'; import '../../firebase/notification_service.dart'; import '../../functions/crud.dart'; import '../../functions/location_controller.dart'; import '../../functions/tts.dart'; class MapDriverController extends GetxController { bool isLoading = true; final formKey1 = GlobalKey(); final formKey2 = GlobalKey(); final formKeyCancel = GlobalKey(); final messageToPassenger = TextEditingController(); final sosEmergincyNumberCotroller = TextEditingController(); final cancelTripCotroller = TextEditingController(); List data = []; List dataDestination = []; LatLngBounds? boundsData; BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor passengerIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker; final List polylineCoordinates = []; final List polylineCoordinatesDestination = []; List polyLines = []; List polyLinesDestination = []; Set markers = {}; late String passengerLocation; late String passengerDestination; late String step0; late String step1; late String step2; late String step3; late String step4; late String passengerWalletBurc; late String timeOfOrder; late String duration; late String totalCost; String distance = '0'; String? passengerName; late String passengerEmail; late String totalPricePassenger; late String passengerPhone; late String rideId; late String isHaveSteps; String paymentAmount = '0'; late String paymentMethod; late String passengerId; late String driverId; late String tokenPassenger; late String durationToPassenger; late String walletChecked; late String direction; late String durationOfRideValue; late String status; int timeWaitingPassenger = 5; //5 miniute bool isPassengerInfoWindow = false; bool isBtnRideBegin = false; bool isArrivedSend = true; bool isdriverWaitTimeEnd = false; bool isRideFinished = false; bool isRideStarted = false; bool isPriceWindow = false; double passengerInfoWindowHeight = Get.height * .38; double driverEndPage = 100; double progress = 0; double progressToPassenger = 0; double progressInPassengerLocationFromDriver = 0; bool isRideBegin = false; int progressTimerToShowPassengerInfoWindowFromDriver = 25; int remainingTimeToShowPassengerInfoWindowFromDriver = 25; int remainingTimeToPassenger = 60; int remainingTimeInPassengerLocatioWait = 60; bool isDriverNearPassengerStart = false; GoogleMapController? mapController; late LatLng myLocation; int remainingTimeTimerRideBegin = 60; String stringRemainingTimeRideBegin = ''; String stringRemainingTimeRideBegin1 = ''; double progressTimerRideBegin = 0; Timer? timer; String? mapAPIKEY; final zones = []; String canelString = 'yet'; LatLng latLngPassengerLocation = LatLng(0, 0); late LatLng latLngPassengerDestination = LatLng(0, 0); List> routeSteps = []; String currentInstruction = ""; int currentStepIndex = 0; bool isTtsEnabled = false; void toggleTts() { isTtsEnabled = !isTtsEnabled; box.write(BoxName.ttsEnabled, isTtsEnabled); update(); // تحديث الواجهة } void disposeEverything() { onClose(); } @override void onClose() { print("--- KILLING ALL DRIVER TIMERS ---"); _rideTimer?.cancel(); _rideTimer = null; timer?.cancel(); timer = null; _navigationTimer?.cancel(); _navigationTimer = null; _posSub?.cancel(); _posSub = null; mapController?.dispose(); super.onClose(); } void onMapCreated(GoogleMapController controller) async { myLocation = Get.find().myLocation; // myLocation = myLocation; mapController = controller; controller.getVisibleRegion(); // LatLngBounds bounds = await controller.getVisibleRegion(); controller.animateCamera( CameraUpdate.newLatLng(Get.find().myLocation), ); update(); // Set up a timer or interval to trigger the marker update every 3 seconds. timer = Timer.periodic(const Duration(seconds: 1), (_) { updateMarker(); }); } void changeStatusDriver() { status = 'On'; update(); } void changeDriverEndPage() { remainingTimeTimerRideBegin < 60 ? driverEndPage = 160 : 100; update(); } takeSnapMap() { mapController!.takeSnapshot(); } @override void dispose() { mapController!.dispose(); super.dispose(); } Future openGoogleMapFromDriverToPassenger() async { var endLat = latLngPassengerLocation.latitude; var endLng = latLngPassengerLocation.longitude; var startLat = Get.find().myLocation.latitude; var startLng = Get.find().myLocation.longitude; String url = 'https://www.google.com/maps/dir/$startLat,$startLng/$endLat,$endLng/&directionsmode=driving'; if (await canLaunchUrl(Uri.parse(url))) { await launchUrl(Uri.parse(url)); } else { throw 'Could not launch google maps'; } } void clearPolyline() { polyLines = []; polyLinesDestination = []; polylineCoordinates.clear(); polylineCoordinatesDestination.clear(); update(); } void changeRideToBeginToPassenger() { isRideBegin = true; passengerInfoWindowHeight = Get.height * .22; update(); } cancelTripFromDriverAfterApplied() async { if (formKeyCancel.currentState!.validate()) { // 1. إيقاف استقبال التحديثات فوراً box.write(BoxName.statusDriverLocation, 'off'); // إظهار لودينج لمنع المستخدم من الضغط مرتين Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); try { // 2. إرسال الإشعار للراكب NotificationService.sendNotification( target: tokenPassenger.toString(), title: "Cancel Trip from driver", body: "Trip Cancelled from driver. We are looking for a new driver. Please wait." .tr, isTopic: false, tone: 'cancel', driverList: [], category: "Cancel Trip from driver", ); // 3. تحديث السيرفرات (نستخدم await لضمان وصول الأمر للسيرفر قبل إغلاق الصفحة) // ملاحظة: تأكد من صحة هذه الروابط // await CRUD().post( // link: "${AppLink.server}/ride/rides/cancelRideFromDriver.php", // payload: { // "id": (rideId).toString(), // // "status": 'CancelFromDriverAfterApply' // }); // CRUD().post(link: "${AppLink.rideServer}/rides/update.php", payload: { // "id": (rideId).toString(), // "status": 'CancelFromDriverAfterApply' // }); // هذا الرابط كان يسبب مشكلة HTML، وضعناه في try منفصل كي لا يوقف العملية // try { // CRUD().postFromDialogue( // link: '${AppLink.server}/driver_order/add.php', // payload: { // 'driver_id': box.read(BoxName.driverID).toString(), // 'order_id': (rideId).toString(), // 'status': 'CancelFromDriverAfterApply' // }); // } catch (e) { // Log.print("Error logging driver order: $e"); // } CRUD().post( link: "${AppLink.ride}/cancelRide/addCancelTripFromDriverAfterApplied.php", payload: { "order_id": (rideId).toString(), "driver_id": box.read(BoxName.driverID).toString(), "status": 'CancelFromDriverAfterApply', "notes": (cancelTripCotroller.text) ?? 'none', }); // 4. تنظيف البيانات المحلية // CRUD().post( // link: "${AppLink.ride}/cancelRide/deletArgumets.php", // payload: { // "driver_id": box.read(BoxName.driverID).toString(), // }); box.remove(BoxName.rideArgumentsFromBackground); box.remove(BoxName.rideArguments); box.write(BoxName.statusDriverLocation, 'off'); // 5. حل مشكلة الكراش (SQL UNIQUE constraint failed) // نضع الكود داخل try-catch، إذا كان الرقم موجوداً مسبقاً سيتم تجاهل الإضافة ولن ينهار التطبيق try { await sql.insertData({ 'order_id': (rideId), 'created_at': DateTime.now().toString(), 'driver_id': box.read(BoxName.driverID).toString(), }, TableName.driverOrdersRefuse); } catch (e) { Log.print( "Order already exists in refused list, skipping insert. Error: $e"); } box.write(BoxName.rideStatus, 'Cancel'); Log.print('rideStatus from map 240 : ${box.read(BoxName.rideStatus)}'); // تحديث القائمة الرئيسية Get.find().getRefusedOrderByCaptain(); // إغلاق اللودينج والانتقال if (Get.isDialogOpen ?? false) Get.back(); Get.offAll(() => HomeCaptain()); } catch (e) { // في حال حدوث أي خطأ غير متوقع، نغلق اللودينج ونخرج أيضاً لضمان عدم تعليق التطبيق if (Get.isDialogOpen ?? false) Get.back(); Log.print("Error during cancellation: $e"); Get.offAll(() => HomeCaptain()); } } } void startTimerToShowPassengerInfoWindowFromDriver() async { if (box.read(BoxName.rideStatus) == 'Begin') { Log.print('rideStatus from map 248 : ${box.read(BoxName.rideStatus)}'); isPassengerInfoWindow = false; } else { isPassengerInfoWindow = true; for (int i = 0; i <= int.parse(durationToPassenger); i++) { await Future.delayed(const Duration(seconds: 1)); progressToPassenger = i / int.parse(durationToPassenger); remainingTimeToPassenger = int.parse(durationToPassenger) - i; if (remainingTimeToPassenger == 0) { isBtnRideBegin = true; update(); } int minutes = (remainingTimeToPassenger / 60).floor(); int seconds = remainingTimeToPassenger % 60; stringRemainingTimeToPassenger = '$minutes:${seconds.toString().padLeft(2, '0')}'; update(); } } // update(); // startTimerToShowDriverToPassengerDuration(); } String stringRemainingTimeToPassenger = ''; String stringRemainingTimeWaitingPassenger = ''; void startTimerToShowDriverWaitPassengerDuration() async { for (int i = 0; i <= timeWaitingPassenger * 60; i++) { await Future.delayed(const Duration(seconds: 1)); progressInPassengerLocationFromDriver = i / (timeWaitingPassenger * 60); remainingTimeInPassengerLocatioWait = (timeWaitingPassenger * 60) - i; if (isRideBegin == true) { remainingTimeInPassengerLocatioWait = 0; update(); } if (remainingTimeInPassengerLocatioWait == 0) { isdriverWaitTimeEnd = true; update(); } 'remainingTimeInPassengerLocatioWait $remainingTimeInPassengerLocatioWait'; int minutes = (remainingTimeInPassengerLocatioWait / 60).floor(); int seconds = remainingTimeInPassengerLocatioWait % 60; stringRemainingTimeWaitingPassenger = '$minutes:${seconds.toString().padLeft(2, '0')}'; update(); } } void driverGoToPassenger() async { changeRideToBeginToPassenger(); box.write(BoxName.rideStatus, 'Applied'); Log.print('rideStatus from map 304 : ${box.read(BoxName.rideStatus)}'); update(); await CRUD() .post(link: "${AppLink.server}/ride/rides/update.php", payload: { 'id': (rideId), 'driverGoToPassengerTime': DateTime.now().toString(), 'status': 'Applied' }); // CRUD().post(link: "${AppLink.rideServer}/ride/rides/update.php", payload: { // 'id': (rideId), // 'driverGoToPassengerTime': DateTime.now().toString(), // 'status': 'Applied' // }); NotificationService.sendNotification( target: tokenPassenger.toString(), title: 'Driver Is Going To Passenger'.tr, body: box.read(BoxName.nameDriver).toString(), isTopic: false, // Important: this is a token tone: 'start', driverList: [], category: 'Driver Is Going To Passenger', ); } bool isSocialPressed = false; driverCallPassenger() async { String scam = await getDriverScam(); // نحول القيمة لرقم بشكل آمن int scamCount = int.tryParse(scam) ?? 0; // لو فوق الحد المطلوب if (scamCount > 3) { box.write(BoxName.statusDriverLocation, 'on'); Get.find().stopLocationUpdates(); await CRUD().post( link: AppLink.addNotificationCaptain, payload: { 'driverID': box.read(BoxName.driverID), 'title': 'scams operations'.tr, 'body': 'you have connect to passengers and let them cancel the order'.tr, }, ); return; } // تسجيل التحايل بشكل طبيعي if (isSocialPressed == true && passengerId != null && rideId != null) { box.write(BoxName.statusDriverLocation, 'off'); await CRUD().post( link: AppLink.addDriverScam, payload: { 'driverID': box.read(BoxName.driverID), 'passengerID': passengerId, 'rideID': rideId, 'isDriverCalledPassenger': 'true', }, ); } } // دالة مساعدة لحماية التطبيق من كراش الخرائط Future safeAnimateCamera(CameraUpdate cameraUpdate) async { // 1. تحقق مما إذا كان الكونترولر مغلقاً (المستخدم خرج من الصفحة) if (isClosed) return; // 2. تحقق من أن متغير الخريطة موجود if (mapController == null) return; try { // 3. حاول التحريك await mapController!.animateCamera(cameraUpdate); } catch (e) { // 4. إذا حدث خطأ (مثل أن الخريطة لم تعد موجودة في الذاكرة)، تجاهله ولا توقف التطبيق Log.print("SafeAnimateCamera Error ignored: $e"); } } Future getDriverScam() async { var res = await CRUD().post(link: AppLink.getDriverScam, payload: { 'driverID': box.read(BoxName.driverID), }); if (res == 'failure') { box.write(BoxName.statusDriverLocation, 'off'); return '0'; } var d = (res); Log.print('d: ${d}'); // 1. Check if the response status is 'failure' (API level check) if (d['status'] == 'failure') { // If the API status is failure, the message is a String (e.g., 'No ride scam record found') // and there's no 'count' array to read. return '0'; } // 2. Safely access the List/Map structure for 'count' // This assumes a successful response looks like: // {'status': 'success', 'message': [{'count': '12'}]} var messageData = d['message']; // Check if messageData is actually a List before accessing index [0] if (messageData is List && messageData.isNotEmpty && messageData[0] is Map) { return messageData[0]['count']; } // Fallback if the successful data structure is unexpected return '0'; // --- FIX END --- } void startRideFromStartApp() { // if (box.read(BoxName.rideStatus) == 'Begin') { changeRideToBeginToPassenger(); isPassengerInfoWindow = false; isRideStarted = true; isRideFinished = false; remainingTimeInPassengerLocatioWait = 0; timeWaitingPassenger = 0; box.write(BoxName.statusDriverLocation, 'on'); update(); // } // rideIsBeginPassengerTimer(); } Position? currentPosition; startRideFromDriver() async { double _distance = await calculateDistanceBetweenDriverAndPassengerLocation(); if (_distance < 400) { changeRideToBeginToPassenger(); isPassengerInfoWindow = false; isRideStarted = true; isRideFinished = false; remainingTimeInPassengerLocatioWait = 0; timeWaitingPassenger = 0; box.write(BoxName.statusDriverLocation, 'on'); // // ابدأ التتبع الحيّ لخطوات الملاحة await startListeningStepNavigation(); // box.write(BoxName.rideStatus, 'Begin'); // // todo ride details // Get.find().changeToAppliedRide('Begin'); box.write(BoxName.rideStatus, 'Begin'); Log.print('rideStatus from map 399 : ${box.read(BoxName.rideStatus)}'); // Get.find().update(); update(); await CRUD() .post(link: "${AppLink.server}/ride/rides/update.php", payload: { 'id': (rideId).toString(), // معرف الرحلة 'driver_id': box.read(BoxName.driverID).toString(), 'status': 'Begin', }); // CRUD().post(link: AppLink.addDriverOrder, payload: { // 'driver_id': box.read(BoxName.driverID).toString(), // 'order_id': (rideId).toString(), // 'status': 'Begin' // }); NotificationService.sendNotification( target: tokenPassenger.toString(), title: 'Trip is Begin'.tr, body: box.read(BoxName.nameDriver).toString(), isTopic: false, // Important: this is a token tone: 'start', driverList: [], category: 'Trip is Begin', ); rideIsBeginPassengerTimer(); // Get.back(); update(); } else { Get.back(); MyDialog().getDialog('Your are far from passenger location'.tr, 'go to your passenger location before\nPassenger cancel trip'.tr, () { Get.back(); }); } } calculateDistanceInMeter(LatLng prev, LatLng current) async { double distance2 = Geolocator.distanceBetween( prev.latitude, prev.longitude, current.latitude, current.longitude, ); return distance2; } double speedoMeter = 0; void updateLocation() async { try { for (var i = 0; i < remainingTimeTimerRideBegin; i++) { await Future.delayed(const Duration(seconds: 3)); await safeAnimateCamera( CameraUpdate.newCameraPosition( CameraPosition( bearing: Get.find().heading, target: myLocation, zoom: 17, ), ), ); // }); update(); } // Stop listening after ride finishes if (!isRideBegin) {} } catch (error) { debugPrint('Error listening to GPS: $error'); // Handle GPS errors gracefully } // Periodically call updateLocation again await Future.delayed(const Duration(seconds: 1)); updateLocation(); } calculateDistanceBetweenDriverAndPassengerLocation() async { Get.put(LocationController()); var res = await CRUD().get( link: AppLink.getLatestLocationPassenger, payload: {'rideId': (rideId)}); if (res != 'failure') { var passengerLatestLocationString = jsonDecode(res)['message']; double distance2 = Geolocator.distanceBetween( double.parse(passengerLatestLocationString[0]['lat'].toString()), double.parse(passengerLatestLocationString[0]['lng'].toString()), Get.find().myLocation.latitude, Get.find().myLocation.longitude, ); return distance2; } else { double distance2 = Geolocator.distanceBetween( latLngPassengerLocation.latitude, latLngPassengerLocation.longitude, Get.find().myLocation.latitude, Get.find().myLocation.longitude, ); return distance2; } } addWaitingTimeCostFromPassengerToDriverWallet() async { double distance2 = await calculateDistanceBetweenDriverAndPassengerLocation(); if (distance2 > 100) { MyDialog().getDialog('Your are far from passenger location'.tr, 'go to your passenger location before\nPassenger cancel trip'.tr, () { Get.back(); }); } else { double costOfWaiting5Minute = box.read(BoxName.countryCode) == 'Egypt' ? (distanceBetweenDriverAndPassengerWhenConfirm * .08) + (5 * 1) : (distanceBetweenDriverAndPassengerWhenConfirm * 1100) + (5 * .06); //for Eygpt other like jordan .06 per minute await CRUD().post(link: "${AppLink.ride}/rides/update.php", payload: { 'id': (rideId), 'rideTimeStart': DateTime.now().toString(), 'status': 'CancelAfterWait', }); CRUD().post(link: AppLink.addDriverOrder, payload: { 'driver_id': box.read(BoxName.driverID).toString(), 'order_id': (rideId).toString(), 'status': 'CancelAfterWait' }); var paymentTokenWait = await generateTokenDriver(costOfWaiting5Minute.toString()); var res = await CRUD().post(link: AppLink.addDrivePayment, payload: { 'rideId': (rideId), 'amount': (costOfWaiting5Minute.toString()), 'payment_method': 'wait-cancel', 'passengerID': (passengerId), 'token': paymentTokenWait, 'driverID': box.read(BoxName.driverID).toString(), }); var paymentTokenWait1 = await generateTokenDriver(costOfWaiting5Minute.toString()); var res1 = await CRUD().post(link: AppLink.addDriversWalletPoints, payload: { 'paymentID': 'rideId${(rideId)}', 'amount': (costOfWaiting5Minute).toStringAsFixed(0), 'paymentMethod': 'wait', 'token': paymentTokenWait1, 'driverID': box.read(BoxName.driverID).toString(), }); if (res != 'failure') { Get.snackbar( 'You will get cost of your work for this trip'.tr, '${'you gain'.tr} $costOfWaiting5Minute \$${' in your wallet'.tr}', backgroundColor: AppColor.deepPurpleAccent, ); } var paymentTokenWaitPassenger1 = await generateTokenPassenger((costOfWaiting5Minute * -1).toString()); await CRUD().post(link: AppLink.addPassengersWallet, payload: { 'passenger_id': (passengerId), 'balance': (costOfWaiting5Minute * -1).toString(), 'token': paymentTokenWaitPassenger1, }); box.write(BoxName.statusDriverLocation, 'off'); Get.offAll(HomeCaptain()); } } Future finishRideFromDriver() async { // double distanceToDestination = Geolocator.distanceBetween( // latLngPassengerDestination.latitude, // latLngPassengerDestination.longitude, // Get.find().myLocation.latitude, // Get.find().myLocation.longitude, // ); final originalDistanceM = double.parse(distance.toString()) * 1000; // 2. احسب المسافة التي قطعها السائق حتى الآن final movedDistanceM = Geolocator.distanceBetween( Get.find().myLocation.latitude, Get.find().myLocation.longitude, latLngPassengerLocation.latitude, latLngPassengerLocation.longitude, ); // originalDistanceM - distanceToDestination; // 3. عتبة ثلث المسافة final oneThirdDistanceM = originalDistanceM / 5; // Logging للتتبع Log.print('originalDistanceM: $originalDistanceM'); // Log.print('distanceToDestinationM: $distanceToDestination'); Log.print('movedDistanceM: $movedDistanceM'); Log.print('oneThirdDistanceM: $oneThirdDistanceM'); // 4. إذا لم يقطع السائق ثلث المسافة، نعرض التأكيد if (movedDistanceM > oneThirdDistanceM) { MyDialog().getDialog( 'Are you sure to exit ride?'.tr, '', () { Get.back(); finishRideFromDriver1(); }, ); } ///// else { final textToSpeechController = Get.put(TextToSpeechController()); MyDialog().getDialog( "You haven't moved sufficiently!".tr, '', () => Get.back(), ); await textToSpeechController .speakText("You haven't moved sufficiently!".tr); } } String paymentToken = ''; Future generateTokenDriver(String amount) async { var res = await CRUD().postWallet(link: AppLink.addPaymentTokenDriver, payload: { 'driverID': box.read(BoxName.driverID).toString(), 'amount': amount.toString(), }); var d = (res); return d['message']; } String paymentTokenPassenger = ''; Future generateTokenPassenger(String amount) async { var res = await CRUD() .postWallet(link: AppLink.addPaymentTokenPassenger, payload: { 'passengerId': passengerId, 'amount': amount.toString(), }); var d = (res); return d['message']; } // ... other controller code ... /// Refactored function to finish a ride with consolidated API calls. void finishRideFromDriver1() async { // Show a loading indicator to the user Get.dialog(Center(child: CircularProgressIndicator()), barrierDismissible: false); isRideFinished = true; isRideStarted = false; isPriceWindow = false; box.write(BoxName.rideStatus, 'Finished'); Log.print( 'rideStatus from map (refactored) : ${box.read(BoxName.rideStatus)}'); // --- 1. Calculate Total Cost (Logic remains the same) --- if (price < 172) { totalCost = (carType == 'Comfort' || carType == 'Mishwar Vip' || carType == 'Lady') ? '200' : '172'; } else if (price < double.parse(totalPricePassenger)) { totalCost = totalPricePassenger; } else { totalCost = (carType == 'Comfort' || carType == 'Mishwar Vip' || carType == 'Lady') ? price.toStringAsFixed(2) : totalPricePassenger; } paymentAmount = totalCost; box.write(BoxName.statusDriverLocation, 'off'); // --- 2. Prepare Payloads for Consolidated API Calls --- // final nowString = DateTime.now().toString(); final rideUpdatePayload = { 'rideId': rideId.toString(), 'driver_id': box.read(BoxName.driverID).toString(), 'status': 'Finished', 'price': totalCost, }; final String paymentAuthToken = await generateTokenDriver(paymentAmount.toString()); final paymentProcessingPayload = { 'rideId': rideId.toString(), 'driverId': box.read(BoxName.driverID).toString(), 'passengerId': passengerId.toString(), 'paymentAmount': paymentAmount, 'paymentMethod': paymentMethod, 'walletChecked': walletChecked.toString(), 'passengerWalletBurc': passengerWalletBurc.toString(), 'authToken': paymentAuthToken, }; // --- 3. Execute API Calls in Parallel --- try { List> apiCalls = []; // apiCalls.add(CRUD().post( // link: "${AppLink.rideServer}/rides/finish_ride_updates.php", // payload: rideUpdatePayload, // )); apiCalls.add(CRUD().post( link: "${AppLink.ride}/rides/finish_ride_updates.php", payload: rideUpdatePayload, )); apiCalls.add(CRUD().postWallet( link: "${AppLink.paymentServer}/ride/payment/process_ride_payments.php", payload: paymentProcessingPayload, )); final results = await Future.wait(apiCalls); // --- 4. *** CRITICAL STEP: Verify BOTH results were successful *** --- // Assuming CRUD().post returns a Map like {'success': true, 'message': '...'} final rideUpdate1 = results[0]; Log.print('rideUpdate1: ${rideUpdate1}'); // final rideUpdate2 = results[1]; final paymentRealResult = results[1]; // هذا هو الدفع الحقيقي! // المنطق: يجب أن ينجح تحديث واحد للرحلة على الأقل + يجب أن ينجح الدفع bool isRideUpdated = (rideUpdate1['status'] == 'success'); bool isPaymentSuccess = (paymentRealResult['status'] == 'success'); if (isRideUpdated && isPaymentSuccess) { // --- SUCCESS: Both API calls succeeded, now proceed --- // Dismiss the loading indicator Get.put(DriverBehaviorController()) .sendSummaryToServer(driverId, rideId); NotificationService.sendNotification( target: tokenPassenger.toString(), title: "Driver Finish Trip".tr, body: '${'you will pay to Driver'.tr} ${NumberFormat('#,##0').format(double.tryParse(paymentAmount.toString()))} \$' .tr, isTopic: false, // Important: this is a token tone: 'ding', driverList: [ box.read(BoxName.driverID), rideId, box.read(BoxName.tokenDriver), paymentAmount.toString() ], category: 'Driver Finish Trip', ); // Get.back(); // String formattedPrice = NumberFormat('#,##0.0') // .format(double.tryParse(paymentAmount.toString()) ?? 0.0); // NotificationController().showNotification("تم إنهاء الرحلة", // "المبلغ المستحق من العميل: $formattedPrice", "ding", ""); Log.print('walletChecked: ${walletChecked}'); Log.print('paymentAmount: ${paymentAmount}'); Log.print('rideId: ${rideId}'); Get.to(() => RatePassenger(), arguments: { 'passengerId': passengerId, 'rideId': rideId, 'price': paymentAmount.toString(), 'walletChecked': walletChecked.toString() ?? 'false' }); } else { // --- FAILURE: One or both API calls failed --- // The transaction on the server side would have been rolled back. // We throw an exception to be caught by the catch block, which will revert the UI state. throw Exception( 'Failed. Ride1: ${rideUpdate1['status']}, Payment: ${paymentRealResult['status']}'); } } catch (e) { // --- CATCH ALL ERRORS (Network, Server Failure, etc.) --- Get.back(); // Dismiss the loading indicator Log.print("Error finishing ride: $e"); Get.snackbar("Error", "Could not finish the ride. Please try again."); // Revert state because the operation failed isRideFinished = false; isRideStarted = true; isPriceWindow = true; box.write(BoxName.rideStatus, 'InProgress'); // Revert status } } void cancelCheckRideFromPassenger() async { var res = await CRUD().get( link: "${AppLink.endPoint}/ride/driver_order/getOrderCancelStatus.php", payload: { 'order_id': (rideId), }); //.then((value) { var response = jsonDecode(res); canelString = response['data']['status']; update(); if (canelString == 'Cancel') { remainingTimeTimerRideBegin = 0; remainingTimeToShowPassengerInfoWindowFromDriver = 0; remainingTimeToPassenger = 0; isRideStarted = false; isRideFinished = false; isPassengerInfoWindow = false; clearPolyline(); update(); MyDialog().getDialog( 'Order Cancelled'.tr, 'Order Cancelled by Passenger'.tr, () { Get.offAll(HomeCaptain()); }, ); } } int rideTimerFromBegin = 0; double price = 0; DateTime currentTime = DateTime.now(); /// أثناء الرحلة: نعرض السعر لحظياً بدون مضاعفة العمولة في كل ثانية. /// - نستخدم سعر الدقيقة حسب الوقت، مع قواعد الرحلات البعيدة: /// >25كم أو >35كم => دقيقة = 600، سقف 60 دقيقة، ومع >35كم عفو 10 دقائق. /// - سرعة طويلة: لو المسافة المخططة > 40كم نستخدم 2600 ل.س/كم للـ Speed، //// ونطبق نفس نسبة التخفيض على Comfort/Electric/Van. /// - نضيف فقط "الزيادة" فوق التسعيرة المقتبسة (وقت زائد + كم زائد). /// - نعكس العمولة kazán مرة واحدة على الزيادة (وليس كل ثانية). // ========================================================= // الدالة الرئيسية المعدلة (العداد) // ========================================================= // متغيرات العداد الجديد Timer? _rideTimer; DateTime? _rideStartTime; void rideIsBeginPassengerTimer() { // 1. تنظيف أي عداد سابق _rideTimer?.cancel(); // 2. تحديد وقت البدء الفعلي (لحساب الوقت بدقة حتى لو علق الجهاز) _rideStartTime = DateTime.now(); // 3. تجهيز الثوابت والقيم المبدئية مرة واحدة (Performance) final hc = Get.find(); final loc = Get.find(); // الأسعار final double perKmSpeedBase = hc.speedPrice; final double perKmComfortRaw = hc.comfortPrice; final double perKmDelivery = hc.deliveryPrice; final double perKmVanRaw = hc.familyPrice; const double electricUpliftKm = 400; final double perKmElectricRaw = perKmComfortRaw + electricUpliftKm; // أسعار الدقائق final double perMinNature = hc.naturePrice; final double perMinLate = hc.latePrice; final double perMinHeavy = hc.heavyPrice; // القيم القادمة من الحجز final double basePassengerQuote = safeParseDouble(totalCost); final int quotedMinutes = safeParseInt(duration) != 0 ? safeParseInt(duration) : safeParseInt(durationOfRideValue); final double kazanPct = safeParseDouble(kazan) / 100.0; // تحديد المسافة المخططة double plannedKm = 0.0; try { plannedKm = safeParseDouble(distance); } catch (_) {} final double startKm = loc.totalDistance / 1000; if (plannedKm <= 0) { plannedKm = (startKm > 0) ? startKm : 0.0; } // فلترة الاهتزاز (Jitter Filter) double lastKmForNoise = startKm; const double jitterMeters = 10.0; // 4. بدء العداد الدوري (كل 1 ثانية لتحديث الواجهة بسلاسة) _rideTimer = Timer.periodic(const Duration(seconds: 1), (timer) { // أمان: إذا انتهت الرحلة، أوقف العداد if (box.read(BoxName.rideStatus) != 'Begin') { timer.cancel(); return; } final now = DateTime.now(); // حساب الثواني المنقضية بدقة من ساعة النظام final int elapsedSeconds = now.difference(_rideStartTime!).inSeconds; // -- تحديث المسافة (فلترة الضجيج) -- double liveKm = loc.totalDistance / 1000; final double deltaMeters = (liveKm - lastKmForNoise) * 1000.0; // إذا كانت الحركة أقل من 10 أمتار، نعتبرها اهتزاز GPS ولا نزيدها if (deltaMeters < jitterMeters) { liveKm = lastKmForNoise; } else { lastKmForNoise = liveKm; } // -- تحديث السعر (كل 5 ثواني لتخفيف الحسابات، أو كل ثانية إذا أردت دقة لحظية) -- if (elapsedSeconds % 1 == 0) { // جعلناها كل ثانية لدقة العرض // استدعاء دالة حساب السعر المفصولة (أنظف للكود) price = _calculateCurrentPrice( now: now, elapsedSeconds: elapsedSeconds, liveKm: liveKm, plannedKm: plannedKm, startKm: startKm, quotedMinutes: quotedMinutes, basePassengerQuote: basePassengerQuote, kazanPct: kazanPct, // تمرير الأسعار perKmSpeedBase: perKmSpeedBase, perKmComfortRaw: perKmComfortRaw, perKmDelivery: perKmDelivery, perKmVanRaw: perKmVanRaw, perKmElectricRaw: perKmElectricRaw, perMinNature: perMinNature, perMinLate: perMinLate, perMinHeavy: perMinHeavy, ); } // -- تحديث عناصر الواجهة -- speed = loc.speed * 3.6; // حساب الوقت المتبقي (Countdown) int totalQuotedSeconds = quotedMinutes * 60; int remainingSeconds = totalQuotedSeconds - elapsedSeconds; if (remainingSeconds < 0) remainingSeconds = 0; remainingTimeTimerRideBegin = remainingSeconds; progressTimerRideBegin = (totalQuotedSeconds == 0) ? 0.0 : (elapsedSeconds / totalQuotedSeconds).clamp(0.0, 1.0); // تغيير تصميم الصفحة في الدقائق الأخيرة remainingTimeTimerRideBegin < 60 ? driverEndPage = 160 : 100; // إيقاف بث الموقع للسائق في آخر دقيقة (حسب منطقك القديم) if (remainingTimeTimerRideBegin < 60) { box.write(BoxName.statusDriverLocation, 'off'); } updateMarker(); update(); // تحديث GetBuilder }); } // ========================================================= // دالة حساب السعر (منطق مفصول ونظيف) // ========================================================= double _calculateCurrentPrice({ required DateTime now, required int elapsedSeconds, required double liveKm, required double plannedKm, required double startKm, required int quotedMinutes, required double basePassengerQuote, required double kazanPct, // الأسعار required double perKmSpeedBase, required double perKmComfortRaw, required double perKmDelivery, required double perKmVanRaw, required double perKmElectricRaw, required double perMinNature, required double perMinLate, required double perMinHeavy, }) { // الثوابت الخاصة بالمسافات الطويلة const double longSpeedThresholdKm = 40.0; const double longSpeedPerKm = 2600.0; const double mediumDistThresholdKm = 25.0; const double longDistThresholdKm = 35.0; const double longTripPerMin = 600.0; const int minuteCapMedium = 60; const int minuteCapLong = 60; const int freeMinutesLong = 10; const double extraReduction100 = 0.07; const double maxReductionCap = 0.35; // 1. تحديد سياق المطار bool isAirport(String s) => s.toLowerCase().contains('airport') || s.contains('مطار'); final bool airportCtx = isAirport(startNameLocation) || isAirport(endNameLocation); // 2. تحديد المسافة المعتمدة للحساب final double plannedForRulesKm = (plannedKm > 0) ? plannedKm : liveKm; // 3. تحديد نسبة التخفيض للمسافات الطويلة double reductionPct = 0.0; if (plannedForRulesKm > 40.0) { double r40 = 0.0; if (perKmSpeedBase > 0) { r40 = (1.0 - (longSpeedPerKm / perKmSpeedBase)) .clamp(0.0, maxReductionCap); } reductionPct = r40; if (plannedForRulesKm > 100.0) { reductionPct = (r40 + extraReduction100).clamp(0.0, maxReductionCap); } } // 4. تحديد سعر الكيلومتر بناءً على النوع والمسافة final bool isLong = plannedForRulesKm > longSpeedThresholdKm; // حساب أسعار الكيلومتر المخفضة final double finalPerKmSpeed = isLong ? longSpeedPerKm : perKmSpeedBase; final double finalPerKmBalash = (finalPerKmSpeed - 500).clamp(0, double.infinity); final double finalPerKmComfort = (perKmComfortRaw * (1.0 - reductionPct)); final double finalPerKmElectric = (perKmElectricRaw * (1.0 - reductionPct)); final double finalPerKmVan = (perKmVanRaw * (1.0 - reductionPct)); double perKmForType; switch (carType) { case 'Speed': perKmForType = finalPerKmSpeed; break; case 'Fixed Price': perKmForType = finalPerKmSpeed; break; case 'Awfar Car': perKmForType = finalPerKmBalash; break; case 'Comfort': case 'Mishwar Vip': case 'RayehGaiComfort': case 'Lady': perKmForType = finalPerKmComfort; break; case 'Electric': perKmForType = finalPerKmElectric; break; case 'Van': perKmForType = finalPerKmVan; break; case 'Delivery': perKmForType = perKmDelivery; break; default: perKmForType = finalPerKmSpeed; } // 5. تحديد سعر الدقيقة الفعلي double perMinEff; int capMinutes = 1 << 30; // رقم كبير جداً (لا سقف) int freeMinutes = 0; // قواعد المسافات if (plannedForRulesKm > longDistThresholdKm) { perMinEff = longTripPerMin; capMinutes = minuteCapLong; freeMinutes = freeMinutesLong; } else if (plannedForRulesKm > mediumDistThresholdKm) { perMinEff = longTripPerMin; capMinutes = minuteCapMedium; } else { // القواعد الزمنية العادية final h = now.hour; if (airportCtx) { perMinEff = perMinLate; } else if (h >= 21 || h < 1) { perMinEff = perMinLate; } else if (h >= 14 && h <= 17) { perMinEff = perMinHeavy; } else { perMinEff = perMinNature; } } // 6. حساب الدقائق الإضافية final int elapsedMinutes = (elapsedSeconds ~/ 60); int extraMinutes = 0; final int rawExtra = elapsedMinutes - quotedMinutes - freeMinutes; if (rawExtra > 0) { extraMinutes = rawExtra; // تطبيق سقف الدقائق إن وجد if (capMinutes < (1 << 30)) { final int maxBillable = (capMinutes - quotedMinutes - freeMinutes); if (extraMinutes > maxBillable) { extraMinutes = maxBillable < 0 ? 0 : maxBillable; } } } // 7. حساب الكيلومترات الإضافية double extraKm = liveKm - plannedForRulesKm; if (plannedKm <= 0) { extraKm = liveKm - startKm; } if (extraKm < 0) extraKm = 0; // 8. الحساب النهائي final double extraCost = (extraMinutes * perMinEff) + (extraKm * perKmForType); // إضافة العمولة فقط على الزيادة return basePassengerQuote + (extraCost * (1.0 + kazanPct)); } // price = double.parse(totalCost); // for (int i = 0; i <= durationOfRide; i++) { // await Future.delayed(const Duration(seconds: 1)); // recentDistanceToDash = Get.find().totalDistance; // // rideTimerFromBegin = i; // if (int.parse(duration) + 300 > i) { // price = double.parse(totalCost); // } else { // if (startNameLocation.toLowerCase().contains('airport') || // endNameLocation.toLowerCase().contains('airport') || // startNameLocation.contains('مطار') || // startNameLocation.contains('المطار') || // endNameLocation.contains('مطار') || // endNameLocation.contains('المطار')) { // price = carType == 'Comfort' // || carType == 'Free Ride' // ? price + ((i ~/ 60) - int.parse(duration)) * latePrice // : carType == 'Lady' // ? price + ((i ~/ 60) - int.parse(duration)) * latePrice // : carType == 'RayehGaiComfort' // ? (i ~/ 60) * latePrice + // (recentDistanceToDash * // Get.find().comfortPrice) // : (i ~/ 60) * latePrice + // (recentDistanceToDash * // Get.find().mashwariPrice); // } else if (currentTime.hour >= 21 && currentTime.hour < 0) { // price = carType == 'Comfort' // || carType == 'Free Ride' // ? price + ((i ~/ 60) - int.parse(duration)) * latePrice // : carType == 'Lady' // ? price + ((i ~/ 60) - int.parse(duration)) * latePrice // : carType == 'RayehGaiComfort' // ? (i ~/ 60) * latePrice + // (recentDistanceToDash * // Get.find().comfortPrice) // : (i ~/ 60) * latePrice + // (recentDistanceToDash * // Get.find().mashwariPrice); // } else if (currentTime.hour >= 1 && currentTime.hour < 5) { // if (startNameLocation.contains('club') || // startNameLocation.contains('nightclub') || // startNameLocation.contains('ديسكو') || // startNameLocation.contains('ملهى ليلي') || // startNameLocation.contains('Night club')) { // price = carType == 'Comfort' // || carType == 'Free Ride' // ? (i ~/ 60) * (latePrice + .5) * 2 + // (price) - // int.parse(duration) * (latePrice + .5) * 2 // : carType == 'Lady' // ? (i ~/ 60) * (latePrice + .5) * 2 + // (price) - // int.parse(duration) * (latePrice + .5) * 2 // : carType == 'RayehGaiComfort' // ? (i ~/ 60) * (latePrice + .5) * 2 + (price) // : (i ~/ 60) * (latePrice + .5) * 2 + (price); // } // price = carType == 'Comfort' // || carType == 'Free Ride' // ? (latePrice + 0.5) * ((i ~/ 60) - int.parse(duration)) + price // : carType == 'Lady' // ? (latePrice + 0.5) * ((i ~/ 60) - int.parse(duration)) + // price // : carType == 'RayehGaiComfort' // ? (latePrice + 0.5) * ((i ~/ 60) - int.parse(duration)) + // price // : price; // } else if (currentTime.hour >= 14 && currentTime.hour <= 17) { // price = carType == 'Comfort' // || carType == 'Free Ride' // ? Get.find().heavyPrice * // ((i ~/ 60) - int.parse(duration)) + // price - // (0.5 * int.parse(duration)) // : carType == 'Lady' // ? Get.find().heavyPrice * // ((i ~/ 60) - int.parse(duration)) + // price - // (0.5 * int.parse(duration)) // : carType == 'RayehGaiComfort' // ? (i ~/ 60) * // (Get.find().heavyPrice) + // (recentDistanceToDash * // Get.find().comfortPrice) // : (i ~/ 60) * // (Get.find().heavyPrice) + // (recentDistanceToDash * // Get.find().mashwariPrice); // } else { // price = carType == 'Comfort' // || carType == 'Free Ride' // ? (i ~/ 60) + (price) - int.parse(duration) // : carType == 'Lady' // ? (i ~/ 60) + (price) - int.parse(duration) // : carType == 'RayehGaiComfort' // ? (i ~/ 60) + // (recentDistanceToDash * // Get.find().comfortPrice) // : (i ~/ 60) + // (recentDistanceToDash * // Get.find().mashwariPrice); // } // } // // $1 for each minute + $4 for each km // price = (price * double.parse(kazan)) + price; // Add 10% tax // speed = Get.find().speed * 3.6; // progressTimerRideBegin = i / durationOfRide; // remainingTimeTimerRideBegin = durationOfRide - i; // remainingTimeTimerRideBegin < 60 ? driverEndPage = 160 : 100; // updateMarker(); // if (remainingTimeTimerRideBegin < 60) { // // to make driver available on last 2 minute in his trip // box.write(BoxName.statusDriverLocation, 'off'); // } // int minutes = (remainingTimeTimerRideBegin / 60).floor(); // int seconds = remainingTimeTimerRideBegin % 60; // stringRemainingTimeRideBegin = // '$minutes:${seconds.toString().padLeft(2, '0')}'; // int minutes1 = (i / 60).floor(); // int seconds1 = i % 60; // stringRemainingTimeRideBegin1 = // '$minutes1:${seconds1.toString().padLeft(2, '0')}'; // update(); // } // } double recentDistanceToDash = 0; double recentAngelToMarker = 0; double speed = 0; void updateMarker() async { // Remove the existing marker with the ID `MyLocation`. markers.remove(MarkerId('MyLocation')); // Add a new marker with the ID `MyLocation` at the current location of the user. LocationController locationController = Get.find(); myLocation = locationController.myLocation; markers.add( Marker( markerId: MarkerId('MyLocation'.tr), position: myLocation, draggable: true, icon: carIcon, rotation: locationController.heading, // infoWindow: const InfoWindow( // title: 'Time', // ), ), ); // Animate camera only once after updating the marker // mapController!.animateCamera( // CameraUpdate.newLatLng(myLocation), // ); update(); } void addCustomCarIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 35), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/car.png', // mipmaps: false, ).then((value) { carIcon = value; update(); }); } void addCustomStartIcon() async { // Create the marker with the resized image ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/A.png', ).then((value) { startIcon = value; update(); }); } void addCustomEndIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(25, 25), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/b.png', ).then((value) { endIcon = value; update(); }); } void addCustomPassengerIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio // scale: 1.0, ); BitmapDescriptor.asset( config, 'assets/images/picker.png', ).then((value) { passengerIcon = value; update(); }); } var activeRouteSteps = >[]; var traveledPathPoints = []; // المسار المقطوع (رمادي) var upcomingPathPoints = []; // المسار المتبقي (أزرق/أحمر) // --- متغيرات الأيقونات والمواقع --- var heading = 0.0; // ... يمكنك إضافة أيقونات البداية والنهاية هنا // --- متغيرات قياس الأداء الذكي --- final List _performanceReadings = []; final int _readingsToCollect = 10; // اجمع 10 قراءات bool _hasMadeDecision = false; var updateInterval = 5.obs; // القيمة الافتراضية // --- متغيرات داخلية للملاحة --- var _stepBounds = []; var _stepEndPoints = []; var _allPointsForActiveRoute = []; bool _rayIntersectsSegment(LatLng point, LatLng vertex1, LatLng vertex2) { double px = point.longitude; double py = point.latitude; double v1x = vertex1.longitude; double v1y = vertex1.latitude; double v2x = vertex2.longitude; double v2y = vertex2.latitude; // Check if the point is outside the vertical bounds of the segment if ((py < v1y && py < v2y) || (py > v1y && py > v2y)) { return false; } // Calculate the intersection of the ray and the segment double intersectX = v1x + (py - v1y) * (v2x - v1x) / (v2y - v1y); // Check if the intersection is to the right of the point return intersectX > px; } // Function to check if the point is inside the polygon bool isPointInPolygon(LatLng point, List polygon) { int intersections = 0; for (int i = 0; i < polygon.length; i++) { LatLng vertex1 = polygon[i]; LatLng vertex2 = polygon[(i + 1) % polygon.length]; // Loop back to the start if (_rayIntersectsSegment(point, vertex1, vertex2)) { intersections++; } } // If the number of intersections is odd, the point is inside return intersections % 2 != 0; } String getLocationArea(double latitude, double longitude) { LatLng passengerPoint = LatLng(latitude, longitude); // 1. فحص الأردن if (isPointInPolygon(passengerPoint, CountryPolygons.jordanBoundary)) { box.write(BoxName.countryCode, 'Jordan'); // يمكنك تعيين AppLink.endPoint هنا إذا كان منطقك الداخلي لا يزال يعتمد عليه // box.write(BoxName.serverChosen, // AppLink.IntaleqSyriaServer); // مثال: اختر سيرفر سوريا للبيانات return 'Jordan'; } // 2. فحص سوريا if (isPointInPolygon(passengerPoint, CountryPolygons.syriaBoundary)) { box.write(BoxName.countryCode, 'Syria'); // box.write(BoxName.serverChosen, AppLink.IntaleqSyriaServer); return 'Syria'; } // 3. فحص مصر if (isPointInPolygon(passengerPoint, CountryPolygons.egyptBoundary)) { box.write(BoxName.countryCode, 'Egypt'); // box.write(BoxName.serverChosen, AppLink.IntaleqAlexandriaServer); return 'Egypt'; } // 4. الافتراضي (إذا كان خارج المناطق المخدومة) box.write(BoxName.countryCode, 'Jordan'); // box.write(BoxName.serverChosen, AppLink.IntaleqSyriaServer); return 'Unknown Location (Defaulting to Jordan)'; } // استبدل دالة getRoute الحالية في الكنترولر بهذا الكود المعدل // هذه النسخة تحتوي على خاصية إعادة المحاولة (Retry) وتستخدم API routec.intaleq.xyz // استبدل دالة getRoute الحالية في الكنترولر بهذا الكود المعدل // هذه النسخة تحتوي على خاصية إعادة المحاولة (Retry) وتستخدم API routec.intaleq.xyz Future getRoute({ required LatLng origin, required LatLng destination, required Color routeColor, }) async { // 1. إعداد المتغيرات // getLocationArea(origin.latitude, origin.longitude); String _dynamicApiUrl = 'https://routec.intaleq.xyz/route-jo'; final String _routeApiKey = Env.mapKeyOsm; var url = '$_dynamicApiUrl?origin=${origin.latitude},${origin.longitude}&destination=${destination.latitude},${destination.longitude}&steps=true&overview=full'; // 2. منطق التكرار (Retry Logic) var responseData; int retryCount = 0; const int maxRetries = 3; // عدد المحاولات القصوى while (retryCount < maxRetries) { try { if (retryCount > 0) { print("Retrying route fetch... Attempt ${retryCount + 1}"); } var response = await http.get( Uri.parse(url), headers: {'X-API-KEY': _routeApiKey}, ); if (response.statusCode == 200) { var decoded = jsonDecode(response.body); // التحقق من صلاحية البيانات (يجب أن تكون status == ok) if (decoded != null && decoded['status'] == 'ok') { responseData = decoded; print("Route fetched successfully on attempt ${retryCount + 1}"); break; // نجاح! الخروج من الحلقة } else { print("API returned status: ${decoded?['status']} (Not OK)"); } } else { print("Route API returned HTTP error: ${response.statusCode}"); } } catch (e) { print("Exception calling route API: $e"); } // إذا وصلنا هنا، فهذا يعني فشل المحاولة retryCount++; if (retryCount < maxRetries) { // انتظار ثانيتين قبل المحاولة التالية لتخفيف الضغط وإعطاء وقت للشبكة await Future.delayed(Duration(seconds: 2)); } } // 3. التحقق النهائي بعد انتهاء المحاولات if (responseData == null || responseData['status'] != 'ok') { print("Failed to fetch route after $maxRetries attempts."); // هنا يمكنك إظهار رسالة للمستخدم: "تعذر رسم المسار، يرجى التحقق من الشبكة" mySnackeBarError("تعذر رسم المسار، يرجى التحقق من الشبكة"); // isLoading.value = false; return; } // 4. معالجة البيانات (Parsing) - فقط إذا نجحنا في جلبها _resetRouteState(); // تنظيف الحالة القديمة try { // استخراج النقاط ورسم المسار final pointsString = responseData["polyline"]; // تأكد من أن دالة فك التشفير موجودة لديك _allPointsForActiveRoute = decodePolylineToLatLng(pointsString); upcomingPathPoints.assignAll(_allPointsForActiveRoute); // استخراج الخطوات final stepsList = List>.from(responseData['steps']); // تعديل هيكلة الخطوات لتتناسب مع الكود القديم for (var step in stepsList) { // إنشاء التعليمات من الـ maneuver step['html_instructions'] = _createInstructionFromManeuver(step); // ضبط الموقع النهائي للخطوة if (step['maneuver'] != null && step['maneuver']['location'] != null) { var loc = step['maneuver']['location']; // [lng, lat] step['end_location'] = {'lat': loc[1], 'lng': loc[0]}; } } activeRouteSteps.assignAll(stepsList); _prepareStepData(activeRouteSteps); // نطق التعليمات الأولية if (activeRouteSteps.isNotEmpty) { currentInstruction = _parseInstruction(activeRouteSteps[0]['html_instructions']); if (isTtsEnabled) { if (Get.isRegistered()) { Get.find().speakText(currentInstruction); } else { Get.put(TextToSpeechController()).speakText(currentInstruction); } } } // تحديث حدود الكاميرا (Bounds) if (_allPointsForActiveRoute.isNotEmpty) { final bounds = _boundsFromLatLngList(_allPointsForActiveRoute); _fitToBounds(bounds); } update(); // تحديث الواجهة } catch (e) { print("Critical Error parsing route data: $e"); // هذا الـ Catch يحميك من أي تغيير غير متوقع في شكل البيانات القادمة من السيرفر } } String _createInstructionFromManeuver(Map step) { final maneuver = step['maneuver']; final type = maneuver['type'] ?? 'continue'; final modifier = maneuver['modifier'] ?? 'straight'; final name = step['name'] ?? ''; String instruction = ""; switch (type) { case 'depart': instruction = "انطلق"; break; case 'arrive': instruction = "لقد وصلت إلى وجهتك"; if (name.isNotEmpty) instruction += "، $name"; return instruction; case 'turn': case 'fork': case 'off ramp': case 'on ramp': case 'roundabout': instruction = _getTurnInstruction(modifier); break; case 'continue': instruction = "استمر"; break; default: instruction = "اتجه"; } if (name.isNotEmpty) { if (instruction == "استمر") { instruction += " على $name"; } else { instruction += " إلى $name"; } } else if (type == 'continue' && modifier == 'straight') { instruction = "استمر بشكل مستقيم"; } return instruction; } /** * دالة مساعدة لترجمة تعليمات الانعطاف */ String _getTurnInstruction(String modifier) { switch (modifier) { case 'uturn': return "قم بالاستدارة والعودة"; case 'sharp right': return "انعطف يمينًا بحدة"; case 'right': return "انعطف يمينًا"; case 'slight right': return "انعطف يمينًا قليلاً"; case 'straight': return "استمر بشكل مستقيم"; case 'slight left': return "انعطف يسارًا قليلاً"; case 'left': return "انعطف يسارًا"; case 'sharp left': return "انعطف يسارًا بحدة"; default: return "اتجه"; } } /** * دالة لحساب حدود الخريطة (Bounds) من قائمة نقاط */ LatLngBounds _boundsFromLatLngList(List list) { assert(list.isNotEmpty); double? x0, x1, y0, y1; for (LatLng latLng in list) { if (x0 == null) { x0 = x1 = latLng.latitude; y0 = y1 = latLng.longitude; } else { if (latLng.latitude > x1!) x1 = latLng.latitude; if (latLng.latitude < x0) x0 = latLng.latitude; if (latLng.longitude > y1!) y1 = latLng.longitude; if (latLng.longitude < y0!) y0 = latLng.longitude; } } return LatLngBounds( northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!)); } // // دالة موحّدة وقوية لجلب أي مسار // Future getRoute({ // required LatLng origin, // required LatLng destination, // required Color routeColor, // }) async { // // إظهار مؤشر التحميل لو رغبت // // isLoading.value = true; // var url = // ('${AppLink.googleMapsLink}directions/json?language=ar&destination=${destination.latitude},${destination.longitude}&origin=${origin.latitude},${origin.longitude}&key=${AK.mapAPIKEY}'); // var response = await CRUD().getGoogleApi(link: url, payload: {}); // if (response == null || response['routes'].isEmpty) { // // isLoading.value = false; // // أظهر رسالة خطأ // return; // } // _resetRouteState(); // تنظيف الحالة القديمة قبل رسم الجديد // final route = response['routes'][0]; // final leg = route['legs'][0]; // // استخراج النقاط ورسم المسار المبدئي بالكامل // final pointsString = route["overview_polyline"]["points"]; // _allPointsForActiveRoute = decodePolylineToLatLng(pointsString); // upcomingPathPoints.assignAll(_allPointsForActiveRoute); // // استخراج خطوات الملاحة // activeRouteSteps.assignAll(List>.from(leg['steps'])); // _prepareStepData(activeRouteSteps); // // تحديث التعليمات الأولية // if (activeRouteSteps.isNotEmpty) { // currentInstruction = // _parseInstruction(activeRouteSteps[0]['html_instructions']); // Get.isRegistered() // ? Get.find().speakText(currentInstruction) // : Get.put(TextToSpeechController()).speakText(currentInstruction); // } // // تحديث الكاميرا لتناسب المسار الجديد // final boundsData = route["bounds"]; // _fitToBounds(LatLngBounds( // northeast: LatLng( // boundsData['northeast']['lat'], boundsData['northeast']['lng']), // southwest: LatLng( // boundsData['southwest']['lat'], boundsData['southwest']['lng']), // )); // // isLoading.value = false; // update(); // تحديث الواجهة مرة واحدة بعد كل العمليات // } // الدالة التي يتم استدعاؤها من خدمة الموقع كل 5 ثوان (أو حسب الفترة المحددة) void onLocationUpdated(Position newPosition) { myLocation = LatLng(newPosition.latitude, newPosition.longitude); heading = newPosition.heading; // -->> منطق قياس الأداء يبدأ هنا <<-- final stopwatch = Stopwatch()..start(); // -->> منطق الملاحة وتحديث المسار <<-- _onLocationTick(myLocation); stopwatch.stop(); // -->> تحليل الأداء واتخاذ القرار <<-- if (!_hasMadeDecision) { _performanceReadings.add(stopwatch.elapsedMilliseconds); if (_performanceReadings.length >= _readingsToCollect) { _analyzePerformance(); _hasMadeDecision = true; } } } // ================================================================= // 3. منطق الملاحة الداخلي (Internal Navigation Logic) // ================================================================= void _onLocationTick(LatLng pos) { if (activeRouteSteps.isEmpty || currentStepIndex >= _stepBounds.length) { return; } final double dToEnd = _distanceMeters(pos, _stepEndPoints[currentStepIndex]); if (dToEnd <= 35) { // 35 متر عتبة للوصول لنهاية الخطوة _advanceStep(); } } void _advanceStep() { if (currentStepIndex >= _stepBounds.length - 1) { // وصل للنهاية currentInstruction = "لقد وصلت إلى وجهتك"; return; } currentStepIndex++; currentInstruction = _parseInstruction( activeRouteSteps[currentStepIndex]['html_instructions']); Get.isRegistered() ? Get.find().speakText(currentInstruction) : Get.put(TextToSpeechController()).speakText(currentInstruction); // -->> هنا يتم تحديث لون المسار <<-- _updateTraveledPath(); _fitToBounds(_stepBounds[currentStepIndex], padding: 80); // تقريب الكاميرا على الخطوة التالية update(); } void _updateTraveledPath() { // استخراج كل النقاط للخطوات التي تم اجتيازها List pointsForTraveledSteps = []; for (int i = 0; i < currentStepIndex; i++) { final stepPolyline = activeRouteSteps[i]['polyline']['points']; pointsForTraveledSteps.addAll(decodePolylineToLatLng(stepPolyline)); } traveledPathPoints.assignAll(pointsForTraveledSteps); } void _prepareStepData(List> steps) { _stepBounds.clear(); _stepEndPoints.clear(); for (final s in steps) { // 1. استخراج نقطة النهاية (الكود الحالي سليم) final end = s['end_location']; _stepEndPoints.add(LatLng( (end['lat'] as num).toDouble(), (end['lng'] as num).toDouble(), )); // 2. فك تشفير البوليلاين الخاص بالخطوة وتحويله إلى LatLng // -->> هنا تم التصحيح <<-- List pts = decodePolyline(s['polyline']['points']) .map((point) => LatLng(point[0].toDouble(), point[1].toDouble())) .toList(); // أضف نقاط البداية والنهاية إذا لم تكن موجودة في البوليلاين لضمان دقة الحدود if (pts.isNotEmpty) { final start = s['start_location']; final startLatLng = LatLng( (start['lat'] as num).toDouble(), (start['lng'] as num).toDouble()); if (pts.first != startLatLng) { pts.insert(0, startLatLng); } } _stepBounds.add(_boundsFromPoints(pts)); } } // A helper function to decode and convert the polyline string List decodePolylineToLatLng(String polylineString) { // 1. Decode the string into a list of number lists (e.g., [[lat, lng], ...]) List> decodedPoints = decodePolyline(polylineString); // 2. Map each [lat, lng] pair to a LatLng object, ensuring conversion to double List latLngPoints = decodedPoints .map((point) => LatLng(point[0].toDouble(), point[1].toDouble())) .toList(); return latLngPoints; } // ================================================================= // 4. منطق الأداء الذكي (Smart Performance Logic) // ================================================================= void _analyzePerformance() { final int sum = _performanceReadings.reduce((a, b) => a + b); final double averageTime = sum / _performanceReadings.length; if (averageTime > 1000) { // إذا كانت العملية تستغرق أكثر من ثانية _suggestOptimization(); } } void _suggestOptimization() { Get.snackbar( "تحسين أداء التطبيق", "لضمان أفضل تجربة، نقترح تعديل الإعدادات لتناسب جهازك. هل تود المتابعة؟", duration: const Duration(seconds: 15), mainButton: TextButton( child: const Text("نعم، قم بالتحسين"), onPressed: () { updateInterval.value = 8; // غير الفترة إلى 8 ثوانٍ // save setting to shared_preferences box.write(BoxName.updateInterval, 8); Get.back(); }, ), ); } // ================================================================= // 5. دوال مساعدة (Helper Functions) // ================================================================= void _resetRouteState() { activeRouteSteps.clear(); traveledPathPoints.clear(); upcomingPathPoints.clear(); _allPointsForActiveRoute.clear(); currentStepIndex = 0; } String _parseInstruction(String html) => html.replaceAll(RegExp(r'<[^>]*>'), ''); Future _fitToBounds(LatLngBounds b, {double padding = 60}) async { // نستخدم الدالة الآمنة التي أنشأناها await safeAnimateCamera(CameraUpdate.newLatLngBounds(b, padding)); } double distanceBetweenDriverAndPassengerWhenConfirm = 0; getMap(String origin, destination) async { isLoading = false; update(); var url = ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}'); var response = await CRUD().getGoogleApi(link: url, payload: {}); Log.print('response: $response'); data = response['routes'][0]['legs']; distanceBetweenDriverAndPassengerWhenConfirm = (data[0]['distance']['value']) / 1000; final points = decodePolyline(response["routes"][0]["overview_polyline"]["points"]); for (int i = 0; i < points.length; i++) { double lat = points[i][0].toDouble(); double lng = points[i][1].toDouble(); polylineCoordinates.add(LatLng(lat, lng)); } if (polyLines.isNotEmpty) { clearPolyline(); var polyline = Polyline( polylineId: PolylineId(response["routes"][0]["summary"]), points: polylineCoordinates, width: 10, color: AppColor.blueColor, ); polyLines.add(polyline); // rideConfirm = false; update(); } else { var polyline = Polyline( polylineId: PolylineId(response["routes"][0]["summary"]), points: polylineCoordinates, width: 10, color: AppColor.blueColor, ); // final dataBounds = response["routes"][0]["bounds"]; // updateCameraFromBoundsAfterGetMap(dataBounds); // Fit the camera to the bounds polyLines.add(polyline); // rideConfirm = false; // Define the northeast and southwest coordinates final bounds = response["routes"][0]["bounds"]; LatLng northeast = LatLng(bounds['northeast']['lat'], bounds['northeast']['lng']); LatLng southwest = LatLng(bounds['southwest']['lat'], bounds['southwest']['lng']); // Create the LatLngBounds object boundsData = LatLngBounds(northeast: northeast, southwest: southwest); // Fit the camera to the bounds var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData!, 140); await safeAnimateCamera(cameraUpdate); update(); } } void checkForNextStep(LatLng currentPosition) { if (currentStepIndex >= routeSteps.length) return; final step = routeSteps[currentStepIndex]; final endLocation = step['end_location']; final endLatLng = LatLng(endLocation['lat'], endLocation['lng']); final distance = calculateDistance( currentPosition.latitude, currentPosition.longitude, endLatLng.latitude, endLatLng.longitude, ); if (distance < 50) { // 50 متر قبل النقطة currentStepIndex++; if (currentStepIndex < routeSteps.length) { currentInstruction = _parseInstruction( routeSteps[currentStepIndex]['html_instructions']); Get.isRegistered() ? Get.find().speakText(currentInstruction) : Get.put(TextToSpeechController()).speakText(currentInstruction); Log.print('Current Instruction: $currentInstruction'); update(); } } } /// Calculates the distance in meters between two latitude/longitude points. double calculateDistance(double lat1, double lon1, double lat2, double lon2) { const double earthRadius = 6371000; // meters double dLat = _degreesToRadians(lat2 - lat1); double dLon = _degreesToRadians(lon2 - lon1); double a = (sin(dLat / 2) * sin(dLat / 2)) + cos(_degreesToRadians(lat1)) * cos(_degreesToRadians(lat2)) * (sin(dLon / 2) * sin(dLon / 2)); double c = 2 * atan2(sqrt(a), sqrt(1 - a)); double distance = earthRadius * c; return distance; } double _degreesToRadians(double degrees) { return degrees * (3.1415926535897932 / 180.0); } // String _parseInstruction(String htmlInstruction) { // return htmlInstruction.replaceAll(RegExp(r'<[^>]*>'), ''); // } void checkDestinationProximity() { final distance = calculateDistance( myLocation.latitude, myLocation.longitude, latLngPassengerDestination.latitude, latLngPassengerDestination.longitude, ); if (distance < 300) { // 300 متر قبل الوجهة // Get.find().sendNotificationToDriverMAP( // "You are near the destination", // "You are near the destination".tr, // tokenPassenger, // [ // box.read(BoxName.driverID), // rideId, // box.read(BoxName.tokenDriver), // paymentAmount.toString() // ], // 'ding.wav', // ); NotificationService.sendNotification( target: tokenPassenger.toString(), title: "You are near the destination".tr, body: "You are near the destination".tr, isTopic: false, // Important: this is a token tone: 'ding', driverList: [ box.read(BoxName.driverID), rideId, box.read(BoxName.tokenDriver), paymentAmount.toString() ], category: "You are near the destination", ); // يمكن إضافة أي إجراء آخر هنا عند الاقتراب من الوجهة } } List stepBounds = []; List stepEndPoints = []; List stepInstructions = []; StreamSubscription? _posSub; DateTime _lastCameraUpdateTs = DateTime.fromMillisecondsSinceEpoch(0); getMapDestination(String origin, destination) async { var url = ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}'); var response = await CRUD().getGoogleApi(link: url, payload: {}); dataDestination = response['routes'][0]['legs']; final points = decodePolyline(response["routes"][0]["overview_polyline"]["points"]); polylineCoordinatesDestination.clear(); for (int i = 0; i < points.length; i++) { double lat = points[i][0].toDouble(); double lng = points[i][1].toDouble(); polylineCoordinatesDestination.add(LatLng(lat, lng)); } // الخطوات من أول leg routeSteps = List>.from(dataDestination[0]['steps']); // حضّر بيانات كل step _prepareStepData(routeSteps); currentStepIndex = 0; if (stepInstructions.isNotEmpty) { currentInstruction = _parseInstruction(stepInstructions[0]); Log.print('currentInstruction: $currentInstruction'); Get.isRegistered() ? Get.find().speakText(currentInstruction) : Get.put(TextToSpeechController()).speakText(currentInstruction); } // ارسم الـ polyline الرئيسي (مثل ما لديك) final summary = response["routes"][0]["summary"]; final polyline = Polyline( polylineId: PolylineId(summary.isEmpty ? 'route' : summary), points: polylineCoordinatesDestination, width: 10, color: AppColor.redColor, ); polyLinesDestination.add(polyline); // fit للخريطة على أول step if (stepBounds.isNotEmpty) { _fitToBounds(stepBounds[0]); } update(); // // ابدأ التتبع الحيّ لخطوات الملاحة // await startListeningStepNavigation(); } // ———————————————————————————————————————————————————————————————— // يُنادى عند كل تحديث للموقع // void _onLocationTick(LatLng pos) async { // if (routeSteps.isEmpty || currentStepIndex >= stepBounds.length) return; // // إذا تجاوزت نهاية الـ step الحالية بمسافة صغيرة -> انتقل // final double dToEnd = _distanceMeters(pos, stepEndPoints[currentStepIndex]); // final bool nearEnd = dToEnd <= 25; // عتبة 25م (عدّلها حسب حاجتك) // // إذا دخلت نطاق الـ step التالية -> انتقل // bool insideNext = false; // if (currentStepIndex < stepBounds.length - 1) { // insideNext = _contains(stepBounds[currentStepIndex + 1], pos); // } // if (nearEnd || insideNext) { // _advanceStep(); // return; // } // // تحديث الكاميرا بشكل خفيف أثناء الحركة (كل 2 ثانية مثلاً) // final now = DateTime.now(); // if (now.difference(_lastCameraUpdateTs).inMilliseconds > 2000) { // _lastCameraUpdateTs = now; // // ركّز على bounds الحالية مع الحفاظ على تتبّع عام // _fitToBounds(stepBounds[currentStepIndex], padding: 60); // } // } LatLngBounds _boundsFromPoints(List pts) { double? minLat, maxLat, minLng, maxLng; for (final p in pts) { minLat = (minLat == null) ? p.latitude : math.min(minLat, p.latitude); maxLat = (maxLat == null) ? p.latitude : math.max(maxLat, p.latitude); minLng = (minLng == null) ? p.longitude : math.min(minLng, p.longitude); maxLng = (maxLng == null) ? p.longitude : math.max(maxLng, p.longitude); } return LatLngBounds( southwest: LatLng(minLat ?? 0, minLng ?? 0), northeast: LatLng(maxLat ?? 0, maxLng ?? 0), ); } bool _contains(LatLngBounds b, LatLng p) { final south = math.min(b.southwest.latitude, b.northeast.latitude); final north = math.max(b.southwest.latitude, b.northeast.latitude); final west = math.min(b.southwest.longitude, b.northeast.longitude); final east = math.max(b.southwest.longitude, b.northeast.longitude); return (p.latitude >= south && p.latitude <= north && p.longitude >= west && p.longitude <= east); } double _distanceMeters(LatLng a, LatLng b) { // هافرساين مبسطة const R = 6371000.0; // m final dLat = _deg2rad(b.latitude - a.latitude); final dLng = _deg2rad(b.longitude - a.longitude); final s1 = math.sin(dLat / 2); final s2 = math.sin(dLng / 2); final aa = s1 * s1 + math.cos(_deg2rad(a.latitude)) * math.cos(_deg2rad(b.latitude)) * s2 * s2; final c = 2 * math.atan2(math.sqrt(aa), math.sqrt(1 - aa)); return R * c; } double _deg2rad(double d) => d * math.pi / 180.0; // تحريك الكاميرا لباوند معيّن // Future _fitToBounds(LatLngBounds b, {double padding = 40}) async { // if (mapController == null) return; // try { // // أحياناً يلزم انتظار فريم حتى تكون الخريطة مرسومة // await Future.delayed(const Duration(milliseconds: 50)); // await mapController!.animateCamera( // CameraUpdate.newLatLngBounds(b, padding), // ); // } catch (_) { // // fallback لو حصلت مشكلة الحجم // final center = LatLng( // (b.northeast.latitude + b.southwest.latitude) / 2, // (b.northeast.longitude + b.southwest.longitude) / 2, // ); // await mapController!.animateCamera(CameraUpdate.newLatLng(center)); // } // } // الانتقال للخطوة التالية وتحديث التعليمات والكاميرا // void _advanceStep() { // if (currentStepIndex >= stepBounds.length - 1) return; // currentStepIndex++; // currentInstruction = _parseInstruction(stepInstructions[currentStepIndex]); // // نطق التعليمات // if (Get.isRegistered()) { // Get.find().speakText(currentInstruction); // } else { // Get.put(TextToSpeechController()).speakText(currentInstruction); // } // // تركيز الكاميرا على باوند الخطوة الجديدة // _fitToBounds(stepBounds[currentStepIndex]); // update(); // } // void _prepareStepData(List> steps) { // stepBounds.clear(); // stepEndPoints.clear(); // stepInstructions.clear(); // for (final s in steps) { // // 1) instruction // final html = (s['html_instructions'] ?? '').toString(); // stepInstructions.add(html); // // 2) end point // final end = s['end_location']; // final endLatLng = LatLng( // (end['lat'] as num).toDouble(), (end['lng'] as num).toDouble()); // stepEndPoints.add(endLatLng); // // 3) bounds من الـ polyline (إن لم يوجد bounds جاهز من الـ API) // List pts = []; // if (s['polyline'] != null && s['polyline']['points'] != null) { // final decoded = decodePolyline(s['polyline']['points']); // for (var p in decoded) { // pts.add(LatLng((p[0] as num).toDouble(), (p[1] as num).toDouble())); // } // } else { // // fallback: استخدم start/end فقط // final start = s['start_location']; // pts.add(LatLng((start['lat'] as num).toDouble(), // (start['lng'] as num).toDouble())); // pts.add(endLatLng); // } // stepBounds.add(_boundsFromPoints(pts)); // } // } // getMapDestination(String origin, destination) async { // var url = // ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}'); // var response = await CRUD().getGoogleApi(link: url, payload: {}); // dataDestination = response['routes'][0]['legs']; // final points = // decodePolyline(response["routes"][0]["overview_polyline"]["points"]); // for (int i = 0; i < points.length; i++) { // double lat = points[i][0].toDouble(); // double lng = points[i][1].toDouble(); // polylineCoordinatesDestination.add(LatLng(lat, lng)); // } // // استخراج الخطوات // routeSteps = List>.from(dataDestination[0]['steps']); // Log.print('routeSteps: ${routeSteps}'); // currentStepIndex = 0; // if (routeSteps.isNotEmpty) { // currentInstruction = // _parseInstruction(routeSteps[0]['html_instructions']); // Log.print('currentInstruction: ${currentInstruction}'); // Get.isRegistered() // ? Get.find().speakText(currentInstruction) // : Get.put(TextToSpeechController()).speakText(currentInstruction); // } // update(); // // دالة مساعدة لتنظيف التعليمات // if (polyLinesDestination.isNotEmpty) { // // clearPolyline(); // var polyline = Polyline( // polylineId: PolylineId(response["routes"][0]["summary"]), // points: polylineCoordinatesDestination, // width: 10, // color: AppColor.redColor, // ); // polyLinesDestination.add(polyline); // // rideConfirm = false; // update(); // } else { // var polyline = Polyline( // polylineId: PolylineId(response["routes"][0]["summary"]), // points: polylineCoordinatesDestination, // width: 10, // color: AppColor.redColor, // ); // // final dataBounds = response["routes"][0]["bounds"]; // // updateCameraFromBoundsAfterGetMap(dataBounds); // // polyLinesDestination.add(polyline); // // rideConfirm = false; // // Define the northeast and southwest coordinates // update(); // } // } void updateCameraFromBoundsAfterGetMap(dynamic response) { final bounds = response["routes"][0]["bounds"]; LatLng northeast = LatLng(bounds['northeast']['lat'], bounds['northeast']['lng']); LatLng southwest = LatLng(bounds['southwest']['lat'], bounds['southwest']['lng']); // Create the LatLngBounds object LatLngBounds boundsData = LatLngBounds(northeast: northeast, southwest: southwest); // Fit the camera to the bounds var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 140); safeAnimateCamera(cameraUpdate); } void changePassengerInfoWindow() { isPassengerInfoWindow = !isPassengerInfoWindow; passengerInfoWindowHeight = isPassengerInfoWindow == true ? 200 : 0; update(); } double mpg = 0; calculateConsumptionFuel() { mpg = Get.find().fuelPrice / 12; //todo in register car add mpg in box update(); } argumentLoading() async { try { passengerLocation = Get.arguments['passengerLocation']; passengerDestination = Get.arguments['passengerDestination']; duration = Get.arguments['Duration']; totalCost = Get.arguments['totalCost']; passengerId = Get.arguments['passengerId']; driverId = Get.arguments['driverId']; distance = Get.arguments['Distance']; passengerName = Get.arguments['name']; passengerEmail = Get.arguments['email']; totalPricePassenger = Get.arguments['totalPassenger']; passengerPhone = Get.arguments['phone']; walletChecked = Get.arguments['WalletChecked']; tokenPassenger = Get.arguments['tokenPassenger']; direction = Get.arguments['direction']; durationToPassenger = Get.arguments['DurationToPassenger']; rideId = Get.arguments['rideId']; durationOfRideValue = Get.arguments['durationOfRideValue']; paymentAmount = Get.arguments['paymentAmount']; paymentMethod = Get.arguments['paymentMethod']; isHaveSteps = Get.arguments['isHaveSteps']; step0 = Get.arguments['step0']; step1 = Get.arguments['step1']; step2 = Get.arguments['step2']; step3 = Get.arguments['step3']; step4 = Get.arguments['step4']; passengerWalletBurc = Get.arguments['passengerWalletBurc']; timeOfOrder = Get.arguments['timeOfOrder']; carType = Get.arguments['carType']; kazan = Get.arguments['kazan']; startNameLocation = Get.arguments['startNameLocation']; endNameLocation = Get.arguments['endNameLocation']; // Parse to double latlng(passengerLocation, passengerDestination); String lat = Get.find().myLocation.latitude.toString(); String lng = Get.find().myLocation.longitude.toString(); String origin = '$lat,$lng'; // Set the origin and destination coordinates for the Google Maps directions request. Future.delayed(const Duration(seconds: 1)); getRoute( origin: Get.find().myLocation, destination: latLngPassengerLocation, routeColor: Colors.yellow // أو أي لون ); update(); } catch (e) { Log.print("Error parsing arguments: $e"); } } latlng(String passengerLocation, passengerDestination) { double latPassengerLocation = double.parse(passengerLocation.toString().split(',')[0]); double lngPassengerLocation = double.parse(passengerLocation.toString().split(',')[1]); double latPassengerDestination = double.parse(passengerDestination.toString().split(',')[0]); double lngPassengerDestination = double.parse(passengerDestination.toString().split(',')[1]); latLngPassengerLocation = LatLng(latPassengerLocation, lngPassengerLocation); latLngPassengerDestination = LatLng(latPassengerDestination, lngPassengerDestination); } late Duration durationToAdd; int hours = 0; int minutes = 0; String carType = ''; late String kazan; late String startNameLocation; late String endNameLocation; Future runGoogleMapDirectly() async { if (box.read(BoxName.googlaMapApp) == true) { if (Platform.isAndroid) { Bubble().startBubbleHead(sendAppToBackground: true); } await openGoogleMapFromDriverToPassenger(); } } @override void onInit() async { mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY); // Get the passenger location from the arguments. await argumentLoading(); Get.put(FirebaseMessagesController()); runGoogleMapDirectly(); addCustomCarIcon(); addCustomPassengerIcon(); addCustomStartIcon(); addCustomEndIcon(); // updateMarker(); // updateLocation(); startTimerToShowPassengerInfoWindowFromDriver(); durationToAdd = Duration(seconds: int.parse(duration)); hours = durationToAdd.inHours; minutes = (durationToAdd.inMinutes % 60).round(); calculateConsumptionFuel(); updateLocation(); // cancelCheckRidefromPassenger(); // checkIsDriverNearPassenger(); super.onInit(); } Timer? _navigationTimer; Future startListeningStepNavigation() async { _posSub?.cancel(); _navigationTimer?.cancel(); // إلغاء التايمر لأنه يسبب تأخير _posSub = Geolocator.getPositionStream( locationSettings: LocationSettings( accuracy: LocationAccuracy.high, distanceFilter: 10, // تحديث كل 10 أمتار ), ).listen((position) { myLocation = LatLng(position.latitude, position.longitude); heading = position.heading; // استدعاء منطق التوجيه فوراً عند تغير الموقع if (!isClosed) { onLocationUpdated(position); update(); } }); } void stopListeningStepNavigation() { _posSub?.cancel(); _posSub = null; } } double safeParseDouble(dynamic value, {double defaultValue = 0.0}) { if (value == null) return defaultValue; if (value is double) return value; if (value is int) return value.toDouble(); return double.tryParse(value.toString()) ?? defaultValue; } int safeParseInt(dynamic value, {int defaultValue = 0}) { if (value == null) return defaultValue; if (value is int) return value; return int.tryParse(value.toString()) ?? defaultValue; } ================================================== FILE PATH: ./lib/controller/home/captin/model.dart ================================================== import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class NavigationStep { final String instruction; final String maneuver; final double distance; final String duration; final LatLng startLocation; final LatLng endLocation; final String htmlInstructions; NavigationStep({ required this.instruction, required this.maneuver, required this.distance, required this.duration, required this.startLocation, required this.endLocation, required this.htmlInstructions, }); factory NavigationStep.fromJson(Map json) { return NavigationStep( instruction: json['html_instructions'] ?? '', maneuver: json['maneuver'] ?? 'straight', distance: (json['distance']['value'] ?? 0).toDouble(), duration: json['duration']['text'] ?? '', startLocation: LatLng( json['start_location']['lat'].toDouble(), json['start_location']['lng'].toDouble(), ), endLocation: LatLng( json['end_location']['lat'].toDouble(), json['end_location']['lng'].toDouble(), ), htmlInstructions: json['html_instructions'] ?? '', ); } // Get clean instruction text (remove HTML tags) String get cleanInstruction { return instruction .replaceAll(RegExp(r'<[^>]*>'), '') .replaceAll(' ', ' '); } // Get instruction icon based on maneuver IconData get instructionIcon { switch (maneuver.toLowerCase()) { case 'turn-left': return Icons.turn_left; case 'turn-right': return Icons.turn_right; case 'turn-slight-left': return Icons.turn_slight_left; case 'turn-slight-right': return Icons.turn_slight_right; case 'turn-sharp-left': return Icons.turn_sharp_left; case 'turn-sharp-right': return Icons.turn_sharp_right; case 'uturn-left': case 'uturn-right': return Icons.u_turn_left; case 'straight': return Icons.straight; case 'ramp-left': return Icons.ramp_left; case 'ramp-right': return Icons.ramp_right; case 'merge': return Icons.merge; case 'fork-left': case 'fork-right': return Icons.call_split; case 'ferry': return Icons.directions_boat; case 'roundabout-left': case 'roundabout-right': return Icons.roundabout_left; default: return Icons.navigation; } } } ================================================== FILE PATH: ./lib/controller/home/captin/help/maintain_center_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:get/get.dart'; class MaintainCenterController extends GetxController { bool isLoading = false; Map tripCount = {}; Future getTripCountByCaptain() async { var res = await CRUD().get(link: AppLink.getTripCountByCaptain, payload: { "driver_id": box.read(BoxName.driverID).toString(), }); if (res != 'failure') { tripCount = jsonDecode(res)['message']; update(); } } } ================================================== FILE PATH: ./lib/controller/home/captin/help/assurance_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; class AssuranceHealthController extends GetxController { bool isLoading = false; Map tripCount = {}; Future getTripCountByCaptain() async { var res = await CRUD().get(link: AppLink.getTripCountByCaptain, payload: { "driver_id": box.read(BoxName.driverID).toString(), }); if (res != 'failure') { tripCount = jsonDecode(res)['message']; update(); } } Future addDriverHealthAssurance({ String? driverId, String? assured, required String healthInsuranceProvider, }) async { // Define the URL to your PHP backend // Data to be sent to the backend Map data = { "driver_id": box.read(BoxName.driverID).toString(), "assured": '1', "health_insurance_provider": healthInsuranceProvider, }; try { // Send the POST request to your backend var response = await CRUD() .post(link: AppLink.addHealthInsuranceProvider, payload: data); if (response != 'failure') { // Handle success (e.g., show a success message) mySnackbarSuccess( "You have successfully opted for health insurance.".tr); } else { // Handle failure (e.g., show an error message) print("Failed to save health assurance data"); mySnackeBarError("Please enter a health insurance status.".tr); } } catch (e) { // Handle any errors print("Error: $e"); } } } ================================================== FILE PATH: ./lib/controller/home/captin/help/help_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/links.dart'; import '../../../../constant/style.dart'; import '../../../../main.dart'; import '../../../../views/widgets/elevated_btn.dart'; import '../../../functions/crud.dart'; import '../../../functions/encrypt_decrypt.dart'; class HelpController extends GetxController { bool isLoading = false; final formKey = GlobalKey(); final helpQuestionController = TextEditingController(); Map helpQuestionDate = {}; Map helpQuestionRepleyDate = {}; String status = ''; String qustion = ''; late int indexQuestion = 0; getIndex(int i, String qustion1) async { indexQuestion = i; qustion = qustion1; update(); } void addHelpQuestion() async { isLoading = true; update(); var res = await CRUD().post(link: AppLink.addhelpCenter, payload: { 'driverID': box.read(BoxName.driverID).toString(), 'helpQuestion': (helpQuestionController.text) }); var d = jsonDecode(res); isLoading = false; update(); if (d['status'].toString() == 'success') { getHelpQuestion(); // Get.snackbar('Feedback data saved successfully'.tr, '', // backgroundColor: AppColor.greenColor, // snackPosition: SnackPosition.BOTTOM); } } void getHelpQuestion() async { isLoading = true; update(); var res = await CRUD().get(link: AppLink.gethelpCenter, payload: { 'driverID': box.read(BoxName.driverID).toString(), }); if (res == "failure") { isLoading = false; update(); Get.defaultDialog( title: 'There is no help Question here'.tr, titleStyle: AppStyle.title, middleText: '', confirm: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Add Question'.tr, onPressed: () { Get.back(); }), MyElevatedButton( title: 'Back'.tr, onPressed: () { Get.back(); Get.back(); }), ], )); } helpQuestionDate = jsonDecode(res); isLoading = false; update(); } Future getHelpRepley(String id) async { isLoading = true; update(); var res = await CRUD().get(link: AppLink.getByIdhelpCenter, payload: { 'id': id, }); if (res == "failure") { status = 'not yet'; isLoading = false; update(); } helpQuestionRepleyDate = jsonDecode(res); isLoading = false; update(); } @override void onInit() { getHelpQuestion(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/home/captin/help/video_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/print.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; import 'package:video_player/video_player.dart'; class VideoController extends GetxController { var videos = []; var isLoading = true.obs; final String apiUrl = '${AppLink.seferCairoServer}/ride/videos_driver/get.php'; @override void onInit() { fetchVideos(); super.onInit(); } late VideoPlayerController videoPlayerController; // Initialize the video player with the provided URL Future initializeVideo(String videoUrl) async { videoPlayerController = VideoPlayerController.networkUrl(Uri.parse(videoUrl)); await videoPlayerController.initialize(); videoPlayerController .setLooping(true); // Set to true if you want the video to loop update(); // Update the UI after the video has been initialized } // Play the video void play() { videoPlayerController.play(); update(); } // Pause the video void pause() { videoPlayerController.pause(); update(); } @override void onClose() { videoPlayerController .dispose(); // Dispose of the video player controller when not in use super.onClose(); } void fetchVideos() async { try { var res = await CRUD().get(link: apiUrl, payload: {}); if (res != 'failure') { videos = jsonDecode(res)['message']; // Log.print('videos: ${videos}'); update(); } else { mySnackeBarError(''); } } catch (e) { mySnackeBarError(e.toString()); } finally { isLoading(false); } } } ================================================== FILE PATH: ./lib/controller/home/payment/paymob_payout.dart ================================================== import 'dart:convert'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; import '../../../constant/links.dart'; import '../../../views/widgets/mydialoug.dart'; import '../../functions/crud.dart'; import 'captain_wallet_controller.dart'; class PaymobPayout extends GetxController { bool isLoading = false; String dropdownValue = 'etisalat'; int payOutFee = 5; payToDriverWallet(String amount, String issuer, String msisdn) async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { // var dec = await CRUD() // .postWallet(link: AppLink.paymobPayoutDriverWallet, payload: { // "issuer": issuer, // "method": "wallet", // "amount": amount, //9.0, // "full_name": // '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}', // "msisdn": msisdn, //"01010101010", // "bank_transaction_type": "cash_transfer" // }); // if (dec['disbursement_status'] == 'successful') { // var paymentToken = await Get.find() // .generateToken( // ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) // .toStringAsFixed(0)); // await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { // 'rideId': DateTime.now().toIso8601String(), // 'amount': // ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) // .toStringAsFixed(0), // 'payment_method': 'payout', // 'passengerID': 'myself', // 'token': paymentToken, // 'driverID': box.read(BoxName.driverID).toString(), // }); // await Get.find() // .addSeferWallet('payout fee myself', payOutFee.toString()); // await updatePaymentToPaid(box.read(BoxName.driverID).toString()); // await sendEmail( // box.read(BoxName.driverID).toString(), // amount, // box.read(BoxName.phoneDriver).toString(), // box.read(BoxName.nameDriver).toString(), // 'Wallet', // box.read(BoxName.emailDriver).toString()); // mySnackbarSuccess('${'Transaction successful'.tr} ${dec['amount']}'); // Get.find().refreshCaptainWallet(); // } else if (dec['disbursement_status'] == 'failed') { // mySnackeBarError('Transaction failed'.tr); // } } else { MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); } } Future updatePaymentToPaid(String driverID) async { await CRUD().postWallet(link: AppLink.updatePaymetToPaid, payload: { 'driverID': driverID.toString(), }); } Future sendEmail( String driverId, amount, phone, name, bankCardNumber, email) async { await CRUD().sendEmail(AppLink.sendEmailToDrivertransaction, { "driverID": driverId, "total_amount": amount, "phone": phone, "name_arabic": name, "accountBank": bankCardNumber, "email": email }); } getAIKey(String key) async { var res = await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key}); if (res != 'failure') { var d = jsonDecode(res)['message']; return d[key].toString(); } else {} } payToDriverBankAccount( String amount, String bankCardNumber, String bankCode) async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { var body = { "issuer": "bank_card", "method": "bank_card", "amount": amount, //9.0, "full_name": '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}', "bank_card_number": bankCardNumber, //"1111-2222-3333-4444", "bank_code": bankCode, //"CIB", "bank_transaction_type": "cash_transfer" }; var dec = await CRUD().postWallet( link: 'wl.tripz-egypt.com/v1/main/ride/payMob/paymob_driver/paymob_payout.php', payload: body, ); if (dec['disbursement_status'] == 'successful') { var paymentToken = await Get.find() .generateToken( ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) .toStringAsFixed(0)); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'rideId': DateTime.now().toIso8601String(), 'amount': ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) .toStringAsFixed(0), 'payment_method': 'payout', 'passengerID': 'myself', 'token': paymentToken, 'driverID': box.read(BoxName.driverID).toString(), }); await Get.find() .addSeferWallet('payout fee myself', payOutFee.toString()); await updatePaymentToPaid(box.read(BoxName.driverID).toString()); await sendEmail( box.read(BoxName.driverID).toString(), amount, box.read(BoxName.phoneDriver).toString(), box.read(BoxName.nameDriver).toString(), 'Wallet', box.read(BoxName.emailDriver).toString()); mySnackbarSuccess('${'Transaction successful'.tr} ${dec['amount']}'); Get.find().refreshCaptainWallet(); } else if (dec['disbursement_status'] == 'failed') { mySnackeBarError('Transaction failed'.tr); } } else { MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); } } Future payToWalletDriverAll( String amount, String issuer, String msisdn) async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { await payToDriverWallet(amount, issuer, msisdn); } else { MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); } } Future payToBankDriverAll( String amount, String bankCardNumber, String bankCode) async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { await payToDriverBankAccount(amount, bankCardNumber, bankCode); } else { MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); } } } ================================================== FILE PATH: ./lib/controller/home/payment/captain_wallet_controller.dart ================================================== import 'dart:convert'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/firebase/firbase_messge.dart'; import 'package:sefer_driver/controller/firebase/local_notification.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import '../../../views/widgets/mydialoug.dart'; import '../../firebase/notification_service.dart'; class CaptainWalletController extends GetxController { bool isLoading = false; final formKeyTransfer = GlobalKey(); final formKeyAccount = GlobalKey(); Map walletDate = {}; Map walletDateVisa = {}; Map walletDriverPointsDate = {}; final formKey = GlobalKey(); String totalAmount = '0'; double kazan = 0; String totalAmountVisa = '0'; String totalPoints = '0'; final amountFromBudgetController = TextEditingController(); final newDriverPhoneController = TextEditingController(); final phoneWallet = TextEditingController(); final cardBank = TextEditingController(); final bankCode = TextEditingController(); payFromBudget() async { if (formKey.currentState!.validate()) { var pointFromBudget = int.parse((amountFromBudgetController.text)); // await getPaymentId('fromBudgetToPoints', // int.parse((amountFromBudgetController.text)) * -1); var paymentToken3 = await generateToken((pointFromBudget * -1).toString()); var paymentID = await getPaymentId( 'fromBudgetToPoints', (pointFromBudget * -1).toString()); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'amount': (pointFromBudget * -1).toString(), 'rideId': paymentID.toString(), 'payment_method': 'myBudget', 'passengerID': 'myBudgetToPoint', 'token': paymentToken3, 'driverID': box.read(BoxName.driverID).toString(), }); Future.delayed(const Duration(seconds: 1)); await addDriverWallet( 'fromBudget', pointFromBudget.toString(), pointFromBudget.toString()); update(); Get.back(); await refreshCaptainWallet(); NotificationController().showNotification( 'You have successfully charged your account'.tr, '$pointFromBudget ${'has been added to your budget'.tr}', 'tone1', '', ); } } Future refreshCaptainWallet() async { await getCaptainWalletFromRide(); await getCaptainWalletFromBuyPoints(); // await checkAccountCaptainBank(); } List amountToNewDriverMap = []; bool isNewTransfer = false; Future detectNewDriverFromMyBudget() async { if (formKeyTransfer.currentState!.validate()) { if (int.parse(amountFromBudgetController.text) < double.parse(totalAmountVisa) && int.parse(amountFromBudgetController.text) > 10) { //get new driver details isNewTransfer = true; update(); var res = await CRUD().get( link: AppLink.getDriverDetails, payload: {'driver_phone': '+2${newDriverPhoneController.text}'}); isNewTransfer = false; update(); if (res != 'failure') { var d = jsonDecode(res); amountToNewDriverMap = d['data']; // update(); } else { mySnackeBarError("This driver is not registered".tr); } } else { mySnackeBarError('Your Budget less than needed'.tr); } } } Future getCaptainWalletFromRide() async { isLoading = true; update(); var res = await CRUD().getWallet( link: AppLink.getAllPaymentFromRide, payload: {'driverID': box.read(BoxName.driverID).toString()}, ); // isLoading = false; if (res != 'failure') { walletDate = jsonDecode(res); totalAmount = walletDate['message'][0]['total_amount'] ?? '0'; update(); var res1 = await CRUD().getWallet( link: AppLink.getAllPaymentVisa, payload: {'driverID': box.read(BoxName.driverID).toString()}); walletDateVisa = jsonDecode(res1); totalAmountVisa = walletDateVisa['message'][0]['diff'].toString(); update(); } else { totalAmount = "0"; totalAmountVisa = "0"; } } 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); } else { totalPoints = '0'; } update(); } String paymentToken = ''; Future generateToken(String amount) async { var res = await CRUD().postWallet(link: AppLink.addPaymentTokenDriver, payload: { 'driverID': box.read(BoxName.driverID).toString(), 'amount': amount.toString(), }); var d = (res); return d['message']; } // late String paymentID; Future getPaymentId(String paymentMethod, amount) async { // paymentToken = await generateToken(amount); var res = await CRUD().postWallet(link: AppLink.addDriverPaymentPoints, payload: { 'driverID': box.read(BoxName.driverID).toString(), 'amount': amount.toString(), 'payment_method': paymentMethod.toString(), }); var d = (res); // paymentID = d['message'].toString(); return d['message']; } Future addDriverWallet(String paymentMethod, point, count) async { paymentToken = await generateToken(count); var paymentID = await getPaymentId(paymentMethod, point.toString()); await CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: { 'driverID': box.read(BoxName.driverID).toString(), 'paymentID': paymentID.toString(), 'amount': point, 'token': paymentToken, 'paymentMethod': paymentMethod.toString(), }); } Future addDriverPayment(String paymentMethod, point, wayPay) async { paymentToken = await generateToken(point); var paymentID = await getPaymentId(paymentMethod, point.toString()); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'amount': point.toString(), 'rideId': paymentID.toString(), 'payment_method': paymentMethod, 'passengerID': wayPay, 'token': paymentToken, 'driverID': box.read(BoxName.driverID).toString(), }); } Future addDriverWalletFromPromo(String paymentMethod, point) async { var resPromotion = await CRUD().postWallet(link: AppLink.addpromotionDriver, payload: { 'driver_id': box.read(BoxName.driverID).toString(), 'payment_amount': point, 'timePromo': paymentMethod, }); if (resPromotion != 'failure') { paymentToken = await generateToken(point); var paymentID = await getPaymentId(paymentMethod, point.toString()); var res = await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'amount': point, 'rideId': paymentID.toString(), 'payment_method': paymentMethod.toString(), 'passengerID': paymentMethod, 'token': paymentToken, 'driverID': box.read(BoxName.driverID).toString(), }); if (res != 'failure') { String title = 'wallet_updated'.tr; // Notification title String message = '${'wallet_credited_message'.tr} $point'; String tone = 'default_tone'.tr; // Notification tone or sound String payLoad = 'wallet_updated'; // Additional data payload for the notification Get.find() .showNotification(title, message, tone, payLoad); } } else { Get.back(); mySnackeBarError( "A promotion record for this driver already exists for today.".tr); } } Future addDriverWalletToInvitor(String paymentMethod, driverID, point) async { paymentToken = await generateToken(point); var paymentID = await getPaymentId(paymentMethod, point.toString()); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'driverID': driverID, 'amount': point, 'token': paymentToken, 'rideId': paymentID.toString(), 'payment_method': paymentMethod.toString(), 'passengerID': paymentMethod, }); await addSeferWallet(paymentMethod, (double.parse(point) * -2).toString()); // deduct 2 from sefer wallet } Future addSeferWallet(String paymentMethod, String point) async { var seferToken = await generateToken(point.toString()); await CRUD().postWallet(link: AppLink.addSeferWallet, payload: { 'amount': point.toString(), 'paymentMethod': paymentMethod, 'passengerId': 'driver', 'token': seferToken, 'driverId': box.read(BoxName.driverID).toString(), }); } Future addTransferDriversWallet(String paymentMethod1, paymentMethod2) async { var paymentID = await getPaymentId(paymentMethod1, amountFromBudgetController.text); paymentToken = await generateToken( (int.parse(amountFromBudgetController.text) * -1).toString()); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'amount': (int.parse(amountFromBudgetController.text) * -1).toString(), 'rideId': paymentID.toString(), 'payment_method': paymentMethod1, 'passengerID': 'To ${amountToNewDriverMap[0]['id']}', 'token': paymentToken, 'driverID': box.read(BoxName.driverID).toString(), }); paymentID = await getPaymentId(paymentMethod2, (int.parse(amountFromBudgetController.text) - 5).toString()); paymentToken = await generateToken(amountFromBudgetController.text); var res1 = await CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: { 'driverID': amountToNewDriverMap[0]['id'].toString(), 'paymentID': paymentID.toString(), 'amount': ((int.parse(amountFromBudgetController.text) - 5)) // kazan) // double.parse(kazan) .08 for egypt .toStringAsFixed( 0), // this will convert buddget to poitns by kazan .08 'token': paymentToken, 'paymentMethod': paymentMethod2.toString(), }); if (res1 != 'failure') { // Get.find().sendNotificationToDriverMAP( // 'Transfer', // '${'You have transfer to your wallet from'.tr}' // '${box.read(BoxName.nameDriver)}', // amountToNewDriverMap[0]['token'].toString(), // [], // 'order1.wav'); NotificationService.sendNotification( target: amountToNewDriverMap[0]['token'].toString(), title: 'Transfer'.tr, body: '${'You have transfer to your wallet from'.tr}' '${box.read(BoxName.nameDriver)}', isTopic: false, // Important: this is a token tone: 'ding', driverList: [], category: 'Transfer', ); await addSeferWallet('payout fee', '5'); Get.defaultDialog( title: 'transfer Successful'.tr, middleText: '', titleStyle: AppStyle.title, confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () async { Get.back(); Get.back(); await refreshCaptainWallet(); })); } } //check if account bank is created or not Future checkAccountCaptainBank() async { isLoading = true; update(); if (box.read(BoxName.accountIdStripeConnect).toString().isEmpty) { var res = await CRUD().get(link: AppLink.getAccount, payload: { 'id': box.read(BoxName.driverID).toString(), }); var d = jsonDecode(res); if (d['status'] != 'failure') { box.write(BoxName.accountIdStripeConnect, d['message'][0]['accountBank'].toString()); } } isLoading = false; update(); } 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'].toString()); // 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']); // fuelPrice = double.parse(json['message'][0]['fuelPrice']); } update(); } @override void onInit() async { // getKazanPercent(); await refreshCaptainWallet(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/home/payment/credit_card_Controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../constant/box_name.dart'; import '../../functions/digit_obsecur_formate.dart'; import '../../functions/secure_storage.dart'; class CreditCardController extends GetxController { final GlobalKey formKey = GlobalKey(); final TextEditingController cardNumberController = TextEditingController(); final TextEditingController cardHolderNameController = TextEditingController(); final TextEditingController expiryDateController = TextEditingController(); final TextEditingController cvvCodeController = TextEditingController(); openPayment() async { String? cardNumber = await SecureStorage().readData(BoxName.cardNumber); String? cardHolderName = await SecureStorage().readData(BoxName.cardHolderName); String? expiryDate = await SecureStorage().readData(BoxName.expiryDate); String? cvvCode = await SecureStorage().readData(BoxName.cvvCode); if (cvvCode != null && cvvCode.isNotEmpty) { final maskedCardNumber = DigitObscuringFormatter() .formatEditUpdate( TextEditingValue.empty, TextEditingValue(text: cardNumber ?? ''), ) .text; cardNumberController.text = maskedCardNumber; cardHolderNameController.text = cardHolderName ?? ''; expiryDateController.text = expiryDate ?? ''; cvvCodeController.text = cvvCode; } } @override void onInit() async { super.onInit(); openPayment(); // String? cardNumber = await SecureStorage().readData(BoxName.cardNumber); // String? cardHolderName = // await SecureStorage().readData(BoxName.cardHolderName); // String? expiryDate = await SecureStorage().readData(BoxName.expiryDate); // String? cvvCode = await SecureStorage().readData(BoxName.cvvCode); // if (cvvCode != null && cvvCode.isNotEmpty) { // final maskedCardNumber = DigitObscuringFormatter() // .formatEditUpdate( // TextEditingValue.empty, // TextEditingValue(text: cardNumber ?? ''), // ) // .text; // cardNumberController.text = maskedCardNumber; // cardHolderNameController.text = cardHolderName ?? ''; // expiryDateController.text = expiryDate ?? ''; // cvvCodeController.text = cvvCode; // } } } class CreditCardModel { String cardNumber; String cardHolderName; String expiryDate; String cvvCode; CreditCardModel({ required this.cardNumber, required this.cardHolderName, required this.expiryDate, required this.cvvCode, }); } ================================================== FILE PATH: ./lib/controller/home/navigation/decode_polyline_isolate.dart ================================================== import 'package:google_maps_flutter/google_maps_flutter.dart'; // تم تعديل الدالة لتقبل وسيط من نوع `dynamic` لحل مشكلة عدم تطابق الأنواع مع دالة `compute`. // هذه الدالة لا تزال تعمل كدالة من المستوى الأعلى (Top-level function) // وهو شرط أساسي لاستخدامها مع دالة compute. List decodePolylineIsolate(dynamic encodedMessage) { // التأكد من أن الرسالة المستقبلة هي من نوع String if (encodedMessage is! String) { // إرجاع قائمة فارغة أو إظهار خطأ إذا كان النوع غير صحيح return []; } final String encoded = encodedMessage; List points = []; int index = 0, len = encoded.length; int lat = 0, lng = 0; while (index < len) { int b, shift = 0, result = 0; do { b = encoded.codeUnitAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.codeUnitAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; points.add(LatLng(lat / 1E5, lng / 1E5)); } return points; } ================================================== FILE PATH: ./lib/controller/home/navigation/navigation_controller.dart ================================================== import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'dart:convert'; // <<<--- إضافة جديدة import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; // <<<--- إضافة جديدة import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import '../../../constant/box_name.dart'; import '../../../constant/country_polygons.dart'; import '../../../constant/links.dart'; import '../../../env/env.dart'; import '../../../main.dart'; import '../../../print.dart'; // import '../../functions/crud.dart'; // <<<--- تم إلغاء الاعتماد عليه import '../../functions/tts.dart'; import 'decode_polyline_isolate.dart'; class NavigationController extends GetxController { // --- متغيرات الحالة العامة --- bool isLoading = false; GoogleMapController? mapController; final TextEditingController placeDestinationController = TextEditingController(); // --- متغيرات الخريطة والموقع --- LatLng? myLocation; double heading = 0.0; final Set markers = {}; final Set polylines = {}; BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor destinationIcon = BitmapDescriptor.defaultMarker; // --- متغيرات النظام الذكي للتحديث --- Timer? _locationUpdateTimer; Duration _currentUpdateInterval = const Duration(seconds: 2); // --- متغيرات البحث عن الأماكن --- List placesDestination = []; Timer? _debounce; // --- متغيرات الملاحة (Navigation) --- LatLng? _finalDestination; List> routeSteps = []; List _fullRouteCoordinates = []; List> _stepPolylines = []; bool _nextInstructionSpoken = false; String currentInstruction = ""; String nextInstruction = ""; int currentStepIndex = 0; // <<<--- [تعديل] ---: متغير جديد لتتبع المسار المقطوع بدقة int _lastTraveledIndexInFullRoute = 0; double currentSpeed = 0.0; String distanceToNextStep = ""; final List _stepBounds = []; // --- ثوابت الـ API الجديد --- static const String _routeApiBaseUrl = 'https://routec.intaleq.xyz/'; static final String _routeApiKey = Env.mapKeyOsm; @override void onInit() { super.onInit(); _initialize(); } Future _initialize() async { await _loadCustomIcons(); await _getCurrentLocationAndStartUpdates(); if (!Get.isRegistered()) { Get.put(TextToSpeechController()); } } @override void onClose() { _locationUpdateTimer?.cancel(); mapController?.dispose(); _debounce?.cancel(); placeDestinationController.dispose(); super.onClose(); } // ======================================================================= // ١. النظام الذكي لتحديد الموقع والتحديث // ======================================================================= // Helper function to check if a ray from the point intersects with a polygon segment bool _rayIntersectsSegment(LatLng point, LatLng vertex1, LatLng vertex2) { double px = point.longitude; double py = point.latitude; double v1x = vertex1.longitude; double v1y = vertex1.latitude; double v2x = vertex2.longitude; double v2y = vertex2.latitude; // Check if the point is outside the vertical bounds of the segment if ((py < v1y && py < v2y) || (py > v1y && py > v2y)) { return false; } // Calculate the intersection of the ray and the segment double intersectX = v1x + (py - v1y) * (v2x - v1x) / (v2y - v1y); // Check if the intersection is to the right of the point return intersectX > px; } // Function to check if the point is inside the polygon bool isPointInPolygon(LatLng point, List polygon) { int intersections = 0; for (int i = 0; i < polygon.length; i++) { LatLng vertex1 = polygon[i]; LatLng vertex2 = polygon[(i + 1) % polygon.length]; // Loop back to the start if (_rayIntersectsSegment(point, vertex1, vertex2)) { intersections++; } } // If the number of intersections is odd, the point is inside return intersections % 2 != 0; } String getLocationArea(double latitude, double longitude) { LatLng passengerPoint = LatLng(latitude, longitude); // 1. فحص الأردن if (isPointInPolygon(passengerPoint, CountryPolygons.jordanBoundary)) { box.write(BoxName.countryCode, 'Jordan'); // يمكنك تعيين AppLink.endPoint هنا إذا كان منطقك الداخلي لا يزال يعتمد عليه // box.write(BoxName.serverChosen, // AppLink.IntaleqSyriaServer); // مثال: اختر سيرفر سوريا للبيانات return 'Jordan'; } // 2. فحص سوريا if (isPointInPolygon(passengerPoint, CountryPolygons.syriaBoundary)) { box.write(BoxName.countryCode, 'Syria'); // box.write(BoxName.serverChosen, AppLink.IntaleqSyriaServer); return 'Syria'; } // 3. فحص مصر if (isPointInPolygon(passengerPoint, CountryPolygons.egyptBoundary)) { box.write(BoxName.countryCode, 'Egypt'); // box.write(BoxName.serverChosen, AppLink.IntaleqAlexandriaServer); return 'Egypt'; } // 4. الافتراضي (إذا كان خارج المناطق المخدومة) box.write(BoxName.countryCode, 'Jordan'); // box.write(BoxName.serverChosen, AppLink.IntaleqSyriaServer); return 'Unknown Location (Defaulting to Jordan)'; } Future _getCurrentLocationAndStartUpdates() async { try { Position position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); myLocation = LatLng(position.latitude, position.longitude); getLocationArea(myLocation!.latitude, myLocation!.longitude); update(); animateCameraToPosition(myLocation!); _startLocationTimer(); } catch (e) { print("Error getting location: $e"); } } void _startLocationTimer() { _locationUpdateTimer?.cancel(); _locationUpdateTimer = Timer.periodic(_currentUpdateInterval, (timer) { _updateLocationAndProcess(); }); } Future _updateLocationAndProcess() async { try { final position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); myLocation = LatLng(position.latitude, position.longitude); heading = position.heading; currentSpeed = position.speed * 3.6; _updateCarMarker(); if (polylines.isNotEmpty && myLocation != null) { animateCameraToPosition( myLocation!, bearing: heading, zoom: 18.5, ); _checkNavigationStep(myLocation!); } update(); } catch (e) { print("Error in _updateLocationAndProcess: $e"); } } void _adjustUpdateInterval() { if (currentStepIndex >= routeSteps.length) return; final currentStepDistance = routeSteps[currentStepIndex]['distance']; if (currentStepDistance > 1500) { _currentUpdateInterval = const Duration(seconds: 4); } else { _currentUpdateInterval = const Duration(seconds: 2); } _startLocationTimer(); } void onMapCreated(GoogleMapController controller) { mapController = controller; if (myLocation != null) { animateCameraToPosition(myLocation!); } } void _updateCarMarker() { if (myLocation == null) return; markers.removeWhere((m) => m.markerId.value == 'myLocation'); markers.add( Marker( markerId: const MarkerId('myLocation'), position: myLocation!, icon: carIcon, rotation: heading, anchor: const Offset(0.5, 0.5), flat: true, ), ); } void animateCameraToPosition(LatLng position, {double zoom = 16.0, double bearing = 0.0}) { mapController?.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( target: position, zoom: zoom, bearing: bearing, tilt: 45.0), ), ); } // ======================================================================= // ٢. الملاحة والتحقق من الخطوات // ======================================================================= void _checkNavigationStep(LatLng currentPosition) { if (routeSteps.isEmpty || currentStepIndex >= routeSteps.length || _finalDestination == null) return; // <<<--- [تعديل] ---: استدعاء الدالة الجديدة والمحسنة _updateTraveledPolyline(currentPosition); final step = routeSteps[currentStepIndex]; final endLatLng = LatLng(step['end_location']['lat'], step['end_location']['lng']); final distance = Geolocator.distanceBetween( currentPosition.latitude, currentPosition.longitude, endLatLng.latitude, endLatLng.longitude, ); distanceToNextStep = (distance > 1000) ? "${(distance / 1000).toStringAsFixed(1)} كم" : "${distance.toStringAsFixed(0)} متر"; if (distance < 30 && !_nextInstructionSpoken && nextInstruction.isNotEmpty) { Get.find().speakText(nextInstruction); _nextInstructionSpoken = true; } if (distance < 20) { _advanceStep(); } } void _advanceStep() { currentStepIndex++; if (currentStepIndex < routeSteps.length) { currentInstruction = routeSteps[currentStepIndex]['instruction_text']; nextInstruction = ((currentStepIndex + 1) < routeSteps.length) ? routeSteps[currentStepIndex + 1]['instruction_text'] : "الوجهة النهائية"; _nextInstructionSpoken = false; _adjustUpdateInterval(); if (currentStepIndex < _stepBounds.length) { mapController?.animateCamera( CameraUpdate.newLatLngBounds(_stepBounds[currentStepIndex], 70.0)); } update(); } else { currentInstruction = "لقد وصلت إلى وجهتك."; nextInstruction = ""; distanceToNextStep = ""; _locationUpdateTimer?.cancel(); Get.find().speakText(currentInstruction); update(); } } // ======================================================================= // ٣. تحسين خوارزمية البحث ورسم المسار المقطوع // ======================================================================= // <<<--- [تعديل] ---: تم إعادة كتابة الدالة بالكامل void _updateTraveledPolyline(LatLng currentPosition) { // 1. التأكد من أن المسار الكامل محمل if (_fullRouteCoordinates.isEmpty) return; double minDistance = double.infinity; // 2. ابدأ البحث دائماً من النقطة الأخيرة التي تم الوصول إليها int newClosestIndex = _lastTraveledIndexInFullRoute; // 3. ابحث للأمام فقط (من آخر نقطة مسجلة إلى نهاية المسار) for (int i = _lastTraveledIndexInFullRoute; i < _fullRouteCoordinates.length; i++) { final point = _fullRouteCoordinates[i]; final distance = Geolocator.distanceBetween( currentPosition.latitude, currentPosition.longitude, point.latitude, point.longitude, ); if (distance < minDistance) { minDistance = distance; newClosestIndex = i; } else if (distance > minDistance + 50) { // 4. تحسين: إذا بدأت المسافة بالزيادة، فتوقف عن البحث // هذا يعني أننا تجاوزنا أقرب نقطة (50 متر هامش أمان) break; } } // 5. قم بتحديث آخر نقطة مسجلة _lastTraveledIndexInFullRoute = newClosestIndex; // 6. ارسم المسار المقطوع (من البداية إلى أقرب نقطة) List traveledPoints = _fullRouteCoordinates.sublist(0, newClosestIndex + 1); traveledPoints.add(currentPosition); // أضف الموقع الحالي لنعومة الخط // 7. ارسم المسار المتبقي (من أقرب نقطة إلى النهاية) List remainingPoints = _fullRouteCoordinates.sublist(newClosestIndex); remainingPoints.insert(0, currentPosition); // ابدأ من الموقع الحالي // 8. تحديث الخطوط على الخريطة polylines.removeWhere((p) => p.polylineId.value == 'traveled_route'); polylines.add(Polyline( polylineId: const PolylineId('traveled_route'), points: traveledPoints, color: Colors.grey.shade600, width: 7, )); polylines.removeWhere((p) => p.polylineId.value == 'remaining_route'); polylines.add(Polyline( polylineId: const PolylineId('remaining_route'), points: remainingPoints, color: const Color(0xFF4A80F0), width: 7, )); } // <<<--- [إلغاء] ---: لم نعد بحاجة لهذه الدالة المعقدة // int _getOverallIndex(int stepIndex, int pointInStepIndex) { // int overallIndex = 0; // for (int i = 0; i < stepIndex; i++) { // overallIndex += _stepPolylines[i].length; // } // return overallIndex + pointInStepIndex; // } // ======================================================================= // ٤. دوال مساعدة وتجهيز البيانات // ======================================================================= Future _prepareStepData() async { _stepBounds.clear(); _stepPolylines.clear(); if (routeSteps.isEmpty) return; for (final step in routeSteps) { final pointsString = step['geometry']; final List polylineCoordinates = await compute( decodePolylineIsolate as ComputeCallback>, pointsString); _stepPolylines.add(polylineCoordinates); _stepBounds.add(_boundsFromLatLngList(polylineCoordinates)); } } Future selectDestination(dynamic place) async { placeDestinationController.clear(); placesDestination = []; final double lat = double.parse(place['latitude'].toString()); final double lng = double.parse(place['longitude'].toString()); final LatLng destination = LatLng(lat, lng); await startNavigationTo(destination, infoWindowTitle: place['name'] ?? 'وجهة محددة'); } Future onMapLongPressed(LatLng tappedPoint) async { Get.dialog( AlertDialog( title: const Text('بدء الملاحة؟'), content: const Text('هل تريد الذهاب إلى هذا الموقع المحدد؟'), actionsAlignment: MainAxisAlignment.spaceBetween, actions: [ TextButton( child: const Text('إلغاء', style: TextStyle(color: Colors.grey)), onPressed: () => Get.back(), ), TextButton( child: const Text('اذهب الآن'), onPressed: () { Get.back(); startNavigationTo(tappedPoint, infoWindowTitle: 'الموقع المحدد'); }, ), ], ), ); } Future startNavigationTo(LatLng destination, {String infoWindowTitle = ''}) async { isLoading = true; update(); try { _finalDestination = destination; clearRoute(isNewRoute: true); markers.add( Marker( markerId: const MarkerId('destination'), position: destination, icon: destinationIcon, infoWindow: InfoWindow(title: infoWindowTitle), ), ); await getRoute(myLocation!, destination); } catch (e) { Get.snackbar('خطأ', 'حدث خطأ أثناء تحديد الوجهة.'); print("Error starting navigation: $e"); } finally { isLoading = false; update(); } } // --- (تعديل) ---: تم تعديل الدالة لاستخدام http.get Future getRoute(LatLng origin, LatLng destination) async { final url = '$_routeApiBaseUrl/route-jo?origin=${origin.latitude},${origin.longitude}&destination=${destination.latitude},${destination.longitude}&steps=true&overview=full'; try { final response = await http.get( Uri.parse(url), headers: {'X-API-KEY': _routeApiKey}, ); if (response.statusCode != 200) { print("Error from route API: ${response.statusCode}"); Get.snackbar('خطأ', 'لم يتم العثور على مسار.'); return; } final responseData = jsonDecode(response.body); if (responseData == null || responseData['status'] != 'ok') { Get.snackbar('خطأ', 'لم يتم العثور على مسار.'); return; } polylines.clear(); final pointsString = responseData['polyline']; _fullRouteCoordinates = await compute( decodePolylineIsolate as ComputeCallback>, pointsString); // <<<--- [تعديل] ---: تصفير الـ index عند بدء مسار جديد _lastTraveledIndexInFullRoute = 0; polylines.add( Polyline( polylineId: const PolylineId('remaining_route'), points: _fullRouteCoordinates, color: const Color(0xFF4A80F0), width: 7, startCap: Cap.roundCap, endCap: Cap.roundCap, ), ); polylines.add( const Polyline( polylineId: PolylineId('traveled_route'), points: [], color: Colors.grey, width: 7, ), ); routeSteps = List>.from(responseData['steps']); await _prepareStepData(); for (int i = 0; i < routeSteps.length; i++) { var step = routeSteps[i]; if (i < _stepPolylines.length && _stepPolylines[i].isNotEmpty) { LatLng endLocation = _stepPolylines[i].last; step['end_location'] = { 'lat': endLocation.latitude, 'lng': endLocation.longitude }; } else { var loc = step['maneuver']['location']; // [lng, lat] step['end_location'] = {'lat': loc[1], 'lng': loc[0]}; } step['instruction_text'] = _createInstructionFromManeuver(step); } currentStepIndex = 0; _nextInstructionSpoken = false; if (routeSteps.isNotEmpty) { currentInstruction = routeSteps[0]['instruction_text']; nextInstruction = (routeSteps.length > 1) ? routeSteps[1]['instruction_text'] : "الوجهة النهائية"; Get.find().speakText(currentInstruction); } _adjustUpdateInterval(); if (_fullRouteCoordinates.isNotEmpty) { final bounds = _boundsFromLatLngList(_fullRouteCoordinates); mapController ?.animateCamera(CameraUpdate.newLatLngBounds(bounds, 100.0)); } } catch (e) { print("Exception in getRoute: $e"); Get.snackbar('خطأ', 'حدث خطأ في الشبكة.'); } } Future recalculateRoute() async { if (myLocation == null || _finalDestination == null || isLoading) return; isLoading = true; update(); Get.snackbar( 'إعادة التوجيه', 'جاري حساب مسار جديد من موقعك الحالي...', backgroundColor: AppColor.goldenBronze, ); await getRoute(myLocation!, _finalDestination!); isLoading = false; update(); } void clearRoute({bool isNewRoute = false}) { polylines.clear(); if (!isNewRoute) { markers.removeWhere((m) => m.markerId.value == 'destination'); _finalDestination = null; } routeSteps.clear(); currentInstruction = ""; nextInstruction = ""; distanceToNextStep = ""; currentSpeed = 0.0; _stepBounds.clear(); _fullRouteCoordinates.clear(); _stepPolylines.clear(); _nextInstructionSpoken = false; _locationUpdateTimer?.cancel(); // <<<--- [تعديل] ---: تصفير الـ index عند إلغاء المسار _lastTraveledIndexInFullRoute = 0; update(); } LatLngBounds _boundsFromLatLngList(List list) { assert(list.isNotEmpty); double? x0, x1, y0, y1; for (LatLng latLng in list) { if (x0 == null) { x0 = x1 = latLng.latitude; y0 = y1 = latLng.longitude; } else { if (latLng.latitude > x1!) x1 = latLng.latitude; if (latLng.latitude < x0) x0 = latLng.latitude; if (latLng.longitude > y1!) y1 = latLng.longitude; if (latLng.longitude < y0!) y0 = latLng.longitude; } } return LatLngBounds( northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!)); } Future _loadCustomIcons() async { carIcon = await BitmapDescriptor.fromAssetImage( const ImageConfiguration(size: Size(40, 40)), 'assets/images/car.png'); destinationIcon = await BitmapDescriptor.fromAssetImage( const ImageConfiguration(size: Size(25, 25)), 'assets/images/b.png'); } String _createInstructionFromManeuver(Map step) { final maneuver = step['maneuver']; final type = maneuver['type'] ?? 'continue'; final modifier = maneuver['modifier'] ?? 'straight'; final name = step['name'] ?? ''; String instruction = ""; switch (type) { case 'depart': instruction = "انطلق"; break; case 'arrive': instruction = "لقد وصلت إلى وجهتك"; if (name.isNotEmpty) instruction += "، $name"; return instruction; case 'turn': case 'fork': case 'off ramp': case 'on ramp': case 'roundabout': instruction = _getTurnInstruction(modifier); break; case 'continue': instruction = "استمر"; break; default: instruction = "اتجه"; } if (name.isNotEmpty) { if (instruction == "استمر") { instruction += " على $name"; } else { instruction += " إلى $name"; } } else if (type == 'continue' && modifier == 'straight') { instruction = "استمر بشكل مستقيم"; } return instruction; } String _getTurnInstruction(String modifier) { switch (modifier) { case 'uturn': return "قم بالاستدارة والعودة"; case 'sharp right': return "انعطف يمينًا بحدة"; case 'right': return "انعطف يمينًا"; case 'slight right': return "انعطف يمينًا قليلاً"; case 'straight': return "استمر بشكل مستقيم"; case 'slight left': return "انعطف يسارًا قليلاً"; case 'left': return "انعطف يسارًا"; case 'sharp left': return "انعطف يسارًا بحدة"; default: return "اتجه"; } } // ======================================================================= // ٥. دالة البحث عن الأماكن المحدثة والدوال المساعدة لها // ======================================================================= // --- (تعديل) ---: تم تعديل الدالة لاستخدام http.post Future getPlaces() async { final q = placeDestinationController.text.trim(); if (q.isEmpty || q.length < 3) { placesDestination = []; update(); return; } if (myLocation == null) { print('myLocation is null, cannot search for places.'); return; } final lat = myLocation!.latitude; final lng = myLocation!.longitude; const radiusKm = 200.0; final latDelta = _kmToLatDelta(radiusKm); final lngDelta = _kmToLngDelta(radiusKm, lat); final latMin = lat - latDelta; final latMax = lat + latDelta; final lngMin = lng - lngDelta; final lngMax = lng + lngDelta; // تجهيز البيانات لإرسالها كـ JSON final payload = { 'query': q, 'lat_min': latMin.toString(), 'lat_max': latMax.toString(), 'lng_min': lngMin.toString(), 'lng_max': lngMax.toString(), }; try { final response = await CRUD().post(link: AppLink.getPlacesSyria, payload: payload); // إرسال البيانات كـ JSON final responseData = (response); List list; if (responseData is Map) { if (responseData['status'] == 'success' && responseData['message'] is List) { list = List.from(responseData['message'] as List); } else if (responseData['status'] == 'failure') { print('Server Error: ${responseData['message']}'); return; } else { print('Unexpected Map shape from server'); return; } } else if (responseData is List) { list = List.from(responseData); } else { print('Unexpected response shape from server'); return; } String _bestName(Map p) { return (p['name_ar'] ?? p['name'] ?? p['name_en'] ?? '').toString(); } for (final p in list) { final plat = double.tryParse(p['latitude']?.toString() ?? '0.0') ?? 0.0; final plng = double.tryParse(p['longitude']?.toString() ?? '0.0') ?? 0.0; final distance = _haversineKm(lat, lng, plat, plng); final relevance = _relevanceScore(_bestName(p), q); final score = (1.0 / (1.0 + distance)) * (1.0 + relevance); p['distanceKm'] = distance; p['relevance'] = relevance; p['score'] = score; } list.sort((a, b) { final sa = (a['score'] ?? 0.0) as double; final sb = (b['score'] ?? 0.0) as double; return sb.compareTo(sa); }); placesDestination = list; Log.print('Updated places: $placesDestination'); update(); } catch (e) { print('Exception in getPlaces: $e'); } } void onSearchChanged(String query) { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 700), () => getPlaces()); } // ----------------------------------------------------------------- // --== دوال مساعدة (محدثة) ==-- // ----------------------------------------------------------------- double _haversineKm(double lat1, double lon1, double lat2, double lon2) { const R = 6371.0; final dLat = (lat2 - lat1) * (pi / 180.0); final dLon = (lon2 - lon1) * (pi / 180.0); final rLat1 = lat1 * (pi / 180.0); final rLat2 = lat2 * (pi / 180.0); final a = sin(dLat / 2) * sin(dLat / 2) + cos(rLat1) * cos(rLat2) * sin(dLon / 2) * sin(dLon / 2); final c = 2 * atan2(sqrt(a), sqrt(1 - a)); return R * c; } double _relevanceScore(String placeName, String query) { if (placeName.isEmpty || query.isEmpty) return 0.0; final pLower = placeName.toLowerCase(); final qLower = query.toLowerCase(); if (pLower.startsWith(qLower)) return 1.0; if (pLower.contains(qLower)) return 0.5; return 0.0; } double _kmToLatDelta(double km) { const kmInDegree = 111.32; return km / kmInDegree; } double _kmToLngDelta(double km, double latitude) { const kmInDegree = 111.32; return km / (kmInDegree * cos(latitude * (pi / 180.0))); } } ================================================== FILE PATH: ./lib/controller/home/navigation/navigation_view.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'dart:ui'; // For BackdropFilter import 'navigation_controller.dart'; // ملاحظة: افترضتُ أن لديك لوناً أساسياً في هذا الملف // import 'package:sefer_driver/constant/colors.dart'; // سأستخدم اللون الأزرق كبديل مؤقت const Color kPrimaryColor = Color(0xFF0D47A1); class NavigationView extends StatelessWidget { const NavigationView({super.key}); @override Widget build(BuildContext context) { // استخدام Get.find() بدلاً من Get.put() لضمان أن الكونترولر مُهيأ مسبقاً // إذا كانت هذه هي نقطة الدخول، Get.put() صحيح. final NavigationController controller = Get.put(NavigationController()); return Scaffold( body: GetBuilder( builder: (_) => Stack( children: [ // --- الخريطة --- GoogleMap( onMapCreated: controller.onMapCreated, onLongPress: controller.onMapLongPressed, initialCameraPosition: CameraPosition( target: controller.myLocation ?? const LatLng(33.5138, 36.2765), // Default to Damascus zoom: 16.0, ), markers: controller.markers, polylines: controller.polylines, myLocationEnabled: false, myLocationButtonEnabled: false, compassEnabled: false, zoomControlsEnabled: false, buildingsEnabled: false, // تعديل الـ padding لإعطاء مساحة للعناصر العلوية والسفلية // مساحة أكبر في الأعلى للبحث + النتائج، ومساحة أكبر بالأسفل للملاحة padding: EdgeInsets.only( bottom: controller.currentInstruction.isNotEmpty ? 170 : 0, top: 150, ), ), // --- واجهة البحث (تصميم زجاجي) --- _buildGlassSearchUI(controller), // --- إرشادات الملاحة (تصميم عائم) --- if (controller.currentInstruction.isNotEmpty) _buildFloatingNavigationUI(controller), // --- أزرار التحكم (تصميم عائم) --- _buildFloatingMapControls(controller), // --- مؤشر التحميل --- if (controller.isLoading) Container( color: Colors.black.withOpacity(0.5), child: const Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.white), strokeWidth: 3, ), ), ), ], ), ), ); } /// --- 1. واجهة البحث بالتصميم الزجاجي المطور --- Widget _buildGlassSearchUI(NavigationController controller) { return Positioned( top: 0, left: 0, right: 0, child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), child: Column( children: [ // --- شريط البحث --- ClipRRect( borderRadius: BorderRadius.circular(28.0), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( height: 56, decoration: BoxDecoration( color: Colors.white.withOpacity(0.85), borderRadius: BorderRadius.circular(28.0), border: Border.all(color: Colors.white.withOpacity(0.4)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 15, offset: const Offset(0, 5), ), ], ), child: Row( children: [ const Padding( padding: EdgeInsets.only(left: 18.0, right: 10.0), child: Icon(Icons.search, color: kPrimaryColor, size: 24), ), Expanded( child: TextField( controller: controller.placeDestinationController, onChanged: controller.onSearchChanged, textInputAction: TextInputAction.search, style: const TextStyle( fontSize: 16, color: Colors.black87), decoration: InputDecoration( hintText: 'إلى أين تريد الذهاب؟', hintStyle: const TextStyle( color: Colors.black45, fontSize: 16), border: InputBorder.none, contentPadding: const EdgeInsets.only(bottom: 2), ), ), ), // زر المسح أو إلغاء المسار if (controller .placeDestinationController.text.isNotEmpty) _buildClearButton(controller) else if (controller.polylines.isNotEmpty) _buildCancelRouteButton(controller), ], ), ), ), ), const SizedBox(height: 10), // --- قائمة النتائج --- if (controller.placesDestination.isNotEmpty) _buildSearchResultsList(controller), ], ), ), ), ); } Widget _buildClearButton(NavigationController controller) { return IconButton( icon: const Icon(Icons.clear, color: Colors.grey, size: 22), onPressed: () { controller.placeDestinationController.clear(); controller.placesDestination = []; controller.update(); }, ); } Widget _buildCancelRouteButton(NavigationController controller) { return IconButton( tooltip: 'إلغاء المسار', icon: const Icon(Icons.close, color: Colors.redAccent, size: 22), onPressed: () => controller.clearRoute(), ); } Widget _buildSearchResultsList(NavigationController controller) { return ClipRRect( borderRadius: BorderRadius.circular(24.0), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( constraints: const BoxConstraints(maxHeight: 220), decoration: BoxDecoration( color: Colors.white.withOpacity(0.85), borderRadius: BorderRadius.circular(24.0), border: Border.all(color: Colors.white.withOpacity(0.4)), ), child: ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8.0), itemCount: controller.placesDestination.length, itemBuilder: (context, index) { final place = controller.placesDestination[index]; final distance = place['distanceKm'] as double?; final address = (place['address'] ?? '').toString(); return Material( color: Colors.transparent, child: InkWell( onTap: () => controller.selectDestination(place), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 12.0), child: Row( children: [ // أيقونة الموقع Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: kPrimaryColor.withOpacity(0.1), shape: BoxShape.circle, ), child: const Icon(Icons.location_on_outlined, color: kPrimaryColor, size: 20), ), const SizedBox(width: 14), // الاسم والعنوان Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( place['name'] ?? 'اسم غير معروف', style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 16, color: Colors.black87), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (address.isNotEmpty) Text( address, style: const TextStyle( color: Colors.black54, fontSize: 13), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), const SizedBox(width: 10), // المسافة if (distance != null) Text( '${distance.toStringAsFixed(1)} كم', style: const TextStyle( color: kPrimaryColor, fontWeight: FontWeight.w500, fontSize: 13, ), ), ], ), ), ), ); }, ), ), ), ); } /// --- 2. أزرار التحكم بالتصميم العائم --- Widget _buildFloatingMapControls(NavigationController controller) { return Positioned( // اجعلها تطفو فوق لوحة الملاحة bottom: controller.currentInstruction.isNotEmpty ? 190 : 24, right: 16, child: Column( children: [ if (controller.polylines.isNotEmpty) ...[ FloatingActionButton( heroTag: 'rerouteBtn', backgroundColor: Colors.white, elevation: 6, onPressed: () => controller.recalculateRoute(), tooltip: 'إعادة حساب المسار', child: const Icon(Icons.sync_alt, color: kPrimaryColor, size: 24), ), const SizedBox(height: 12), ], FloatingActionButton( heroTag: 'gpsBtn', backgroundColor: Colors.white, elevation: 6, onPressed: () { if (controller.myLocation != null) { controller.animateCameraToPosition( controller.myLocation!, bearing: controller.heading, zoom: 18.5, ); } }, child: const Icon(Icons.gps_fixed, color: Colors.black54, size: 24), ), ], ), ); } /// --- 3. واجهة الملاحة بالتصميم العائم المطور --- Widget _buildFloatingNavigationUI(NavigationController controller) { return Positioned( bottom: 16, left: 16, right: 16, child: Container( decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF1E88E5), Color(0xFF0D47A1)], // أزرق متدرج begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.circular(28), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 25, offset: const Offset(0, 10), ), ], ), child: Padding( padding: const EdgeInsets.fromLTRB(22, 20, 22, 22), child: Column( mainAxisSize: MainAxisSize.min, children: [ // --- الصف العلوي: الإرشاد والمسافة --- Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // الأيقونة Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), shape: BoxShape.circle, ), child: const Icon(Icons.navigation_rounded, color: Colors.white, size: 28), ), const SizedBox(width: 16), // الإرشاد Expanded( child: Text( controller.currentInstruction, style: const TextStyle( color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold, height: 1.3, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 16), // المسافة Text( controller.distanceToNextStep, style: const TextStyle( color: Colors.white, fontSize: 32, fontWeight: FontWeight.bold, ), ), ], ), // --- فاصل --- if (controller.nextInstruction.isNotEmpty || controller.currentSpeed > 0) const Padding( padding: EdgeInsets.symmetric(vertical: 14.0), child: Divider(color: Colors.white30, height: 1), ), // --- الصف السفلي: الإرشاد التالي والسرعة --- Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // الإرشاد التالي Expanded( child: controller.nextInstruction.isNotEmpty ? Text( 'التالي: ${controller.nextInstruction}', style: const TextStyle( color: Colors.white70, fontSize: 15, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ) : const SizedBox(), // يترك مساحة فارغة إذا لم يكن هناك إرشاد تالي ), // السرعة Row( children: [ Text( controller.currentSpeed.toStringAsFixed(0), style: const TextStyle( color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 6), const Text( 'كم/س', style: TextStyle( color: Colors.white70, fontSize: 14, fontWeight: FontWeight.w500, ), ), ], ), ], ), ], ), ), ), ); } } ================================================== FILE PATH: ./lib/controller/home/navigation/route_matcher_worker.dart ================================================== // lib/controllers/navigation/route_matcher_worker.dart import 'dart:async'; import 'dart:isolate'; import 'dart:typed_data'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'dart:math'; /// Worker entrypoint (spawnUri/spawn). /// Messages: /// - init: {'type':'init','coords': Float64List} /// - match: {'type':'match','id': int, 'lat': double, 'lng': double, 'lastIndex': int, 'window': int} /// - dispose: {'type':'dispose'} /// /// Responses are sent back as Map via SendPort: /// - {'type':'ready'} /// - {'type':'matchResult','id': id, 'index': overallIndex, 'lat': lat, 'lng': lng, 'dist': meters} void routeMatcherIsolateEntry(SendPort sendPort) { final ReceivePort port = ReceivePort(); sendPort.send({'type': 'ready', 'port': port.sendPort}); Float64List? flat; // [lat,lng,lat,lng,...] int nPoints = 0; port.listen((dynamic message) { try { if (message is Map) { final type = message['type'] as String? ?? ''; if (type == 'init') { final data = message['coords'] as Float64List?; if (data != null) { flat = data; nPoints = flat!.length ~/ 2; sendPort.send({'type': 'inited', 'points': nPoints}); } else { sendPort.send({'type': 'error', 'message': 'init missing coords'}); } } else if (type == 'match') { if (flat == null) { sendPort.send({'type': 'error', 'message': 'not inited'}); return; } final int id = message['id'] as int; final double lat = (message['lat'] as num).toDouble(); final double lng = (message['lng'] as num).toDouble(); final int lastIndex = (message['lastIndex'] as int?) ?? 0; final int window = (message['window'] as int?) ?? 120; final result = _findClosestWindowInternal(flat!, lat, lng, lastIndex, window); sendPort.send({ 'type': 'matchResult', 'id': id, 'index': result['index'], 'lat': result['lat'], 'lng': result['lng'], 'dist': result['dist'] }); } else if (type == 'dispose') { port.close(); sendPort.send({'type': 'disposed'}); } else { sendPort.send({'type': 'error', 'message': 'unknown message type'}); } } } catch (e, st) { sendPort.send( {'type': 'error', 'message': e.toString(), 'stack': st.toString()}); } }); } /// Internal helper: projection on segments, windowed search. /// Returns Map {index, lat, lng, dist} Map _findClosestWindowInternal( Float64List flat, double lat, double lng, int lastIndex, int window) { final int n = flat.length ~/ 2; final int start = max(0, lastIndex - window); final int end = min(n - 1, lastIndex + window); double minDist = double.infinity; int bestIdx = lastIndex; double bestLat = flat[lastIndex * 2]; double bestLng = flat[lastIndex * 2 + 1]; for (int i = start; i < end; i++) { final double aLat = flat[i * 2]; final double aLng = flat[i * 2 + 1]; final double bLat = flat[(i + 1) * 2]; final double bLng = flat[(i + 1) * 2 + 1]; final proj = _closestPointOnSegmentLatLng(lat, lng, aLat, aLng, bLat, bLng); final double d = proj['dist'] as double; if (d < minDist) { minDist = d; bestLat = proj['lat'] as double; bestLng = proj['lng'] as double; // choose overall index: i or i+1 depending on t final double t = proj['t'] as double; bestIdx = i + (t > 0.5 ? 1 : 0); } } return {'index': bestIdx, 'lat': bestLat, 'lng': bestLng, 'dist': minDist}; } /// Projection math on geodetic points approximated in degrees (good for short distances). Map _closestPointOnSegmentLatLng( double px, double py, double ax, double ay, double bx, double by) { // Here px=lat, py=lng; ax=lat, ay=lng, etc. final double x0 = px; final double y0 = py; final double x1 = ax; final double y1 = ay; final double x2 = bx; final double y2 = by; final double dx = x2 - x1; final double dy = y2 - y1; double t = 0.0; final double len2 = dx * dx + dy * dy; if (len2 > 0) { t = ((x0 - x1) * dx + (y0 - y1) * dy) / len2; if (t < 0) t = 0; if (t > 1) t = 1; } final double projX = x1 + t * dx; final double projY = y1 + t * dy; final double distMeters = _haversineDistanceMeters(x0, y0, projX, projY); return {'lat': projX, 'lng': projY, 't': t, 'dist': distMeters}; } /// Haversine distance (meters) double _haversineDistanceMeters( double lat1, double lng1, double lat2, double lng2) { final double R = 6371000.0; final double dLat = _deg2rad(lat2 - lat1); final double dLon = _deg2rad(lng2 - lng1); final double a = sin(dLat / 2) * sin(dLat / 2) + cos(_deg2rad(lat1)) * cos(_deg2rad(lat2)) * sin(dLon / 2) * sin(dLon / 2); final double c = 2 * atan2(sqrt(a), sqrt(1 - a)); return R * c; } double _deg2rad(double deg) => deg * pi / 180.0; ================================================== FILE PATH: ./lib/controller/home/profile/feed_back_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; class FeedBackController extends GetxController { bool isLoading = false; final formKey = GlobalKey(); final feedbackController = TextEditingController(); void addFeedBack() async { isLoading = true; update(); var res = await CRUD().post(link: AppLink.addFeedBack, payload: { 'passengerId': box.read(BoxName.passengerID).toString(), 'feedBack': feedbackController.text }); var d = jsonDecode(res); if (d['status'].toString() == 'success') { Get.defaultDialog( title: 'Success'.tr, titleStyle: AppStyle.title, middleText: 'Feedback data saved successfully'.tr, middleTextStyle: AppStyle.title, confirm: MyElevatedButton( kolor: AppColor.greenColor, title: 'Ok'.tr, onPressed: () { Get.back(); Get.back(); })); } isLoading = false; update(); } } ================================================== FILE PATH: ./lib/controller/home/profile/promos_controller.dart ================================================== import 'dart:convert'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; class PromosController extends GetxController { List promoList = []; bool isLoading = true; late String promos; @override void onInit() { getPromoByToday(); super.onInit(); } Future getPromoByToday() async { var res = await CRUD().get(link: AppLink.getPromoBytody, payload: {}); if (res.toString() == 'failure') { Get.defaultDialog( title: 'No Promo for today .'.tr, middleText: '', titleStyle: AppStyle.title, confirm: MyElevatedButton( title: 'Back'.tr, onPressed: () { Get.back(); Get.back(); })); isLoading = false; update(); } else { var jsonDecoded = jsonDecode(res); promoList = jsonDecoded['message']; isLoading = false; update(); } } } ================================================== FILE PATH: ./lib/controller/home/profile/order_history_controller.dart ================================================== import 'dart:convert'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; class OrderHistoryController extends GetxController { List orderHistoryListPassenger = []; bool isloading = true; @override void onInit() { getOrderHistoryByPassenger(); super.onInit(); } Future getOrderHistoryByPassenger() async { var res = await CRUD().get(link: AppLink.getRides, payload: { 'passenger_id': box.read(BoxName.passengerID).toString(), }); if (res.toString() == 'failure') { // Get.snackbar('failure', 'message'); isloading = false; update(); } else { var jsonDecoded = jsonDecode(res); orderHistoryListPassenger = jsonDecoded['data']; isloading = false; update(); } } } ================================================== FILE PATH: ./lib/controller/rate/rate_conroller.dart ================================================== import 'package:sefer_driver/controller/firebase/firbase_messge.dart'; import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../firebase/notification_service.dart'; import '../home/captin/home_captain_controller.dart'; // import '../home/captin/home_captain_controller.dart'; class RateController extends GetxController { double selectedRateItemId = -1; TextEditingController comment = TextEditingController(); TextEditingController passengerPayAmount = TextEditingController(); String? rideId, passengerId, driverId, price; late GlobalKey formKey; bool ispassengerWantWalletFromDriver = false; String walletChecked = ''; @override void onInit() { formKey = GlobalKey(); passengerId = Get.arguments['passengerId']; rideId = Get.arguments['rideId']; driverId = Get.arguments['driverId']; price = Get.arguments['price']; walletChecked = Get.arguments['walletChecked']; super.onInit(); } void passengerWantPay() { ispassengerWantWalletFromDriver = true; update(); } Future addPassengerWallet() async { if (formKey.currentState!.validate()) { var priceOfTrip = double.parse(price.toString()); // double.parse(Get.find().paymentAmount); double remainingFee = double.parse(passengerPayAmount.text) - priceOfTrip; if (remainingFee > 0) { var paymentToken2 = await Get.find() .generateTokenPassenger(remainingFee.toString()); await CRUD().post(link: AppLink.addPassengersWallet, payload: { 'passenger_id': passengerId, 'balance': remainingFee.toString(), 'token': paymentToken2, }).then((value) async { if (value != 'failure') { mySnackbarSuccess('Wallet Added'.tr); // if (double.parse( // Get.find().totalAmountVisa) > // remainingFee) { var paymentToken3 = await Get.find() .generateTokenDriver((-1 * remainingFee).toString()); await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { 'rideId': 'remain$rideId', 'amount': (-1 * remainingFee).toString(), 'payment_method': 'Remainder', 'passengerID': passengerId, 'token': paymentToken3, 'driverID': box.read(BoxName.driverID).toString(), }); NotificationService.sendNotification( target: Get.find().tokenPassenger.toString(), title: 'Wallet Added'.tr, body: 'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr, isTopic: false, // Important: this is a token tone: 'tone2', driverList: [], category: 'Wallet Added', ); walletChecked = 'true'; // } update(); } }); } else { Get.defaultDialog( title: '${'The price must be over than '.tr} $priceOfTrip', middleText: '', confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () { Get.back(); })); } } } void selectRateItem(double id) { selectedRateItemId = id; update(); } void addRateToPassenger() async { // HomeCaptainController homeCaptainController = // Get.find(); // Get.put(MapDriverController()); if (selectedRateItemId < 1) { Get.defaultDialog( title: 'You Should choose rate figure'.tr, titleStyle: AppStyle.title, middleText: '', confirm: MyElevatedButton(title: 'Ok', onPressed: () => Get.back())); } else { await CRUD().post(link: "${AppLink.server}/ride/rate/add.php", payload: { 'passenger_id': passengerId, 'driverID': box.read(BoxName.driverID).toString(), 'rideId': rideId.toString(), 'rating': selectedRateItemId.toString(), 'comment': comment.text ?? 'none', }); CRUD().sendEmail(AppLink.sendEmailToPassengerForTripDetails, { 'startLocation': Get.find().passengerLocation.toString(), 'endLocation': Get.find().passengerDestination.toString(), 'name': Get.find().passengerName.toString(), 'timeOfTrip': Get.find().timeOfOrder.toString(), 'fee': Get.find().totalPricePassenger.toString(), 'duration': Get.find().duration.toString(), 'phone': Get.find().passengerPhone.toString(), 'email': Get.find().passengerEmail.toString(), 'startNameLocation': Get.find().startNameLocation.toString(), 'endNameLocation': Get.find().endNameLocation.toString(), }); if (Get.isRegistered()) { Get.find() .disposeEverything(); // الدالة التي أنشأناها في الخطوة 3 Get.delete(force: true); // حذف إجباري من الذاكرة } Get.offAll(HomeCaptain()); if (Get.isRegistered()) { Get.find().resumeHomeMapUpdates(); } } } } ================================================== FILE PATH: ./lib/controller/rate/rate_app_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; // Import url_launcher to open the app store import 'package:url_launcher/url_launcher.dart'; class RatingController extends GetxController { var userRating = 0.obs; final comment = TextEditingController(); void submitRating(int rating) { userRating.value = rating; _saveRating(rating); } void _redirectToAppStore() async { // URLs for App Store and Google Play Store const appStoreUrl = 'https://apps.apple.com/st/app/intaleq-driver/id6482995159'; const playStoreUrl = 'https://play.google.com/store/apps/details?id=com.intaleq_driver'; final url = GetPlatform.isIOS ? appStoreUrl : playStoreUrl; if (await launchUrl(Uri.parse(url))) { await launchUrl(Uri.parse(url)); } else { mySnackeBarError("Could not open the app store."); } } Future _saveRating(int rating) async { // Build the payload with user data final payload = { "name": box.read(BoxName.driverID) != null ? box.read(BoxName.nameDriver) : box.read(BoxName.name), "email": (box.read(BoxName.emailDriver)).toString(), "phone": (box.read(BoxName.phoneDriver)).toString(), "userId": box.read(BoxName.driverID), "userType": "driver", "rating": rating.toString(), "comment": comment.text.isEmpty ? 'nothing' : comment.text, // Get actual text from comment controller }; // Send the rating data to the backend var res = await CRUD().post(link: AppLink.addRateApp, payload: payload); // Handle the response and check if it's JSON-formatted if (res != 'failure') { try { // Attempt to parse the response as JSON final parsedResponse = (res); if (parsedResponse['status'] == 'success') { // Display a success message CRUD().post(link: AppLink.sendEmailRateingApp, payload: { "name": payload["name"], "email": payload["email"], "phone": payload["phone"], "rating": rating.toString(), "comment": payload["comment"], }); MyDialog().getDialog('Rating submitted successfully'.tr, '', () { if (rating == 5) { Get.back(); _redirectToAppStore(); } else { Get.back(); } }); // Send confirmation email if the rating was successfully submitted } else { mySnackeBarError('Failed to submit rating'); } } catch (e) { // If JSON decoding fails, log the response directly // Get.snackbar('Success', 'Rating submitted successfully', // backgroundColor: AppColor.greenColor); } } else { mySnackeBarError('Failed to connect to the server'); } } } ================================================== FILE PATH: ./lib/controller/auth/facebook_login.dart ================================================== // import 'package:firebase_auth/firebase_auth.dart'; // import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; // class FacebookSignIn { // Future signInWithFacebook() async { // final LoginResult result = await FacebookAuth.instance.login(); // if (result.status == LoginStatus.success) { // // Create a credential from the access token // final OAuthCredential credential = // FacebookAuthProvider.credential(result.accessToken!.tokenString); // // Once signed in, return the UserCredential // return await FirebaseAuth.instance.signInWithCredential(credential); // } // return null; // } // Future signOut() async { // try { // await FacebookAuth.instance.logOut(); // print('Facebook Sign Out Successful'); // } catch (e) { // print('Error during Facebook Sign Out: $e'); // } // } // Future isSignedIn() async { // final accessToken = await FacebookAuth.instance.accessToken; // return accessToken != null; // } // } ================================================== FILE PATH: ./lib/controller/auth/register_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../views/auth/captin/login_captin.dart'; import '../../views/auth/verify_email_page.dart'; class RegisterController extends GetxController { final formKey = GlobalKey(); TextEditingController firstNameController = TextEditingController(); TextEditingController lastNameController = TextEditingController(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController siteController = TextEditingController(); TextEditingController verfyCode = TextEditingController(); String birthDate = 'Birth Date'.tr; String gender = 'Male'.tr; @override void onInit() { super.onInit(); } getBirthDate() { Get.defaultDialog( title: 'Select Date'.tr, titleStyle: AppStyle.title, content: SizedBox( width: 300, child: CalendarDatePicker( initialDate: DateTime.now().subtract(const Duration(days: 14 * 365)), firstDate: DateTime.parse('1940-06-01'), lastDate: DateTime.now().subtract(const Duration(days: 14 * 365)), onDateChanged: (date) { // Get the selected date and convert it to a DateTime object DateTime dateTime = date; // Call the getOrders() function from the controller birthDate = dateTime.toString().split(' ')[0]; update(); }, // onDateChanged: (DateTime value) {}, ), ), confirm: MyElevatedButton(title: 'Ok'.tr, onPressed: () => Get.back())); } void changeGender(String value) { gender = value; update(); } sendVerifications() async { var res = await CRUD().post(link: AppLink.verifyEmail, payload: { 'email': emailController.text, 'token': verfyCode.text, }); var dec = jsonDecode(res); if (dec['status'] == 'success') { Get.offAll(() => LoginCaptin()); } } void register() async { if (formKey.currentState!.validate()) { var res = await CRUD().post(link: AppLink.signUp, payload: { 'first_name': firstNameController.text.toString(), 'last_name': lastNameController.text.toString(), 'email': emailController.text.toString(), 'phone': phoneController.text.toString(), 'password': passwordController.text.toString(), 'gender': 'yet', 'site': siteController.text, 'birthdate': birthDate, }); if (jsonDecode(res)['status'] == 'success') { int randomNumber = Random().nextInt(100000) + 1; await CRUD().post(link: AppLink.sendVerifyEmail, payload: { 'email': emailController.text, 'token': randomNumber.toString(), }); Get.to(() => const VerifyEmailPage()); } } } } ================================================== FILE PATH: ./lib/controller/auth/login_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/functions/secure_storage.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/verify_email_page.dart'; import '../functions/encrypt_decrypt.dart'; class LoginController extends GetxController { final formKey = GlobalKey(); final formKeyAdmin = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController adminPasswordController = TextEditingController(); TextEditingController adminNameController = TextEditingController(); bool isAgreeTerms = false; bool isloading = false; final FlutterSecureStorage _storage = const FlutterSecureStorage(); void changeAgreeTerm() { isAgreeTerms = !isAgreeTerms; update(); } void saveAgreementTerms() { box.write(BoxName.agreeTerms, 'agreed'); update(); } void saveCountryCode(String countryCode) { box.write(BoxName.countryCode, countryCode); update(); } void login() async { isloading = true; update(); var res = await CRUD().get(link: AppLink.login, payload: { 'email': emailController.text, 'phone': phoneController.text, 'password': passwordController.text }); isloading = false; update(); if (res == 'failure') { //Failure mySnackeBarError(''); } else { var jsonDecoeded = jsonDecode(res); if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success') { if (jsonDecoeded['data'][0]['verified'] == 1) { box.write(BoxName.driverID, jsonDecoeded['data'][0]['id']); box.write(BoxName.emailDriver, (jsonDecoeded['data'][0]['email'])); box.write( BoxName.nameDriver, jsonDecoeded['data'][0]['first_name'] + ' ' + jsonDecoeded['data'][0]['last_name']); box.write(BoxName.phone, jsonDecoeded['data'][0]['phone']); SecureStorage().saveData(BoxName.password, passwordController.text); // Get.offAll(() => const MapPagePassenger()); isloading = false; update(); await CRUD().post(link: AppLink.addTokens, payload: { 'token': box.read(BoxName.tokenFCM), 'passengerID': box.read(BoxName.passengerID).toString() }); } else { isloading = false; update(); Get.defaultDialog( title: 'You must Verify email !.'.tr, middleText: '', backgroundColor: Colors.yellow[300], onConfirm: () async { int randomNumber = Random().nextInt(100000) + 1; await CRUD().post(link: AppLink.sendVerifyEmail, payload: { 'email': emailController.text, 'token': randomNumber.toString(), }); Get.to(() => const VerifyEmailPage()); }, ); } } else if (jsonDecoeded['status'] == 'Failure') { mySnackeBarError(jsonDecoeded['data']); isloading = false; update(); } } else { isloading = false; update(); } } } goToMapPage() { if (box.read(BoxName.email) != null) { // Get.offAll(() => const MapPagePassenger()); } } @override void onInit() { super.onInit(); } } ================================================== FILE PATH: ./lib/controller/auth/tokens_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../main.dart'; class TokenController extends GetxController { bool isloading = false; Future addToken() async { String? basicAuthCredentials = await storage.read(key: BoxName.basicAuthCredentials); isloading = true; update(); var res = await http.post( Uri.parse(AppLink.addTokens), headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode(basicAuthCredentials.toString()))}', }, body: { 'token': box.read(BoxName.tokenFCM.toString()), 'passengerID': box.read(BoxName.passengerID).toString() }, ); isloading = false; update(); var jsonToken = jsonDecode(res.body); if (jsonToken['status'] == 'The token has been updated successfully.') { mySnackbarSuccess('token updated'.tr); } } } ================================================== FILE PATH: ./lib/controller/auth/verify_email_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; class VerifyEmailController extends GetxController { TextEditingController verfyCode = TextEditingController(); @override void onInit() async { super.onInit(); } sendverfications() async { await CRUD().post(link: AppLink.sendVerifyEmail); } } ================================================== FILE PATH: ./lib/controller/auth/onboarding_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import '../../models/model/onboarding_model.dart'; import '../../views/auth/captin/login_captin.dart'; abstract class OnBoardingController extends GetxController { next(); onPageChanged(int index); } class OnBoardingControllerImp extends OnBoardingController { late PageController pageController; int currentPage = 0; @override next() { currentPage++; if (currentPage > onBoardingList.length - 1) { box.write(BoxName.onBoarding, 'yes'); Get.offAll(() => LoginCaptin()); } else { pageController.animateToPage(currentPage, duration: const Duration(milliseconds: 900), curve: Curves.easeInOut); } } @override onPageChanged(int index) { currentPage = index; update(); } @override void onInit() { pageController = PageController(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/auth/apple_sigin.dart ================================================== import 'package:firebase_auth/firebase_auth.dart'; import 'package:get/get.dart'; import 'package:sign_in_with_apple/sign_in_with_apple.dart'; class AuthController extends GetxController { final FirebaseAuth _auth = FirebaseAuth.instance; Future signInWithApple() async { try { final appleCredential = await SignInWithApple.getAppleIDCredential( scopes: [ AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName, ], ); final oAuthProvider = OAuthProvider('apple.com'); final credential = oAuthProvider.credential( idToken: appleCredential.identityToken, accessToken: appleCredential.authorizationCode, ); UserCredential userCredential = await _auth.signInWithCredential(credential); return userCredential.user; } catch (error) { return null; } } void signOut() async { await _auth.signOut(); } } ================================================== FILE PATH: ./lib/controller/auth/google_sign.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/captin/cards/sms_signup.dart'; import 'package:sefer_driver/views/home/on_boarding_page.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; import 'package:google_sign_in/google_sign_in.dart'; import '../../views/auth/captin/ai_page.dart'; import '../functions/add_error.dart'; import '../functions/encrypt_decrypt.dart'; class GoogleSignInHelper { static final GoogleSignIn _googleSignIn = GoogleSignIn( scopes: [ 'email', 'profile', ], ); // Method to handle Google Sign-In static Future signIn() async { try { final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); if (googleUser != null) { await _handleSignUp(googleUser); if (box.read(BoxName.countryCode) == 'Egypt') { Get.to(() => SmsSignupEgypt()); } else if (box.read(BoxName.countryCode) == 'Jordan') { Get.to(() => AiPage()); } } return googleUser; } catch (error) { return null; } } Future signInFromLogin() async { try { final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); if (googleUser != null) { // Handle sign-up and store user information await _handleSignUp(googleUser); // Retrieve driverID and emailDriver with added validation final driverID = (box.read(BoxName.driverID)!.toString()) ?? 'Unknown ID'; final emailDriver = (box.read(BoxName.emailDriver)!.toString()) ?? 'Unknown Email'; // Debug print statements print('Driver ID: $driverID'); print('Driver Email: $emailDriver'); // Check if driverID is a valid numeric string // if (driverID != 'Unknown ID' && int.tryParse(driverID) != null) { await Get.find() .loginWithGoogleCredential(driverID, emailDriver); // } // else { // print('Invalid driverID format: $driverID'); // Get.snackbar('Login Error', 'Invalid driver ID format.', // backgroundColor: AppColor.redColor); // } } return googleUser; } catch (error, stackTrace) { mySnackeBarError('$error'); CRUD.addError(error.toString(), stackTrace.toString(), 'GoogleSignInAccount?> signInFromLogin()'); return null; } } static Future _handleSignUp(GoogleSignInAccount user) async { // Store driver information box.write(BoxName.driverID, (user.id) ?? 'Unknown ID'); // Ensure there's a fallback value box.write(BoxName.emailDriver, (user.email) ?? 'Unknown Email'); } // Method to handle Google Sign-Out static Future signOut() async { try { await _googleSignIn.signOut(); await _handleSignOut(); } catch (error) {} } static Future _handleSignOut() async { // Clear stored driver information box.erase(); storage.deleteAll(); Get.offAll(OnBoardingPage()); // Perform any additional sign-out tasks or API calls here // For example, you can notify your server about the user sign-out } // Method to get the current signed-in user static GoogleSignInAccount? getCurrentUser() { return _googleSignIn.currentUser; } } // import 'dart:async'; // import 'dart:async'; // import 'dart:convert'; // import 'package:flutter/material.dart'; // import 'package:get/get.dart'; // import 'package:http/http.dart' as http; // import 'package:sefer_driver/constant/box_name.dart'; // import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; // import 'package:sefer_driver/main.dart'; // import 'package:sefer_driver/views/auth/captin/ai_page.dart'; // import 'package:sefer_driver/views/auth/captin/cards/sms_signup.dart'; // import 'package:sefer_driver/views/home/on_boarding_page.dart'; // import 'package:sefer_driver/views/widgets/error_snakbar.dart'; // import 'package:url_launcher/url_launcher.dart'; // import '../functions/add_error.dart'; // /// Helper class to manage Google Sign-In via an external browser and polling. // class GoogleSignInHelper { // // URLs for your server endpoints // static const String _startLoginUrl = // 'https://api.tripz-egypt.com/tripz/auth/google_auth/login.php'; // static const String _checkStatusUrl = // 'https://api.tripz-egypt.com/tripz/auth/google_auth/check_status.php'; // static Future _initiateSignIn( // Function(Map userData) onSignInSuccess) async { // try { // // Show a loading dialog to the user // Get.dialog( // const Center( // child: Material( // color: Colors.transparent, // child: Column( // mainAxisSize: MainAxisSize.min, // children: [ // CircularProgressIndicator(), // SizedBox(height: 16), // Text( // "Waiting for browser sign-in...", // style: TextStyle(color: Colors.white, fontSize: 16), // ), // ], // ), // ), // ), // barrierDismissible: false, // ); // // 1. Get the auth URL and login token from the server // final startResponse = await http.get(Uri.parse(_startLoginUrl)); // if (startResponse.statusCode != 200) { // throw Exception('Failed to start login process.'); // } // final startData = jsonDecode(startResponse.body); // final String authUrl = startData['authUrl']; // final String loginToken = startData['loginToken']; // // 2. Launch the URL in an external browser // if (!await launchUrl(Uri.parse(authUrl), // mode: LaunchMode.externalApplication)) { // throw Exception('Could not launch browser.'); // } // // 3. Start polling the server for status // await _startPolling(loginToken, onSignInSuccess); // } catch (e) { // addError(e.toString(), '_initiateSignIn'); // mySnackeBarError('Sign-in failed: ${e.toString()}'); // // Close the loading dialog on error // if (Get.isDialogOpen ?? false) { // Get.back(); // } // } // } // static Future _startPolling(String loginToken, // Function(Map userData) onSignInSuccess) async { // Timer? poller; // const int maxAttempts = 30; // Poll for 60 seconds (30 attempts * 2s) // int attempts = 0; // poller = Timer.periodic(const Duration(seconds: 2), (timer) async { // if (attempts >= maxAttempts) { // timer.cancel(); // if (Get.isDialogOpen ?? false) Get.back(); // mySnackeBarError('Sign-in timed out. Please try again.'); // return; // } // attempts++; // try { // final statusResponse = await http.post( // Uri.parse(_checkStatusUrl), // headers: {'Content-Type': 'application/json'}, // body: jsonEncode({'loginToken': loginToken}), // ); // if (statusResponse.statusCode == 200) { // final statusData = jsonDecode(statusResponse.body); // if (statusData['status'] == 'success') { // timer.cancel(); // if (Get.isDialogOpen ?? false) Get.back(); // // Success! // onSignInSuccess(statusData['userData']); // } // // If status is 'pending', do nothing and wait for the next poll. // } // } catch (e) { // // Handle polling errors silently or log them // debugPrint("Polling error: $e"); // } // }); // } // /// Triggers the sign-in process for a new user. // static Future signIn() async { // await _initiateSignIn((userData) async { // debugPrint('Sign-in success data: $userData'); // await _handleSignUp(userData); // if (box.read(BoxName.countryCode) == 'Egypt') { // Get.offAll(() => SmsSignupEgypt()); // } else if (box.read(BoxName.countryCode) == 'Jordan') { // Get.offAll(() => AiPage()); // } // }); // } // /// Triggers the sign-in process for an existing user. // static Future signInFromLogin() async { // await _initiateSignIn((userData) async { // debugPrint('Sign-in from login success data: $userData'); // await _handleSignUp(userData); // final driverID = userData['id']?.toString() ?? 'Unknown ID'; // final emailDriver = userData['email']?.toString() ?? 'Unknown Email'; // debugPrint('Driver ID from server: $driverID'); // debugPrint('Driver Email from server: $emailDriver'); // await Get.find() // .loginWithGoogleCredential(driverID, emailDriver); // }); // } // /// Stores user information received from the server. // static Future _handleSignUp(Map userData) async { // box.write(BoxName.driverID, userData['id'] ?? 'Unknown ID'); // box.write(BoxName.emailDriver, userData['email'] ?? 'Unknown Email'); // } // /// Clears local data. // static Future signOut() async { // box.remove(BoxName.driverID); // box.remove(BoxName.emailDriver); // box.remove(BoxName.lang); // box.remove(BoxName.nameDriver); // box.remove(BoxName.passengerID); // box.remove(BoxName.phoneDriver); // box.remove(BoxName.tokenFCM); // box.remove(BoxName.tokens); // box.remove(BoxName.carPlate); // box.remove(BoxName.lastNameDriver); // box.remove(BoxName.agreeTerms); // box.remove(BoxName.tokenDriver); // box.remove(BoxName.countryCode); // box.remove(BoxName.accountIdStripeConnect); // box.remove(BoxName.phoneVerified); // Get.offAll(() => OnBoardingPage()); // } // } ================================================== FILE PATH: ./lib/controller/auth/syria/registration_controller.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image/image.dart' as img; import 'package:path/path.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/firebase/notification_service.dart'; import '../../../constant/box_name.dart'; import 'package:path_provider/path_provider.dart'; // --- Final Submission --- import 'package:path_provider/path_provider.dart' as path_provider; import 'package:http/http.dart' as http; import 'package:http_parser/http_parser.dart'; import 'package:mime/mime.dart'; import 'package:path/path.dart' as p; import '../../../constant/colors.dart'; import '../../../constant/info.dart'; import '../../../main.dart'; import '../../../print.dart'; import '../../../views/widgets/error_snakbar.dart'; import '../../functions/crud.dart'; import '../../functions/encrypt_decrypt.dart'; import '../../functions/package_info.dart'; import '../captin/login_captin_controller.dart'; // You can create a simple enum to manage image types enum ImageType { driverLicenseFront, driverLicenseBack, carLicenseFront, carLicenseBack, } class RegistrationController extends GetxController { // Page Controller for managing steps late PageController pageController; var currentPage = 0.obs; // Use .obs for reactive updates on the step indicator // Loading state var isLoading = false.obs; var isloading = false; CroppedFile? croppedFile; final picker = ImagePicker(); var image; File? myImage; String? colorHex; // سيُملى من الدروب داون // Form Keys for validation final driverInfoFormKey = GlobalKey(); final carInfoFormKey = GlobalKey(); // STEP 1: Driver Information Controllers final firstNameController = TextEditingController(); final lastNameController = TextEditingController(); final nationalIdController = TextEditingController(); final bithdateController = TextEditingController(); final phoneController = TextEditingController(); // You can pre-fill this final driverLicenseExpiryController = TextEditingController(); DateTime? driverLicenseExpiryDate; // STEP 2: Car Information Controllers final carPlateController = TextEditingController(); final carMakeController = TextEditingController(); final carModelController = TextEditingController(); final carYearController = TextEditingController(); final carColorController = TextEditingController(); final carVinController = TextEditingController(); // Chassis number final carRegistrationExpiryController = TextEditingController(); DateTime? carRegistrationExpiryDate; // STEP 3: Document Uploads File? driverLicenseFrontImage; File? driverLicenseBackImage; File? carLicenseFrontImage; File? carLicenseBackImage; @override void onInit() { super.onInit(); pageController = PageController(); // Pre-fill phone number if it exists in storage // phoneController.text = box.read(BoxName.phoneDriver) ?? ''; } @override void onClose() { pageController.dispose(); // Dispose all other text controllers super.onClose(); } // --- Page Navigation --- void goToNextStep() { bool isValid = false; if (currentPage.value == 0) { // Validate Step 1 isValid = driverInfoFormKey.currentState!.validate(); if (isValid) { // Optional: Check if license is expired // if (driverLicenseExpiryDate != null && // driverLicenseExpiryDate!.isBefore(DateTime.now())) { // Get.snackbar('Expired License', 'Your driver’s license has expired.'.tr // , // snackPosition: SnackPosition.BOTTOM, // backgroundColor: Colors.red, // colorText: Colors.white); // return; // Stop progression // } } } else if (currentPage.value == 1) { // Validate Step 2 isValid = carInfoFormKey.currentState!.validate(); } if (isValid) { pageController.nextPage( duration: const Duration(milliseconds: 300), curve: Curves.easeIn, ); } } void goToPreviousStep() { pageController.previousPage( duration: const Duration(milliseconds: 300), curve: Curves.easeIn, ); } // --- Image Picking --- Future pickImage(ImageType type) async { try { final picker = ImagePicker(); final picked = await picker.pickImage( source: ImageSource.camera, imageQuality: 95, // جودة أولية من الكاميرا maxWidth: 3000, // نسمح بصورة كبيرة ثم نصغّر نحن ); if (picked == null) return; // قصّ الصورة final cropped = await ImageCropper().cropImage( sourcePath: picked.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.accentColor, toolbarWidgetColor: AppColor.redColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings(title: 'Cropper'.tr), ], ); if (cropped == null) return; // المستخدم ألغى // قراءة bytes + التصحيح حسب EXIF ثم التصغير final rawBytes = await File(cropped.path).readAsBytes(); final decoded = img.decodeImage(rawBytes); if (decoded == null) throw Exception('Decode image failed'); // تصحيح اتجاه الصورة (EXIF) final fixed = img.bakeOrientation(decoded); // تصغير لعرض 800px (عدّل عند الحاجة) final resized = img.copyResize(fixed, width: 800); // حفظ مؤقت بصيغة JPG final tmpDir = await getTemporaryDirectory(); final outPath = '${tmpDir.path}/doc_${DateTime.now().millisecondsSinceEpoch}.jpg'; final outFile = File(outPath); await outFile.writeAsBytes(img.encodeJpg(resized, quality: 85)); // عيّن الملف في المتغير الصحيح حسب النوع if (outFile != null) { switch (type) { case ImageType.driverLicenseFront: driverLicenseFrontImage = File(outFile.path); break; case ImageType.driverLicenseBack: driverLicenseBackImage = File(outFile.path); break; case ImageType.carLicenseFront: carLicenseFrontImage = File(outFile.path); break; case ImageType.carLicenseBack: carLicenseBackImage = File(outFile.path); break; } update(); // Use update() to refresh the GetBuilder UI } update(); // لتحديث الـ UI // // الإرسال للذكاء الاصطناعي // await sendToAI(type, imageFile: outFile); } catch (e) { Get.snackbar('Error'.tr, '${'An unexpected error occurred:'.tr} $e'); } } // ثابت: 20 لون سيارة شائع static const List> kCarColorOptions = [ {'key': 'color.white', 'hex': '#FFFFFF'}, {'key': 'color.black', 'hex': '#000000'}, {'key': 'color.silver', 'hex': '#C0C0C0'}, {'key': 'color.gray', 'hex': '#808080'}, {'key': 'color.gunmetal', 'hex': '#2A3439'}, {'key': 'color.red', 'hex': '#C62828'}, {'key': 'color.blue', 'hex': '#1565C0'}, {'key': 'color.navy', 'hex': '#0D47A1'}, {'key': 'color.green', 'hex': '#2E7D32'}, {'key': 'color.darkGreen', 'hex': '#1B5E20'}, {'key': 'color.beige', 'hex': '#D7CCC8'}, {'key': 'color.brown', 'hex': '#5D4037'}, {'key': 'color.maroon', 'hex': '#800000'}, {'key': 'color.burgundy', 'hex': '#800020'}, {'key': 'color.yellow', 'hex': '#F9A825'}, {'key': 'color.orange', 'hex': '#EF6C00'}, {'key': 'color.gold', 'hex': '#D4AF37'}, {'key': 'color.bronze', 'hex': '#CD7F32'}, {'key': 'color.champagne', 'hex': '#EFE1C6'}, {'key': 'color.purple', 'hex': '#6A1B9A'}, ]; Color hexToColor(String hex) { var v = hex.replaceAll('#', ''); if (v.length == 6) v = 'FF$v'; return Color(int.parse(v, radix: 16)); } //uploadSyrianDocs // دالة مساعدة: تضيف الحقل إذا كان له قيمة void _addField(Map fields, String key, String? value) { if (value != null && value.toString().isNotEmpty) { fields[key] = value.toString(); } } /// خريطة لتخزين روابط المستندات بعد الرفع final Map docUrls = { 'driver_license_front': '', 'driver_license_back': '', 'car_license_front': '', 'car_license_back': '', }; /// التصرّف العام لاختيار/قص/ضغط/رفع الصورة حسب type Future choosImage(String link, String imageType) async { try { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.rear, ); if (pickedImage == null) return; image = File(pickedImage.path); final croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings(title: 'Cropper'.tr), ], ); if (croppedFile == null) return; // صورة للمعاينة داخل التطبيق myImage = File(croppedFile.path); isloading = true; update(); // ضغط (وأيضاً يمكنك إضافة rotateImageIfNeeded قبل/بعد الضغط إن رغبت) final File compressedImage = await compressImage(File(croppedFile.path)); // تجهيز الحقول final driverId = box.read(BoxName.driverID); final payload = { 'driverID': driverId, 'imageType': imageType, // مثال: driver_license_front }; // الرفع وإرجاع الرابط final String imageUrl = await uploadImage(compressedImage, payload, link); // حفظ الرابط محلياً حسب النوع docUrls[imageType] = imageUrl; Log.print('✅ Uploaded $imageType => $imageUrl'); } catch (e, st) { Log.print('❌ Error in choosImage: $e\n$st'); mySnackeBarError('Image Upload Failed'.tr); } finally { isloading = false; update(); } } /// ترفع الملف وترجع رابط الصورة النهائي كـ String Future uploadImage( File file, Map data, String link) async { final uri = Uri.parse(link); final request = http.MultipartRequest('POST', uri); // الهيدرز (كما عندك) final headers = { 'Authorization': 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', }; request.headers.addAll(headers); // اسم الملف: driverID.jpg (اختياري) final forcedName = '${box.read(BoxName.driverID) ?? 'image'}.jpg'; // إضافة الملف (من المسار مباشرة أسلم من الـ stream) request.files.add( await http.MultipartFile.fromPath( 'image', // تأكد أنه نفس اسم الحقل على السيرفر file.path, filename: forcedName, ), ); // الحقول الإضافية data.forEach((k, v) => request.fields[k] = v); // الإرسال final streamed = await request.send(); final res = await http.Response.fromStream(streamed); if (res.statusCode != 200) { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } // نحاول استخراج رابط الصورة من أكثر من مفتاح محتمل final body = jsonDecode(res.body); final String? url = body['url'] ?? body['file_link'] ?? body['image_url'] ?? (body['data'] is Map ? body['data']['url'] : null); if (url == null || url.isEmpty) { // لو السيرفر يرجع هيكل مختلف، عدّل هنا المفتاح حسب استجابتك الفعلية throw Exception( 'Upload succeeded but no image URL found in response: ${res.body}'); } return url; } Future compressImage(File file) async { final dir = await path_provider.getTemporaryDirectory(); final targetPath = "${dir.absolute.path}/temp.jpg"; var result = await FlutterImageCompress.compressAndGetFile( file.absolute.path, targetPath, quality: 70, minWidth: 1024, minHeight: 1024, ); return File(result!.path); } // دالة رفع إلى السيرفر السوري: ترجع file_url (Signed URL) Future uploadToSyria({ required String docType, required File file, required Uri syrianUploadUri, required String authHeader, required String hmacHeader, required String driverId, Duration timeout = const Duration(seconds: 60), http.Client? clientOverride, }) async { final client = clientOverride ?? http.Client(); try { final mime = lookupMimeType(file.path) ?? 'image/jpeg'; final parts = mime.split('/'); final req = http.MultipartRequest('POST', syrianUploadUri); req.headers.addAll({ 'Authorization': authHeader, 'X-HMAC-Auth': hmacHeader, }); req.fields['driver_id'] = driverId; req.fields['doc_type'] = docType; req.files.add( await http.MultipartFile.fromPath( 'file', file.path, filename: p.basename(file.path), contentType: MediaType(parts.first, parts.last), ), ); // ====== الطباعة قبل الإرسال ====== // Log.print('--- Syrian Upload Request ---'); // Log.print('URL: $syrianUploadUri'); // // Log.print('Method: POST'); // // Log.print('Headers: ${req.headers}'); // Log.print('Fields: ${req.fields}'); // // Log.print( // // 'File: ${file.path} (${await file.length()} bytes, mime: $mime)'); // Log.print('-----------------------------'); // الإرسال final streamed = await client.send(req).timeout(timeout); final resp = await http.Response.fromStream(streamed); // ====== الطباعة بعد الاستجابة ====== // Log.print('--- Syrian Upload Response ---'); Log.print('Status: ${resp.statusCode}'); // Log.print('Headers: ${resp.headers}'); // Log.print('Body: ${resp.body}'); // Log.print('-------------------------------'); Map j = {}; try { j = jsonDecode(resp.body) as Map; } catch (e) { Log.print('⚠️ Failed to parse JSON: $e'); } // التحمّل لشكلين من الـ JSON: final statusOk = j['status'] == 'success'; final fileUrl = (j['file_url'] ?? j['message']?['file_url'])?.toString(); final fileName = (j['file_name'] ?? j['message']?['file_name'])?.toString(); if (resp.statusCode == 200 && statusOk && (fileUrl?.isNotEmpty ?? false)) { // Log.print( // '✅ Syrian upload success: $fileUrl (file: ${fileName ?? "-"})'); return fileUrl!; } throw Exception( '❌ Syrian upload failed ($docType): ${j['message'] ?? resp.body}'); } finally { if (clientOverride == null) client.close(); } } Future submitRegistration() async { // 0) دوال/مساعدات محلية // 1) تحقق من وجود الروابط بدل الملفات final driverFrontUrl = docUrls['driver_license_front']; final driverBackUrl = docUrls['driver_license_back']; final carFrontUrl = docUrls['car_license_front']; final carBackUrl = docUrls['car_license_back']; isLoading.value = true; final registerUri = Uri.parse(AppLink.register_driver_and_car); final client = http.Client(); try { // ترويسات مشتركة final bearer = 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}'; final hmac = '${box.read(BoxName.hmac)}'; // 2) جهّز طلب التسجيل الرئيسي: حقول فقط + روابط الصور (لا نرفع صور إطلاقًا) final req = http.MultipartRequest('POST', registerUri); req.headers.addAll({ 'Authorization': bearer, 'X-HMAC-Auth': hmac, }); final fields = {}; // --- Driver Data --- _addField(fields, 'id', box.read(BoxName.driverID)?.toString()); _addField(fields, 'first_name', firstNameController.text); _addField(fields, 'last_name', lastNameController.text); _addField(fields, 'phone', box.read(BoxName.phoneDriver) ?? ''); _addField(fields, 'national_number', nationalIdController.text); _addField(fields, 'birthdate', bithdateController.text); _addField(fields, 'expiry_date', driverLicenseExpiryController.text); _addField( fields, 'password', 'generate_your_password_here'); // عدّل حسب منطقك _addField(fields, 'status', 'yet'); _addField(fields, 'email', 'Not specified'); _addField(fields, 'gender', 'Male'); // --- Car Data --- _addField(fields, 'vin', 'yet'); _addField(fields, 'car_plate', carPlateController.text); _addField(fields, 'make', carMakeController.text); _addField(fields, 'model', carModelController.text); _addField(fields, 'year', carYearController.text); _addField(fields, 'expiration_date', driverLicenseExpiryController.text); _addField(fields, 'color', carColorController.text); _addField(fields, 'fuel', 'Gasoline'); if (colorHex != null && colorHex!.isNotEmpty) { _addField(fields, 'color_hex', colorHex!); } _addField(fields, 'owner', '${firstNameController.text} ${lastNameController.text}'); // --- روابط الصور المخزنة مسبقًا --- _addField(fields, 'driver_license_front', driverFrontUrl!); _addField(fields, 'driver_license_back', driverBackUrl!); _addField(fields, 'car_license_front', carFrontUrl!); _addField(fields, 'car_license_back', carBackUrl!); // أضف الحقول req.fields.addAll(fields); // 3) الإرسال final streamed = await client.send(req).timeout(const Duration(seconds: 60)); final resp = await http.Response.fromStream(streamed); // 4) فحص النتيجة Map? json; try { json = jsonDecode(resp.body) as Map; } catch (_) {} if (resp.statusCode == 200 && json?['status'] == 'success') { // final driverID = // (json!['data']?['driverID'] ?? json['driverID'])?.toString(); // if (driverID != null && driverID.isNotEmpty) { // box.write(BoxName.driverID, driverID); // } Get.snackbar( 'Success'.tr, 'Registration completed successfully!'.tr, snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white, ); // متابعة تسجيل الدخول إن لزم final email = box.read(BoxName.emailDriver); final driverID = box.read(BoxName.driverID); final c = Get.isRegistered() ? Get.find() : Get.put(LoginDriverController()); //token to server String fingerPrint = await DeviceHelper.getDeviceFingerprint(); await CRUD().post(link: AppLink.addTokensDriver, payload: { 'captain_id': (box.read(BoxName.driverID)).toString(), 'token': (box.read(BoxName.tokenDriver)).toString(), 'fingerPrint': fingerPrint.toString(), }); // CRUD().post(link: AppLink.addTokensDriverWallet, payload: { // 'token': box.read(BoxName.tokenDriver).toString(), // 'fingerPrint': fingerPrint.toString(), // 'captain_id': box.read(BoxName.driverID).toString(), // }); NotificationService.sendNotification( target: 'service', // الإرسال لجميع المشتركين في "service" title: 'طلب خدمة جديد', body: 'تم استلام طلب خدمة جديد. الرجاء مراجعة التفاصيل.', isTopic: true, category: 'new_service_request', // فئة توضح نوع الإشعار ); c.loginWithGoogleCredential(driverID, email); } else { final msg = (json?['message'] ?? 'Registration failed. Please try again.') .toString(); Log.print('msg: $msg'); Get.snackbar( 'Error'.tr, msg, snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } } catch (e) { Get.snackbar( 'Error'.tr, '${'An unexpected error occurred:'.tr} $e', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } finally { client.close(); isLoading.value = false; } } // Future submitRegistration() async { // // 1) تحقق من الصور // if (driverLicenseFrontImage == null || // driverLicenseBackImage == null || // carLicenseFrontImage == null || // carLicenseBackImage == null) { // Get.snackbar( // 'Missing Documents'.tr, 'Please upload all 4 required documents.'.tr, // snackPosition: SnackPosition.BOTTOM, // backgroundColor: Colors.orange, // colorText: Colors.white); // return; // } // isLoading.value = true; // final uri = Uri.parse( // 'https://intaleq.xyz/intaleq/auth/syria/driver/register_driver_and_car.php', // ); // final client = http.Client(); // try { // final req = http.MultipartRequest('POST', uri); // // مهم: لا تضع Content-Type يدويًا، الـ MultipartRequest يتكفّل فيه ببناء boundary. // final headers = { // 'Authorization': // 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', // 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', // }; // // 2) الحقول النصية // final fields = {}; // // --- Driver Data --- // _addField(fields, 'id', box.read(BoxName.driverID)?.toString()); // _addField(fields, 'first_name', firstNameController.text); // _addField(fields, 'last_name', lastNameController.text); // _addField(fields, 'phone', box.read(BoxName.phoneDriver) ?? ''); // _addField(fields, 'national_number', nationalIdController.text); // _addField(fields, 'expiry_date', driverLicenseExpiryController.text); // _addField( // fields, 'password', 'generate_your_password_here'); // عدّل حسب منطقك // _addField(fields, 'status', 'yet'); // _addField(fields, 'email', // 'Not specified'); // سكربت السيرفر سيحوّلها null ويبني ايميل افتراضي // _addField(fields, 'gender', 'Male'); // // --- Car Data (مطابقة لما يتوقّعه السكربت) --- // _addField(fields, 'vin', 'carVinController.text);'); // _addField(fields, 'car_plate', carPlateController.text); // _addField(fields, 'make', carMakeController.text); // _addField(fields, 'model', carModelController.text); // _addField(fields, 'year', carYearController.text); // _addField(fields, 'expiration_date', 'carRegistrationExpiryController'); // _addField(fields, 'color', carColorController.text); // _addField(fields, 'fuel', 'Gasoline'); // أو حسب اختيارك // _addField(fields, 'color_hex', colorHex); // مهم // // لو عندك حقول إضافية مطلوبة بالسكربت (مالك المركبة / الكود اللوني / الوقود) مرّرها: // _addField(fields, 'owner', // firstNameController.text + ' ' + lastNameController.text); // // if (colorHex != null) _addField(fields, 'color_hex', colorHex); // // if (fuelType != null) _addField(fields, 'fuel', fuelType); // req.headers.addAll(headers); // req.fields.addAll(fields); // // 3) الملفات (4 صور) — مفاتيحها مطابقة للسكربت // Future addFile(String field, File file) async { // final mime = lookupMimeType(file.path) ?? 'image/jpeg'; // final parts = mime.split('/'); // final mediaType = MediaType(parts.first, parts.last); // req.files.add( // await http.MultipartFile.fromPath( // field, // file.path, // filename: p.basename(file.path), // contentType: mediaType, // ), // ); // } // await addFile('driver_license_front', driverLicenseFrontImage!); // await addFile('driver_license_back', driverLicenseBackImage!); // await addFile('car_license_front', carLicenseFrontImage!); // await addFile('car_license_back', carLicenseBackImage!); // // 4) الإرسال // final streamed = // await client.send(req).timeout(const Duration(seconds: 60)); // final resp = await http.Response.fromStream(streamed); // // 5) فحص النتيجة // Map? json; // try { // json = jsonDecode(resp.body) as Map; // } catch (_) {} // if (resp.statusCode == 200 && // json != null && // json['status'] == 'success') { // // ممكن يرجّع driverID, carRegID, documents // final driverID = // (json['data']?['driverID'] ?? json['driverID'])?.toString(); // if (driverID != null && driverID.isNotEmpty) { // box.write(BoxName.driverID, driverID); // } // Get.snackbar('Success'.tr, 'Registration completed successfully!'.tr, // snackPosition: SnackPosition.BOTTOM, // backgroundColor: Colors.green, // colorText: Colors.white); // // TODO: انتقل للصفحة التالية أو حدّث الحالة… // } else { // final msg = // (json?['message'] ?? 'Registration failed. Please try again.') // .toString(); // Get.snackbar('Error'.tr, msg, // snackPosition: SnackPosition.BOTTOM, // backgroundColor: Colors.red, // colorText: Colors.white); // } // } catch (e) { // Get.snackbar('Error'.tr, '${'An unexpected error occurred:'.tr} $e', // snackPosition: SnackPosition.BOTTOM, // backgroundColor: Colors.red, // colorText: Colors.white); // } finally { // client.close(); // isLoading.value = false; // } // } // Helpers } ================================================== FILE PATH: ./lib/controller/auth/captin/phone_helper_controller.dart ================================================== import 'package:get/get.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/print.dart'; import 'package:sefer_driver/views/home/on_boarding_page.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../main.dart'; import '../../../views/auth/syria/registration_view.dart'; // --- Helper Class for Phone Authentication --- class PhoneAuthHelper { // Define your server URLs static final String _baseUrl = '${AppLink.server}/auth/syria/driver/'; static final String _sendOtpUrl = '${_baseUrl}sendWhatsAppDriver.php'; static final String _verifyOtpUrl = '${_baseUrl}verifyOtp.php'; static final String _registerUrl = '${_baseUrl}register_driver.php'; static String formatSyrianPhone(String phone) { // Remove spaces, symbols, +, -, () phone = phone.replaceAll(RegExp(r'[ \-\(\)\+]'), '').trim(); // Normalize 00963 → 963 if (phone.startsWith('00963')) { phone = phone.replaceFirst('00963', '963'); } // Normalize 0963 → 963 if (phone.startsWith('0963')) { phone = phone.replaceFirst('0963', '963'); } if (phone.startsWith('096309')) { phone = phone.replaceFirst('096309', '963'); } // NEW: Fix 96309xxxx → 9639xxxx if (phone.startsWith('96309')) { phone = '9639' + phone.substring(5); // remove the "0" after 963 } // If starts with 9630 → correct to 9639 if (phone.startsWith('9630')) { phone = '9639' + phone.substring(4); } // If already in correct format: 9639xxxxxxxx if (phone.startsWith('9639') && phone.length == 12) { return phone; } // If starts with 963 but missing the 9 if (phone.startsWith('963') && phone.length > 3) { // Ensure it begins with 9639 if (!phone.startsWith('9639')) { phone = '9639' + phone.substring(3); } return phone; } // If starts with 09xxxxxxxx → 9639xxxxxxxx if (phone.startsWith('09')) { return '963' + phone.substring(1); } // If 9xxxxxxxx (9 digits) if (phone.startsWith('9') && phone.length == 9) { return '963' + phone; } // If starts with incorrect 0xxxxxxx → assume Syrian and fix if (phone.startsWith('0') && phone.length == 10) { return '963' + phone.substring(1); } return phone; } /// Sends an OTP to the provided phone number. static Future sendOtp(String phoneNumber) async { try { final fixedPhone = formatSyrianPhone(phoneNumber); Log.print('fixedPhone: $fixedPhone'); final response = await CRUD().post( link: _sendOtpUrl, payload: {'receiver': fixedPhone}, ); Log.print('fixedPhone: ${fixedPhone}'); if (response != 'failure') { final data = (response); Log.print('data: ${data}'); // if (data['status'] == 'success') { mySnackbarSuccess('An OTP has been sent to your number.'.tr); return true; // } else { // mySnackeBarError(data['message'] ?? 'Failed to send OTP.'); // return false; // } } else { mySnackeBarError('Server error. Please try again.'.tr); return false; } } catch (e) { // mySnackeBarError('An error occurred: $e'); return false; } } /// Verifies the OTP and logs the user in. static Future verifyOtp(String phoneNumber) async { try { final fixedPhone = formatSyrianPhone(phoneNumber); Log.print('fixedPhone: $fixedPhone'); final response = await CRUD().post( link: _verifyOtpUrl, payload: { 'phone_number': fixedPhone, }, ); if (response != 'failure') { final data = response; if (data['status'] == 'success') { final isRegistered = data['message']['isRegistered'] ?? false; box.write(BoxName.phoneVerified, '1'); box.write(BoxName.phoneDriver, phoneNumber); box.write(BoxName.driverID, data['message']['driverID']); if (isRegistered) { // ✅ السائق مسجل مسبقًا - سجل دخوله واذهب إلى الصفحة الرئيسية final driver = data['message']['driver']; // mySnackbarSuccess('Welcome back, ${driver['first_name']}!'); // حفظ بيانات السائق إذا أردت: box.write(BoxName.driverID, driver['id']); box.write(BoxName.emailDriver, driver['email']); await Get.find().loginWithGoogleCredential( driver['id'].toString(), driver['email'].toString()); } else { // ✅ رقم الهاتف تم التحقق منه لكن السائق غير مسجل // mySnackbarSuccess('Phone verified. Please complete registration.'); // Get.offAll(() => SyrianCardAI()); Get.to(() => RegistrationView()); } } else { mySnackeBarError(data['message'] ?? 'Verification failed.'); } } else { mySnackeBarError('Server error. Please try again.'); } } catch (e) { mySnackeBarError('An error occurred: $e'); } } static Future registerUser({ required String phoneNumber, required String firstName, required String lastName, String? email, }) async { try { final response = await CRUD().post( link: _registerUrl, payload: { 'phone_number': phoneNumber, 'first_name': firstName, 'last_name': lastName, 'email': email ?? '', // Send empty string if null }, ); final data = (response); if (data != 'failure') { // Registration successful, log user in await _handleSuccessfulLogin(data['message']); } else { mySnackeBarError( "User with this phone number or email already exists.".tr); } } catch (e) { mySnackeBarError('An error occurred: $e'); } } static Future _handleSuccessfulLogin( Map userData) async { mySnackbarSuccess('Welcome, ${userData['first_name']}!'); // Save user data to local storage (Hive box) using new keys box.write(BoxName.passengerID, userData['id']); box.write(BoxName.nameDriver, userData['first_name']); box.write(BoxName.lastNameDriver, userData['last_name']); box.write(BoxName.emailDriver, userData['email']); box.write(BoxName.phoneDriver, userData['phone']); Get.offAll(() => OnBoardingPage()); // Navigate to home } } ================================================== FILE PATH: ./lib/controller/auth/captin/invit_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_contacts/contact.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:get/get.dart'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:share_plus/share_plus.dart'; import '../../firebase/local_notification.dart'; import '../../functions/launch.dart'; import '../../notification/notification_captain_controller.dart'; class InviteController extends GetxController { final TextEditingController invitePhoneController = TextEditingController(); List driverInvitationData = []; List driverInvitationDataToPassengers = []; String? couponCode; String? driverCouponCode; // **FIX**: Added the missing 'contacts' and 'contactMaps' definitions. List contacts = []; RxList> contactMaps = >[].obs; int selectedTab = 0; PassengerStats passengerStats = PassengerStats(); void updateSelectedTab(int index) { selectedTab = index; update(); } Future shareDriverCode() async { if (driverCouponCode != null) { final String shareText = '''Join Intaleq as a driver using my referral code! Use code: $driverCouponCode Download the Intaleq Driver app now and earn rewards! '''; await Share.share(shareText); } } Future sharePassengerCode() async { if (couponCode != null) { final String shareText = '''Get a discount on your first Intaleq ride! Use my referral code: $couponCode Download the Intaleq app now and enjoy your ride! '''; await Share.share(shareText); } } @override void onInit() { super.onInit(); // **MODIFIED**: Sync contacts automatically on controller initialization. syncContactsToServerOnce(); // fetchDriverStats(); } // --- NEW LOGIC: ONE-TIME CONTACTS SYNC --- /// **NEW**: Syncs all phone contacts to the server, but only runs once per user. Future syncContactsToServerOnce() async { final String syncFlagKey = 'contactsSynced_${box.read(BoxName.driverID)}'; // 1. Check if contacts have already been synced for this user. if (box.read(syncFlagKey) == true) { print("Contacts have already been synced for this user."); return; } try { // 2. Request permission and fetch all contacts. if (await FlutterContacts.requestPermission(readonly: true)) { // mySnackbarSuccess('Starting contacts sync in background...'.tr); final List allContacts = await FlutterContacts.getContacts(withProperties: true); // **FIX**: Assign fetched contacts to the class variable. contacts = allContacts; contactMaps.value = contacts.map((contact) { return { 'name': contact.displayName, 'phones': contact.phones.map((phone) => phone.normalizedNumber).toList(), 'emails': contact.emails.map((email) => email.address).toList(), }; }).toList(); update(); // 3. Loop through contacts and save them to the server. for (var contact in allContacts) { if (contact.phones.isNotEmpty) { // Use the normalized phone number for consistency. var phone = contact.phones.first.normalizedNumber; if (phone.isNotEmpty) { CRUD().post(link: AppLink.savePhonesSyria, payload: { "driverId": box.read(BoxName.driverID), // Associate with driver "name": contact.displayName ?? 'No Name', "phone": phone, }); } } } // 4. After a successful sync, set the flag to prevent future syncs. await box.write(syncFlagKey, true); // mySnackbarSuccess('Contacts sync completed successfully!'.tr); } } catch (e) { // mySnackeBarError('An error occurred during contact sync: $e'.tr); } } // --- NEW LOGIC: NATIVE CONTACT PICKER --- /// **MODIFIED**: This function now opens the phone's native contact picker. Future pickContactFromNativeApp() async { try { if (await FlutterContacts.requestPermission(readonly: true)) { // 1. Open the native contacts app to select a single contact. final Contact? contact = await FlutterContacts.openExternalPick(); // 2. If a contact is selected and has a phone number... if (contact != null && contact.phones.isNotEmpty) { String selectedPhone = contact.phones.first.number; // 3. Format the number and update the text field. invitePhoneController.text = _formatSyrianPhoneNumber(selectedPhone); update(); } } else { mySnackeBarError('Contact permission is required to pick contacts'.tr); } } catch (e) { mySnackeBarError('An error occurred while picking contacts: $e'.tr); } } /// **FIX**: Added the missing 'selectPhone' method. void selectPhone(String phone) { // Format the selected phone number and update the text field. invitePhoneController.text = _formatSyrianPhoneNumber(phone); update(); Get.back(); // Close the contacts dialog after selection. } void fetchDriverStats() async { try { var response = await CRUD().get(link: AppLink.getInviteDriver, payload: { "driverId": box.read(BoxName.driverID), }); if (response != 'failure') { var data = jsonDecode(response); driverInvitationData = data['message']; update(); } } catch (e) { // Handle error gracefully } } void fetchDriverStatsPassengers() async { try { var response = await CRUD() .get(link: AppLink.getDriverInvitationToPassengers, payload: { "driverId": box.read(BoxName.driverID), }); if (response != 'failure') { var data = jsonDecode(response); driverInvitationDataToPassengers = data['message']; update(); } } catch (e) { // Handle error gracefully } } void onSelectDriverInvitation(int index) async { MyDialog().getDialog( int.parse((driverInvitationData[index]['countOfInvitDriver'])) < 100 ? '${'When'.tr} ${(driverInvitationData[index]['invitorName'])} ${"complete, you can claim your gift".tr} ' : 'You deserve the gift'.tr, '${(driverInvitationData[index]['invitorName'])} ${(driverInvitationData[index]['countOfInvitDriver'])} / 100 ${'Trip'.tr}', () async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (int.parse((driverInvitationData[index]['countOfInvitDriver'])) < 100) { Get.back(); } else if (isAvailable) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: const AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { if ((driverInvitationData[index]['isGiftToken']).toString() == '0') { Get.back(); await CRUD().post( link: AppLink.updateInviteDriver, payload: {'id': (driverInvitationData[index]['id'])}); await Get.find().addDriverPayment( 'paymentMethod', ('50000'), '', ); await Get.find() .addDriverWalletToInvitor( 'paymentMethod', (driverInvitationData[index]['driverInviterId']), ('50000'), ); NotificationCaptainController().addNotificationCaptain( driverInvitationData[index]['driverInviterId'].toString(), "You have got a gift for invitation".tr, '${"You have 50000".tr} ${'SYP'.tr}', false); NotificationController().showNotification( "You have got a gift for invitation".tr, '${"You have 50000".tr} ${'SYP'.tr}', 'tone1', ''); } else { Get.back(); MyDialog().getDialog("You have got a gift".tr, "Share the app with another new driver".tr, () => Get.back()); } } else { MyDialog() .getDialog('Authentication failed'.tr, '', () => Get.back()); } } else { MyDialog().getDialog( 'Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () => Get.back()); } }, ); } void onSelectPassengerInvitation(int index) async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); MyDialog().getDialog( int.parse(driverInvitationDataToPassengers[index]['countOfInvitDriver'] .toString()) < 3 ? '${'When'.tr} ${(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${"complete, you can claim your gift".tr} ' : 'You deserve the gift'.tr, '${(driverInvitationDataToPassengers[index]['passengerName'].toString())} ${driverInvitationDataToPassengers[index]['countOfInvitDriver']} / 3 ${'Trip'.tr}', () async { if (int.parse(driverInvitationDataToPassengers[index] ['countOfInvitDriver'] .toString()) < 3) { Get.back(); } else if (isAvailable) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: const AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { if (driverInvitationDataToPassengers[index]['isGiftToken'] .toString() == '0') { Get.back(); await Get.find() .addDriverWallet('paymentMethod', '20000', '20000'); await Get.find() .addDriverWalletToInvitor('paymentMethod', driverInvitationData[index]['driverInviterId'], '20000'); await CRUD().post( link: AppLink.updatePassengerGift, payload: {'id': driverInvitationDataToPassengers[index]['id']}, ); NotificationCaptainController().addNotificationCaptain( driverInvitationDataToPassengers[index]['passengerInviterId'] .toString(), "You have got a gift for invitation".tr, '${"You have 20000".tr} ${'SYP'.tr}', false, ); } else { Get.back(); MyDialog().getDialog( "You have got a gift".tr, "Share the app with another new passenger".tr, () => Get.back(), ); } } else { MyDialog() .getDialog('Authentication failed'.tr, '', () => Get.back()); } } else { MyDialog().getDialog( 'Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () => Get.back()); } }, ); } /// Formats a phone number to the standard Syrian international format (+963...). String _formatSyrianPhoneNumber(String input) { String digitsOnly = input.replaceAll(RegExp(r'\D'), ''); if (digitsOnly.startsWith('09') && digitsOnly.length == 10) { return '963${digitsOnly.substring(1)}'; } if (digitsOnly.length == 9 && digitsOnly.startsWith('9')) { return '963$digitsOnly'; } return input; // Fallback for unrecognized formats } String normalizeSyrianPhone(String input) { String phone = input.trim(); // احذف كل شيء غير أرقام phone = phone.replaceAll(RegExp(r'[^0-9]'), ''); // إذا يبدأ بـ 0 → احذفها if (phone.startsWith('0')) { phone = phone.substring(1); } // إذا يبدأ بـ 963 مكررة → احذف التكرار while (phone.startsWith('963963')) { phone = phone.substring(3); } // إذا يبدأ بـ 963 ولكن داخله كمان 963 → خليه مرة واحدة فقط if (phone.startsWith('963') && phone.length > 12) { phone = phone.substring(phone.length - 9); // آخر 9 أرقام } // الآن إذا كان بلا 963 → أضفها if (!phone.startsWith('963')) { phone = '963' + phone; } return phone; } /// Sends an invitation to a potential new driver. void sendInvite() async { if (invitePhoneController.text.isEmpty) { mySnackeBarError('Please enter a phone number'.tr); return; } // Format Syrian phone number: remove leading 0 and add +963 String formattedPhoneNumber = normalizeSyrianPhone(invitePhoneController.text); if (formattedPhoneNumber.length != 12) { mySnackeBarError('Please enter a correct phone'.tr); return; } var response = await CRUD().post(link: AppLink.addInviteDriver, payload: { "driverId": box.read(BoxName.driverID), "inviterDriverPhone": formattedPhoneNumber, }); if (response != 'failure') { var d = (response); mySnackbarSuccess('Invite sent successfully'.tr); String message = '${'*Intaleq DRIVER CODE*'.tr}\n\n' '${"Use this code in registration".tr}\n' '${"To get a gift for both".tr}\n\n' '${"The period of this code is 1 hour".tr}\n\n' '${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n' '_*${d['message']['inviteCode'].toString()}*_\n\n' '${"Install our app:".tr}\n' '*Android:* https://play.google.com/store/apps/details?id=com.intaleq_driver \n\n\n' '*iOS:* https://apps.apple.com/st/app/intaleq-driver/id6482995159'; launchCommunication('whatsapp', formattedPhoneNumber, message); invitePhoneController.clear(); } else { mySnackeBarError("Invite code already used".tr); } } /// Sends an invitation to a potential new passenger. void sendInviteToPassenger() async { if (invitePhoneController.text.isEmpty) { mySnackeBarError('Please enter a phone number'.tr); return; } // Format Syrian phone number: remove leading 0 and add +963 String formattedPhoneNumber = invitePhoneController.text.trim(); if (formattedPhoneNumber.startsWith('0')) { formattedPhoneNumber = formattedPhoneNumber.substring(1); } formattedPhoneNumber = '+963$formattedPhoneNumber'; if (formattedPhoneNumber.length < 12) { // +963 + 9 digits = 12+ mySnackeBarError('Please enter a correct phone'.tr); return; } var response = await CRUD().post( link: AppLink.addInvitationPassenger, payload: { "driverId": box.read(BoxName.driverID), "inviterPassengerPhone": formattedPhoneNumber, }, ); if (response != 'failure') { var d = response; mySnackbarSuccess('Invite sent successfully'.tr); String message = '${'*Intaleq APP CODE*'.tr}\n\n' '${"Use this code in registration".tr}\n\n' '${"To get a gift for both".tr}\n\n' '${"The period of this code is 1 hour".tr}\n\n' '${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n' '_*${d['message']['inviteCode'].toString()}*_\n\n' '${"Install our app:".tr}\n' '*Android:* https://play.google.com/store/apps/details?id=com.Intaleq.intaleq\n\n\n' '*iOS:* https://apps.apple.com/st/app/intaleq-rider/id6748075179'; launchCommunication('whatsapp', formattedPhoneNumber, message); invitePhoneController.clear(); } else { mySnackeBarError("Invite code already used".tr); } } } class PassengerStats { final int totalInvites; final int activeUsers; final double totalEarnings; PassengerStats({ this.totalInvites = 0, this.activeUsers = 0, this.totalEarnings = 0.0, }); } ================================================== FILE PATH: ./lib/controller/auth/captin/history_captain.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:get/get.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../main.dart'; import '../../../views/home/Captin/history/history_details_page.dart'; import '../../functions/crud.dart'; import '../../functions/encrypt_decrypt.dart'; class HistoryCaptainController extends GetxController { bool isloading = false; Map historyData = {}; Map historyDetailsData = {}; late String orderID; getOrderId(String orderId) { orderID = orderId; update(); } getHistory() async { isloading = true; var res = await CRUD().get( link: AppLink.getDriverOrder, payload: {'driver_id': box.read(BoxName.driverID)}); if (res != 'failure') { historyData = jsonDecode(res); isloading = false; update(); } else { Get.defaultDialog( title: 'No ride yet'.tr, middleText: '', barrierDismissible: false, confirm: MyElevatedButton( title: 'Back'.tr, onPressed: () { Get.back(); Get.back(); })); } } getHistoryDetails(String orderId) async { isloading = true; var res = await CRUD() .get(link: AppLink.getRideOrderID, payload: {'id': (orderId)}); historyDetailsData = jsonDecode(res); isloading = false; update(); Get.to(() => HistoryDetailsPage()); } @override void onInit() { getHistory(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/auth/captin/ml_google_doc.dart ================================================== import 'dart:io'; import 'package:get/get.dart'; // import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/functions/llama_ai.dart'; // class CarRegistrationRecognizerController extends GetxController { // @override // void onInit() { // // scanText(); // super.onInit(); // } // // The ImagePicker instance // final ImagePicker _imagePicker = ImagePicker(); // // The GoogleMlKit TextRecognizer instance // // final TextRecognizer _textRecognizer = TextRecognizer(); // // The scanned text // String? scannedText; // String? jsonOutput; // final List> lines = []; // Map extracted = {}; // XFile? image; // CroppedFile? croppedFile; // // Picks an image from the camera or gallery and extracts the text // final List> extractedTextWithCoordinates = []; // Future scanText() async { // // Pick an image from the camera or gallery // image = await _imagePicker.pickImage(source: ImageSource.gallery); // update(); // // If no image was picked, return // if (image == null) { // return; // } // // Crop the image // croppedFile = await ImageCropper().cropImage( // sourcePath: image!.path, // // // uiSettings: [ // AndroidUiSettings( // toolbarTitle: 'Cropper'.tr, // toolbarColor: AppColor.blueColor, // toolbarWidgetColor: AppColor.yellowColor, // initAspectRatio: CropAspectRatioPreset.original, // lockAspectRatio: false), // IOSUiSettings( // title: 'Cropper'.tr, // ), // ], // ); // // If no cropped image was obtained, return // if (croppedFile == null) { // return; // } // // Convert the cropped file to an InputImage object // final InputImage inputImage = InputImage.fromFile(File(croppedFile!.path)); // // Recognize the text in the image // final RecognizedText recognizedText = // await _textRecognizer.processImage(inputImage); // scannedText = recognizedText.text; // // Extract the scanned text line by line // final List> lines = []; // for (var i = 0; i < recognizedText.blocks.length; i++) { // lines.add({ // i.toString(): recognizedText.blocks[i].text, // }); // } // String result = lines.map((map) => map.values.first.toString()).join(' '); // if (result.length > 2200) { // result = result.substring(0, 2200); // } // Map result2 = await LlamaAi().getCarRegistrationData(result, // 'vin,make,made,year,expiration_date,color,owner,registration_date'); // // // Assign the result to the extracted variable // extracted = result2; // update(); // } // } ================================================== FILE PATH: ./lib/controller/auth/captin/login_captin_controller.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:crypto/crypto.dart'; import 'dart:math'; import 'package:http/http.dart' as http; import 'package:permission_handler/permission_handler.dart'; import 'package:sefer_driver/views/auth/captin/cards/sms_signup.dart'; import 'package:sefer_driver/views/auth/syria/registration_view.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import 'package:location/location.dart'; import '../../../constant/api_key.dart'; import '../../../constant/info.dart'; import '../../../print.dart'; import '../../../views/auth/captin/otp_page.dart'; import '../../../views/auth/captin/otp_token_page.dart'; import '../../../views/auth/syria/pending_driver_page.dart'; import '../../firebase/firbase_messge.dart'; import '../../firebase/local_notification.dart'; import '../../firebase/notification_service.dart'; import '../../functions/encrypt_decrypt.dart'; import '../../functions/package_info.dart'; import '../../functions/secure_storage.dart'; import '../../functions/security_checks.dart'; class LoginDriverController extends GetxController { final formKey = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController passwordController2 = TextEditingController(); bool isAgreeTerms = false; bool isGoogleDashOpen = false; bool isGoogleLogin = false; bool isloading = false; late int isTest = 1; final FlutterSecureStorage _storage = const FlutterSecureStorage(); final location = Location(); void changeAgreeTerm() { isAgreeTerms = !isAgreeTerms; update(); } bool isPasswordHidden = true; void togglePasswordVisibility() { isPasswordHidden = !isPasswordHidden; update([ 'passwordVisibility' ]); // Use a unique ID to only update the password field } void changeGoogleDashOpen() { isGoogleDashOpen = !isGoogleDashOpen; update(); } @override void onInit() async { box.write(BoxName.countryCode, 'Syria'); // box.write(BoxName.driverID, '34feffd3fa72d6bee56b'); // await getAppTester(); getJWT(); super.onInit(); } getAppTester() async { var res = await CRUD().get( link: AppLink.getTesterApp, payload: {'appPlatform': AppInformation.appName}); // Log.print('res: ${res}'); if (res != 'failure') { var d = jsonDecode(res); isTest = d['message'][0]['isTest']; // Log.print('isTest: ${isTest}'); box.write(BoxName.isTest, isTest); // Log.print('isTest: ${box.read(BoxName.isTest)}'); update(); } else { isTest = 0; box.write(BoxName.isTest, isTest); update(); return false; } } updateAppTester(String appPlatform) async { await CRUD().post( link: AppLink.updateTesterApp, payload: {'appPlatform': appPlatform}); } isPhoneVerified() async { var res = await CRUD().post( link: AppLink.isPhoneVerified, payload: {'phone_number': box.read(BoxName.phoneDriver)}); if (res != 'failure') { // Get.offAll(() => SyrianCardAI()); Get.offAll(() => RegistrationView()); // isloading = false; // update(); } else { Get.offAll(() => PhoneNumberScreen()); } } void saveAgreementTerms() { box.write(BoxName.agreeTerms, 'agreed'); update(); } void saveCountryCode(String countryCode) { box.write(BoxName.countryCode, countryCode); update(); } var dev = ''; getJwtWallet() async { final random = Random(); if (random.nextBool()) { await SecurityHelper.performSecurityChecks(); } else { await SecurityChecks.isDeviceRootedFromNative(Get.context!); } String fingerPrint = await DeviceHelper.getDeviceFingerprint(); // print('fingerPrint: ${fingerPrint}'); dev = Platform.isAndroid ? 'android' : 'ios'; var payload = { 'id': box.read(BoxName.driverID), 'password': AK.passnpassenger, 'aud': '${AK.allowedWallet}$dev', 'fingerPrint': fingerPrint }; var response1 = await http.post( Uri.parse(AppLink.loginJwtWalletDriver), body: payload, ); // Log.print('response.request: ${response1.request}'); // Log.print('response.body: ${response1.body}'); // print(payload); // Log.print('payment["jwt"]: ${jsonDecode(response1.body)['jwt']}'); await box.write(BoxName.hmac, jsonDecode(response1.body)['hmac']); return jsonDecode(response1.body)['jwt'].toString(); } String shortHash(String password) { var bytes = utf8.encode(password); var digest = sha256.convert(bytes); return base64UrlEncode(digest.bytes); } getJWT() async { dev = Platform.isAndroid ? 'android' : 'ios'; Log.print( 'box.read(BoxName.firstTimeLoadKey): ${box.read(BoxName.firstTimeLoadKey)}'); if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') { var payload = { 'id': box.read(BoxName.driverID) ?? AK.newId, 'password': AK.passnpassenger, 'aud': '${AK.allowed}$dev', }; // Log.print('payload: ${payload}'); var response0 = await http.post( Uri.parse(AppLink.loginFirstTimeDriver), body: payload, ); Log.print('response0: ${response0.body}'); Log.print('request: ${response0.request}'); if (response0.statusCode == 200) { final decodedResponse1 = jsonDecode(response0.body); Log.print('decodedResponse1: ${decodedResponse1}'); final jwt = decodedResponse1['jwt']; box.write(BoxName.jwt, c(jwt)); // ✅ بعد التأكد أن كل المفاتيح موجودة await EncryptionHelper.initialize(); await AppInitializer().getKey(); } else {} } else { await EncryptionHelper.initialize(); var payload = { 'id': box.read(BoxName.driverID), 'password': box.read(BoxName.emailDriver), 'aud': '${AK.allowed}$dev', }; // print(payload); var response1 = await http.post( Uri.parse(AppLink.loginJwtDriver), body: payload, ); // print(response1.request); // print(response1.body); if (response1.statusCode == 200) { final decodedResponse1 = jsonDecode(response1.body); // Log.print('decodedResponse1: ${decodedResponse1}'); final jwt = decodedResponse1['jwt']; await box.write(BoxName.jwt, c(jwt)); await AppInitializer().getKey(); } } } Future getLocationPermission() async { var status = await Permission.locationAlways.status; if (!status.isGranted) { await Permission.locationAlways.request(); } update(); } String generateUniqueIdFromEmail(String email) { // Step 1: Extract the local part of the email String localPart = email.split('@')[0]; // Step 2: Replace invalid characters (if any) String cleanLocalPart = localPart.replaceAll(RegExp(r'[^a-zA-Z0-9]'), ''); // Step 3: Ensure it does not exceed 24 characters if (cleanLocalPart.length > 24) { cleanLocalPart = cleanLocalPart.substring(0, 24); } // Step 4: Generate a random suffix if needed String suffix = generateRandomSuffix(24 - cleanLocalPart.length); return cleanLocalPart + suffix; } String generateRandomSuffix(int length) { const String chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; Random random = Random(); return List.generate(length, (index) => chars[random.nextInt(chars.length)]) .join(''); } bool isInviteDriverFound = false; Future updateInvitationCodeFromRegister() async { var res = await CRUD().post( link: AppLink.updateDriverInvitationDirectly, payload: { "inviterDriverPhone": box.read(BoxName.phoneDriver).toString(), // "driverId": box.read(BoxName.driverID).toString(), }, ); Log.print('invite: ${res}'); if (res['status'] != 'failure') { isInviteDriverFound = true; update(); // mySnackbarSuccess("Code approved".tr); // Localized success message box.write(BoxName.isInstall, '1'); NotificationController().showNotification( "Code approved".tr, "Code approved".tr, 'tone2', ''); NotificationService.sendNotification( target: (res)['message'][0]['token'].toString(), title: 'You have received a gift token!'.tr, body: 'for '.tr + box.read(BoxName.phoneDriver).toString(), isTopic: false, // Important: this is a token tone: 'tone2', driverList: [], category: 'You have received a gift token!', ); } else { // mySnackeBarError( // "You dont have invitation code".tr); // Localized error message } } loginWithGoogleCredential(String driverID, email) async { isloading = true; update(); // await SecurityHelper.performSecurityChecks(); // Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}'); // await getJWT(); var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: { // 'email': email ?? 'yet', 'id': driverID, }); Log.print('loginWithGoogleCredential: ${res}'); if (res == 'failure') { await isPhoneVerified(); isloading = false; // <--- أضفت هذا أيضاً update(); return false; // Get.snackbar('Failure', '', backgroundColor: Colors.red); } else { var jsonDecoeded = jsonDecode(res); var d = jsonDecoeded['data'][0]; if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success' && d['is_verified'].toString() == '1') { box.write(BoxName.emailDriver, d['email']); box.write(BoxName.firstTimeLoadKey, 'false'); box.write(BoxName.driverID, (d['id'])); box.write(BoxName.isTest, '1'); box.write(BoxName.gender, (d['gender'])); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, (d['phone'])); box.write(BoxName.is_claimed, d['is_claimed']); box.write(BoxName.isInstall, d['isInstall']); // box.write( // BoxName.isGiftToken, d['isGiftToken']); box.write(BoxName.nameArabic, (d['name_arabic'])); box.write(BoxName.carYear, d['year']); box.write(BoxName.bankCodeDriver, (d['bankCode'])); box.write(BoxName.accountBankNumberDriver, (d['accountBank'])); box.write( BoxName.nameDriver, '${(d['first_name'])}' ' ${(d['last_name'])}'); if (((d['model']).toString().contains('دراجه') || d['make'].toString().contains('دراجه '))) { if ((d['gender']).toString() == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (int.parse(d['year'].toString()) > 2016) { if (d['gender'].toString() != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (int.parse(d['year'].toString()) > 2002 && int.parse(d['year'].toString()) < 2016) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (int.parse(d['year'].toString()) < 2002) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } // add invitations if (box.read(BoxName.isInstall) == null || box.read(BoxName.isInstall).toString() == '0') { updateInvitationCodeFromRegister(); } // updateAppTester(AppInformation.appName); if (d['status'].toString() != 'yet') { var token = await CRUD().get( link: AppLink.getDriverToken, payload: { 'captain_id': (box.read(BoxName.driverID)).toString() }); String fingerPrint = await DeviceHelper.getDeviceFingerprint(); await storage.write( key: BoxName.fingerPrint, value: fingerPrint.toString()); // print(jsonDecode(token)['data'][0]['token'].toString()); // print(box.read(BoxName.tokenDriver).toString()); // if (box.read(BoxName.emailDriver).toString() != // '963992952235@intaleqapp.com') { if (token != 'failure') { var serverData = jsonDecode(token); if ((serverData['data'][0]['token'].toString()) != box.read(BoxName.tokenDriver).toString() || serverData['data'][0]['fingerPrint'].toString() != fingerPrint.toString()) { await Get.defaultDialog( barrierDismissible: false, title: 'Device Change Detected'.tr, middleText: 'Please verify your identity'.tr, textConfirm: 'Verify'.tr, confirmTextColor: Colors.white, onConfirm: () { // Get.back(); // انتقل لصفحة OTP الجديدة Get.to( () => OtpVerificationPage( phone: d['phone'].toString(), deviceToken: fingerPrint.toString(), token: token.toString(), ptoken: jsonDecode(token)['data'][0]['token'].toString(), ), ); }, ); } // } } Get.offAll(() => HomeCaptain()); // افترض أن هذا الكلاس موجود isloading = false; // <--- أضفت هذا update(); // <--- أضفت هذا return true; } else { Get.offAll( () => DriverVerificationScreen()); // افترض أن هذا الكلاس موجود isloading = false; // <--- أضفت هذا update(); // <--- أضفت هذا return false; } // Get.off(() => HomeCaptain()); } else { Get.offAll(() => PhoneNumberScreen()); isloading = false; update(); return false; // <--- ✅ وهذا السطر موجود للحالات الأخرى } } else { mySnackbarSuccess(''); isloading = false; update(); } } } logintest(String driverID, email) async { isloading = true; update(); // await SecurityHelper.performSecurityChecks(); // Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}'); var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: { 'email': email ?? 'yet', 'id': driverID, }); // print('res is $res'); // if (res == 'failure') { // await isPhoneVerified(); // // Get.snackbar('Failure', '', backgroundColor: Colors.red); // } else // { var jsonDecoeded = jsonDecode(res); var d = jsonDecoeded['data'][0]; if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success') // && // d['is_verified'].toString() == '1') { box.write(BoxName.emailDriver, d['email']); box.write(BoxName.firstTimeLoadKey, 'false'); box.write(BoxName.driverID, (d['id'])); box.write(BoxName.isTest, '1'); box.write(BoxName.gender, (d['gender'])); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, (d['phone'])); box.write(BoxName.is_claimed, d['is_claimed']); box.write(BoxName.isInstall, d['isInstall']); // box.write( // BoxName.isGiftToken, d['isGiftToken']); box.write(BoxName.nameArabic, (d['name_arabic'])); box.write(BoxName.carYear, d['year']); box.write(BoxName.bankCodeDriver, (d['bankCode'])); box.write(BoxName.accountBankNumberDriver, (d['accountBank'])); box.write( BoxName.nameDriver, '${(d['first_name'])}' ' ${(d['last_name'])}'); if (((d['model']).toString().contains('دراجه') || d['make'].toString().contains('دراجه '))) { if ((d['gender']).toString() == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (int.parse(d['year'].toString()) > 2016) { if (d['gender'].toString() != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (int.parse(d['year'].toString()) > 2002 && int.parse(d['year'].toString()) < 2016) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (int.parse(d['year'].toString()) < 2002) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } // updateAppTester(AppInformation.appName); // var token = await CRUD().get( // link: AppLink.getDriverToken, // payload: {'captain_id': (box.read(BoxName.driverID)).toString()}); // String fingerPrint = await DeviceHelper.getDeviceFingerprint(); // await storage.write( // key: BoxName.fingerPrint, value: fingerPrint.toString()); Get.off(() => HomeCaptain()); // } else { // Get.offAll(() => PhoneNumberScreen()); // isloading = false; // update(); // } // } // else { // mySnackbarSuccess(''); // isloading = false; // update(); } } } loginUsingCredentialsWithoutGoogle(String password, email) async { isloading = true; isGoogleLogin = true; update(); var res = await CRUD() .get(link: AppLink.loginUsingCredentialsWithoutGoogle, payload: { 'email': (email), 'password': password, }); box.write(BoxName.emailDriver, (email).toString()); // print(res); if (res == 'failure') { //Failure if (box.read(BoxName.phoneVerified).toString() == '1') { // Get.offAll(() => SyrianCardAI()); Get.offAll(() => RegistrationView()); } else { Get.offAll(() => SmsSignupEgypt()); } isloading = false; update(); } else { var jsonDecoeded = jsonDecode(res); var d = jsonDecoeded['data'][0]; if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success' && d['is_verified'].toString() == '1') { box.write(BoxName.emailDriver, (d['email'])); box.write(BoxName.driverID, (d['id'])); box.write(BoxName.isTest, '1'); box.write(BoxName.gender, (d['gender'])); box.write(BoxName.phoneVerified, d['is_verified'].toString()); box.write(BoxName.phoneDriver, (d['phone'])); box.write(BoxName.nameArabic, (d['name_arabic'])); box.write(BoxName.bankCodeDriver, (d['bankCode'])); box.write(BoxName.accountBankNumberDriver, d['accountBank']); box.write( BoxName.nameDriver, '${(d['first_name'])}' ' ${(d['last_name'])}'); if ((d['model'].toString().contains('دراجه') || d['make'].toString().contains('دراجه '))) { if ((d['gender']).toString() == 'Male') { box.write(BoxName.carTypeOfDriver, 'Scooter'); } else { box.write(BoxName.carTypeOfDriver, 'Pink Bike'); } } else if (int.parse(d['year'].toString()) > 2017) { if ((d['gender']).toString() != 'Male') { box.write(BoxName.carTypeOfDriver, 'Lady'); } else { box.write(BoxName.carTypeOfDriver, 'Comfort'); } } else if (int.parse(d['year'].toString()) > 2002 && int.parse(d['year'].toString()) < 2017) { box.write(BoxName.carTypeOfDriver, 'Speed'); } else if (int.parse(d['year'].toString()) < 2002) { box.write(BoxName.carTypeOfDriver, 'Awfar Car'); } updateAppTester(AppInformation.appName); var fingerPrint = DeviceHelper.getDeviceFingerprint().toString(); await storage.write(key: BoxName.fingerPrint, value: fingerPrint); var token = await CRUD().get( link: AppLink.getDriverToken, payload: {'captain_id': box.read(BoxName.driverID).toString()}); if (token != 'failure') { if ((jsonDecode(token)['data'][0]['token']) != (box.read(BoxName.tokenDriver))) { // Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP( // 'token change'.tr, // 'change device'.tr, // (jsonDecode(token)['data'][0]['token']).toString(), // [], // 'ding.wav'); NotificationService.sendNotification( target: (jsonDecode(token)['data'][0]['token']).toString(), title: 'token change'.tr, body: 'token change'.tr, isTopic: false, // Important: this is a token tone: 'cancel', driverList: [], category: 'token change', ); Get.defaultDialog( title: 'you will use this device?'.tr, middleText: '', confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () async { await CRUD() .post(link: AppLink.addTokensDriver, payload: { 'token': box.read(BoxName.tokenDriver), 'captain_id': box.read(BoxName.driverID).toString(), 'fingerPrint': (fingerPrint).toString() }); Get.back(); })); } } Get.off(() => HomeCaptain()); // Get.off(() => LoginCaptin()); } else { Get.offAll(() => SmsSignupEgypt()); isloading = false; update(); } } else { mySnackeBarError(''); isloading = false; update(); } } } void loginByBoxData() async { Get.to(() => HomeCaptain()); await CRUD().post(link: AppLink.addTokensDriver, payload: { 'token': box.read(BoxName.tokenDriver).toString(), 'captain_id': box.read(BoxName.driverID).toString() }); CRUD().post( link: "${AppLink.seferAlexandriaServer}/ride/firebase/addDriver.php", payload: { 'token': box.read(BoxName.tokenDriver), 'captain_id': box.read(BoxName.driverID).toString() }); CRUD().post( link: "${AppLink.seferGizaServer}/ride/firebase/addDriver.php", payload: { 'token': box.read(BoxName.tokenDriver), 'captain_id': box.read(BoxName.driverID).toString() }); } } ================================================== FILE PATH: ./lib/controller/auth/captin/opt_token_controller.dart ================================================== import 'dart:async'; import 'package:get/get.dart'; import 'package:sefer_driver/print.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../main.dart'; import '../../firebase/firbase_messge.dart'; import '../../firebase/notification_service.dart'; import '../../functions/crud.dart'; class OtpVerificationController extends GetxController { final String phone; final String deviceToken; final String token; final otpCode = ''.obs; final isLoading = false.obs; final isVerifying = false.obs; var canResend = false.obs; var countdown = 120.obs; Timer? _timer; OtpVerificationController({ required this.phone, required this.deviceToken, required this.token, }); @override void onInit() { super.onInit(); sendOtp(); // ترسل تلقائيًا عند فتح الصفحة startCountdown(); } void startCountdown() { canResend.value = false; countdown.value = 120; _timer?.cancel(); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (countdown.value > 0) { countdown.value--; } else { canResend.value = true; timer.cancel(); } }); } Future sendOtp() async { isLoading.value = true; try { final response = await CRUD().post( link: '${AppLink.server}/auth/token_passenger/driver/send_otp_driver.php', payload: { 'receiver': phone, // 'device_token': deviceToken, }, ); if (response != 'failure') { // بإمكانك عرض رسالة نجاح هنا } else { // Get.snackbar('Error', 'Failed to send OTP'); } } catch (e) { Get.snackbar('Error', e.toString()); } finally { isLoading.value = false; } } Future verifyOtp(String ptoken) async { isVerifying.value = true; var finger = await storage.read(key: BoxName.fingerPrint); try { final response = await CRUD().post( link: '${AppLink.server}/auth/token_passenger/driver/verify_otp_driver.php', payload: { 'phone_number': phone, 'otp': otpCode.value, 'token': box.read(BoxName.tokenDriver).toString(), 'fingerPrint': finger.toString(), }, ); if (response != 'failure') { Log.print('response: ${response}'); Get.back(); // توجه إلى الصفحة التالية await CRUD().post( link: '${AppLink.paymentServer}/auth/token/update_driver_auth.php', payload: { 'token': box.read(BoxName.tokenDriver).toString(), 'fingerPrint': finger.toString(), 'captain_id': box.read(BoxName.driverID).toString(), }); final fcm = Get.isRegistered() ? Get.find() : Get.put(FirebaseMessagesController()); // await fcm.sendNotificationToDriverMAP( // 'token change', // 'change device'.tr, // ptoken.toString(), // [], // 'cancel.wav', // ); await NotificationService.sendNotification( target: ptoken.toString(), title: 'token change'.tr, body: 'token change'.tr, isTopic: false, // Important: this is a token tone: 'cancel', driverList: [], category: 'token change', ); Get.offAll(() => HomeCaptain()); } else { Get.snackbar('Verification Failed', 'OTP is incorrect or expired'); } } catch (e) { Get.snackbar('Error', e.toString()); } finally { isVerifying.value = false; } } } ================================================== FILE PATH: ./lib/controller/auth/captin/register_captin_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/functions/ocr_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/captin/login_captin.dart'; import 'package:sefer_driver/views/auth/captin/verify_email_captain.dart'; import '../../../constant/colors.dart'; import '../../../views/auth/captin/ai_page.dart'; import '../../../views/auth/syria/registration_view.dart'; import '../../../views/home/Captin/home_captain/home_captin.dart'; import '../../functions/sms_egypt_controller.dart'; class RegisterCaptainController extends GetxController { final formKey = GlobalKey(); final formKey3 = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController verifyCode = TextEditingController(); String birthDate = 'Birth Date'.tr; String gender = 'Male'.tr; bool isLoading = false; bool isSent = false; late String name; late String licenseClass; late String documentNo; late String address; late String height; late String postalCode; late String sex; late String stateCode; late String expireDate; late String dob; getBirthDate() { Get.defaultDialog( title: 'Select Date'.tr, content: SizedBox( width: 300, child: CalendarDatePicker( initialDate: DateTime.now().subtract(const Duration(days: 18 * 365)), firstDate: DateTime.parse('1940-06-01'), lastDate: DateTime.now().subtract(const Duration(days: 18 * 365)), onDateChanged: (date) { // Get the selected date and convert it to a DateTime object DateTime dateTime = date; // Call the getOrders() function from the controller birthDate = dateTime.toString().split(' ')[0]; update(); Get.back(); }, // onDateChanged: (DateTime value) {}, ), ), ); } @override void onInit() { // Get.put(SmsEgyptController()); super.onInit(); } void changeGender(String value) { gender = value; update(); } bool isValidEgyptianPhoneNumber(String phoneNumber) { // Remove any non-digit characters (spaces, dashes, etc.) phoneNumber = phoneNumber.replaceAll(RegExp(r'\D+'), ''); // Check if the phone number has exactly 11 digits if (phoneNumber.length != 11) { return false; } // Check if the phone number starts with 010, 011, 012, or 015 RegExp validPrefixes = RegExp(r'^01[0125]\d{8}$'); return validPrefixes.hasMatch(phoneNumber); } sendOtpMessage() async { SmsEgyptController smsEgyptController = Get.put(SmsEgyptController()); isLoading = true; update(); isLoading = true; update(); if (formKey3.currentState!.validate()) { if (box.read(BoxName.countryCode) == 'Egypt') { if (isValidEgyptianPhoneNumber(phoneController.text)) { var responseCheker = await CRUD() .post(link: AppLink.checkPhoneNumberISVerfiedDriver, payload: { 'phone_number': ('+2${phoneController.text}'), }); if (responseCheker != 'failure') { var d = jsonDecode(responseCheker); if (d['message'][0]['is_verified'].toString() == '1') { Get.snackbar('Phone number is verified before'.tr, '', backgroundColor: AppColor.greenColor); box.write(BoxName.phoneVerified, '1'); box.write(BoxName.phone, ('+2${phoneController.text}')); await Get.put(LoginDriverController()).loginWithGoogleCredential( box.read(BoxName.driverID).toString(), (box.read(BoxName.emailDriver).toString()), ); } else { await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: { 'phone_number': ('+2${phoneController.text}'), "driverId": box.read(BoxName.driverID), "email": (box.read(BoxName.emailDriver)), }); isSent = true; isLoading = false; update(); } } else { await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: { 'phone_number': ('+2${phoneController.text}'), "driverId": box.read(BoxName.driverID), "email": box.read(BoxName.emailDriver), }); isSent = true; isLoading = false; update(); } } else { mySnackeBarError( 'Phone Number wrong'.tr, ); } } } isLoading = false; update(); } DateTime? lastOtpSentTime; // Store the last OTP sent time int otpResendInterval = 300; // 5 minutes in seconds // Main function to handle OTP sending // sendOtpMessage() async { // if (_isOtpResendAllowed()) { // isLoading = true; // update(); // if (formKey3.currentState!.validate()) { // String countryCode = box.read(BoxName.countryCode); // String phoneNumber = phoneController.text; // if (countryCode == 'Egypt' && isValidEgyptianPhoneNumber(phoneNumber)) { // await _checkAndSendOtp(phoneNumber); // } else { // _showErrorMessage('Phone Number is not Egypt phone '.tr); // } // } // isLoading = false; // update(); // } else { // _showCooldownMessage(); // } // } // Check if the resend OTP request is allowed (5 minutes cooldown) // bool _isOtpResendAllowed() { // if (lastOtpSentTime == null) return true; // final int elapsedTime = // DateTime.now().difference(lastOtpSentTime!).inSeconds; // return elapsedTime >= otpResendInterval; // } // // Show message when user tries to resend OTP too soon // void _showCooldownMessage() { // int remainingTime = otpResendInterval - // DateTime.now().difference(lastOtpSentTime!).inSeconds; // Get.snackbar( // 'Please wait ${remainingTime ~/ 60}:${(remainingTime % 60).toString().padLeft(2, '0')} minutes before requesting again', // '', // backgroundColor: AppColor.redColor, // ); // } // // Check if the phone number has been verified, and send OTP if not verified // _checkAndSendOtp(String phoneNumber) async { // var responseChecker = await CRUD().post( // link: AppLink.checkPhoneNumberISVerfiedDriver, // payload: { // 'phone_number': '+2$phoneNumber', // }, // ); // if (responseChecker != 'failure') { // var responseData = jsonDecode(responseChecker); // if (_isPhoneVerified(responseData)) { // _handleAlreadyVerified(); // } else { // await _sendOtpAndSms(phoneNumber); // } // } else { // await _sendOtpAndSms(phoneNumber); // } // } // Check if the phone number is already verified bool _isPhoneVerified(dynamic responseData) { return responseData['message'][0]['is_verified'].toString() == '1'; } // Handle case where phone number is already verified _handleAlreadyVerified() { mySnackbarSuccess('Phone number is already verified'.tr); box.write(BoxName.phoneVerified, '1'); box.write(BoxName.phone, ('+2${phoneController.text}')); Get.put(LoginDriverController()).loginWithGoogleCredential( box.read(BoxName.driverID).toString(), box.read(BoxName.emailDriver).toString(), ); } // Send OTP and SMS _sendOtpAndSms(String phoneNumber) async { SmsEgyptController smsEgyptController = Get.put(SmsEgyptController()); int randomNumber = Random().nextInt(100000) + 1; await CRUD().post( link: AppLink.sendVerifyOtpMessage, payload: { 'phone_number': ('+2$phoneNumber'), 'token_code': (randomNumber.toString()), 'driverId': box.read(BoxName.driverID), 'email': box.read(BoxName.emailDriver), }, ); await smsEgyptController.sendSmsEgypt(phoneNumber); lastOtpSentTime = DateTime.now(); // Update the last OTP sent time isSent = true; isLoading = false; update(); } verifySMSCode() async { // var loginDriverController = Get.put(LoginDriverController()); if (formKey3.currentState!.validate()) { var res = await CRUD().post(link: AppLink.verifyOtpDriver, payload: { 'phone_number': ('+2${phoneController.text}'), 'token_code': (verifyCode.text.toString()), }); if (res != 'failure') { // var dec = jsonDecode(res); box.write(BoxName.phoneDriver, ('+2${phoneController.text}')); box.write(BoxName.phoneVerified, '1'); // loginDriverController.isGoogleLogin == true // ? await loginDriverController.loginUsingCredentialsWithoutGoogle( // loginDriverController.passwordController.text.toString(), // box.read(BoxName.emailDriver).toString(), // ) // : await loginDriverController.loginUsingCredentials( // box.read(BoxName.driverID).toString(), // box.read(BoxName.emailDriver).toString(), // ); // Get.offAll(() => SyrianCardAI()); Get.to(() => RegistrationView()); // } else { // Get.snackbar('title', 'message'); // } } } else { mySnackeBarError('you must insert token code '.tr); } } sendVerifications() async { var res = await CRUD().post(link: AppLink.verifyEmail, payload: { 'email': emailController.text.isEmpty ? (Get.find().emailController.text.toString()) : (emailController.text), 'token': (verifyCode.text), }); if (res != 'failure') { if (Get.find().emailController.text.toString() != '') { Get.offAll(() => HomeCaptain()); } else { // Get.to(() => CarLicensePage()); } } } void nextToAIDetection() async { //Todo dont forget this if (formKey.currentState!.validate()) { isLoading = true; update(); Get.to(() => AiPage()); } } Map payloadLisence = {}; void getFromController() { name = Get.find().name; licenseClass = Get.find().licenseClass.toString(); documentNo = Get.find().documentNo.toString(); address = Get.find().address.toString(); height = Get.find().height.toString(); postalCode = Get.find().address.toString(); sex = Get.find().sex.toString(); stateCode = Get.find().postalCode.toString(); expireDate = Get.find().expireDate.toString(); dob = Get.find().dob.toString(); update(); } Future addLisence() async { getFromController(); var res = await CRUD().post(link: AppLink.addLicense, payload: { 'name': name, 'licenseClass': licenseClass, 'documentNo': documentNo, 'address': address, 'height': height, 'postalCode': postalCode, 'sex': sex, 'stateCode': stateCode, 'expireDate': expireDate, 'dateOfBirth': dob, }); isLoading = false; update(); if (jsonDecode(res)['status'] == 'success') { // Get.to(() => AiPage()); //todo rplace this } } void addRegisrationCarForDriver(String vin, make, model, year, color, owner, expirationDate, registrationDate) async { getFromController(); var res = await CRUD().post(link: AppLink.addRegisrationCar, payload: { 'vin': vin, 'make': make, 'model': model, 'year': year, 'expirationDate': expirationDate, 'color': color, 'owner': owner, 'registrationDate': registrationDate, }); box.write(BoxName.vin, vin); box.write(BoxName.make, make); box.write(BoxName.model, model); box.write(BoxName.year, year); box.write(BoxName.expirationDate, expirationDate); box.write(BoxName.color, color); box.write(BoxName.owner, owner); box.write(BoxName.registrationDate, registrationDate); isLoading = false; update(); if (jsonDecode(res)['status'] == 'success') { Get.offAll(() => LoginCaptin()); //todo replace this } } Future register() async { getFromController(); if (formKey.currentState!.validate()) { isLoading = true; update(); var res = await CRUD().post(link: AppLink.signUpCaptin, payload: { 'first_name': name.split(' ')[1], 'last_name': name.split(' ')[0], 'email': emailController.text, 'phone': phoneController.text, 'password': passwordController.text, 'gender': sex, 'site': address, 'birthdate': dob, }); isLoading = false; update(); if (jsonDecode(res)['status'] == 'success') { box.write(BoxName.driverID, jsonDecode(res)['message']); box.write(BoxName.dobDriver, dob); box.write(BoxName.sexDriver, sex); box.write(BoxName.phoneDriver, phoneController.text); box.write(BoxName.lastNameDriver, name.split(' ')[0]); int randomNumber = Random().nextInt(100000) + 1; await CRUD().post(link: AppLink.sendVerifyEmail, payload: { 'email': emailController.text, 'token': randomNumber.toString(), }); Get.to(() => VerifyEmailCaptainPage()); } } } } ================================================== FILE PATH: ./lib/controller/notification/notification_captain_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../functions/crud.dart'; class NotificationCaptainController extends GetxController { bool isLoading = false; Map notificationData = {}; getNotifications() async { isLoading = true; update(); var res = await CRUD().get( link: AppLink.getNotificationCaptain, payload: {'driverID': box.read(BoxName.driverID)}); if (res == "failure") { // MyDialog().getDialog('There is no notification yet'.tr, '', () { // Get.back(); // Get.back(); // }); Get.dialog( CupertinoAlertDialog( title: Column( children: [ const Icon( CupertinoIcons.bell_slash_fill, color: CupertinoColors.systemGrey, size: 40, ), const SizedBox(height: 12), Text( 'There is no notification yet'.tr, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, ), ), ], ), actions: [ CupertinoDialogAction( onPressed: () { Get.back(); Get.back(); }, child: Text('Back'.tr), ), ], ), barrierDismissible: true, transitionCurve: Curves.easeOutBack, transitionDuration: const Duration(milliseconds: 200), ); } notificationData = jsonDecode(res); // sql.insertData(notificationData['message'], TableName.captainNotification); isLoading = false; update(); } updateNotification(String id) async { await CRUD().post( link: AppLink.updateNotificationCaptain, payload: {'isShown': 'true', 'id': id}, ); } addNotificationCaptain(String driverId, title, body, isPin) async { await CRUD().post(link: AppLink.addNotificationCaptain, payload: { 'driverID': driverId, 'title': title, 'body': body, 'isPin': isPin }); } @override void onInit() { getNotifications(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/notification/passenger_notification_controller.dart ================================================== import 'dart:convert'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/firebase/firbase_messge.dart'; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../constant/style.dart'; import '../../main.dart'; import '../../views/widgets/elevated_btn.dart'; import '../firebase/notification_service.dart'; import '../functions/crud.dart'; class PassengerNotificationController extends GetxController { bool isloading = false; Map notificationData = {}; getNotifications() async { isloading = true; update(); var res = await CRUD().get( link: AppLink.getNotificationPassenger, payload: {'passenger_id': box.read(BoxName.passengerID)}); if (res == "failure") { Get.defaultDialog( title: 'There is no notification yet'.tr, titleStyle: AppStyle.title, middleText: '', confirm: MyElevatedButton( title: 'Back', onPressed: () { Get.back(); Get.back(); })); } notificationData = jsonDecode(res); // sql.insertData(notificationData['message'], TableName.captainNotification); isloading = false; update(); } updateNotification(String id) async { await CRUD().post( link: AppLink.updateNotificationPassenger, payload: {'isShown': 'true', 'id': id}, ); Get.back(); getNotifications(); } addNotificationToPassenger(String title, body) async { var res = CRUD().post(link: AppLink.addNotificationPassenger, payload: { 'title': title, 'body': body, }); // FirebaseMessagesController() // .sendNotificationToPassengerToken(title, body, 'token', [], 'ding.wav'); NotificationService.sendNotification( target: 'token'.toString(), title: title.tr, body: body, isTopic: false, // Important: this is a token tone: 'ding', driverList: [], category: title, ); } @override void onInit() { getNotifications(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/notification/ride_available_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; // Import for WidgetsBinding import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../../constant/links.dart'; import '../functions/crud.dart'; import '../functions/location_controller.dart'; class RideAvailableController extends GetxController { bool isLoading = false; // FIX 1: Initialize the map with a default structure. // This prevents `rideAvailableMap['message']` from ever being null in the UI. Map rideAvailableMap = {'message': []}; late LatLng southwest; late LatLng northeast; LatLngBounds calculateBounds(double lat, double lng, double radiusInMeters) { const double earthRadius = 6378137.0; // Earth's radius in meters double latDelta = (radiusInMeters / earthRadius) * (180 / pi); double lngDelta = (radiusInMeters / (earthRadius * cos(pi * lat / 180))) * (180 / pi); double minLat = lat - latDelta; double maxLat = lat + latDelta; double minLng = lng - lngDelta; double maxLng = lng + lngDelta; minLat = max(-90.0, minLat); maxLat = min(90.0, maxLat); minLng = (minLng + 180) % 360 - 180; maxLng = (maxLng + 180) % 360 - 180; if (minLng > maxLng) { double temp = minLng; minLng = maxLng; maxLng = temp; } return LatLngBounds( southwest: LatLng(minLat, minLng), northeast: LatLng(maxLat, maxLng), ); } double calculateDistance(String startLocation) { List startLocationParts = startLocation.split(','); double startLatitude = double.parse(startLocationParts[0]); double startLongitude = double.parse(startLocationParts[1]); double currentLatitude = Get.find().myLocation.latitude; double currentLongitude = Get.find().myLocation.longitude; return Geolocator.distanceBetween( currentLatitude, currentLongitude, startLatitude, startLongitude, ); } // A helper function to safely show dialogs after the build cycle is complete. void _showDialogAfterBuild(Widget dialog) { // FIX 2: Use addPostFrameCallback to ensure dialogs are shown after the build process. // This resolves the "visitChildElements() called during build" error. WidgetsBinding.instance.addPostFrameCallback((_) { Get.dialog( dialog, barrierDismissible: true, transitionCurve: Curves.easeOutBack, transitionDuration: const Duration(milliseconds: 200), ); }); } Future getRideAvailable() async { try { isLoading = true; update(); LatLngBounds bounds = calculateBounds( Get.find().myLocation.latitude, Get.find().myLocation.longitude, 4000); var payload = { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }; var res = await CRUD().get(link: AppLink.getRideWaiting, payload: payload); isLoading = false; // Request is complete, stop loading indicator. if (res != 'failure') { final decodedResponse = jsonDecode(res); // Check for valid response structure if (decodedResponse is Map && decodedResponse.containsKey('message') && decodedResponse['message'] is List) { rideAvailableMap = decodedResponse; // If the list of rides is empty, show the "No Rides" dialog if ((rideAvailableMap['message'] as List).isEmpty) { _showDialogAfterBuild(_buildNoRidesDialog()); } } else { // If response format is unexpected, treat as no rides and show dialog rideAvailableMap = {'message': []}; _showDialogAfterBuild(_buildNoRidesDialog()); } update(); // Update the UI with new data (or empty list) } else { // This block now handles network/server errors correctly HapticFeedback.lightImpact(); update(); // Update UI to turn off loader // Show a proper error dialog instead of "No Rides" _showDialogAfterBuild( _buildErrorDialog("Failed to fetch rides. Please try again.".tr)); } } catch (e) { isLoading = false; update(); // This catches other exceptions like JSON parsing errors _showDialogAfterBuild( _buildErrorDialog("An unexpected error occurred.".tr)); } } // Extracted dialogs into builder methods for cleanliness. Widget _buildNoRidesDialog() { return CupertinoAlertDialog( title: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( CupertinoIcons.car, size: 44, color: CupertinoColors.systemGrey, ), const SizedBox(height: 12), Text( "No Rides Available".tr, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600), ), ], ), content: Padding( padding: const EdgeInsets.only(top: 8), child: Text( "Please check back later for available rides.".tr, style: const TextStyle(fontSize: 13, color: CupertinoColors.systemGrey), ), ), actions: [ CupertinoDialogAction( onPressed: () { Get.back(); // Close dialog Get.back(); // Go back from AvailableRidesPage }, child: Text('OK'.tr), ), ], ); } Widget _buildErrorDialog(String error) { // You can log the error here for debugging. // print("Error fetching rides: $error"); return CupertinoAlertDialog( title: const Icon( CupertinoIcons.exclamationmark_triangle_fill, color: CupertinoColors.systemRed, size: 44, ), content: Text( error, // Display the specific error message passed to the function style: const TextStyle(fontSize: 14), ), actions: [ CupertinoDialogAction( onPressed: () { Get.back(); // Close dialog Get.back(); // Go back from AvailableRidesPage }, child: Text('OK'.tr), ), ], ); } @override void onInit() { super.onInit(); getRideAvailable(); } } ================================================== FILE PATH: ./lib/controller/payment/paymob.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:dio/dio.dart' as dio; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../constant/api_key.dart'; import '../../main.dart'; import '../functions/encrypt_decrypt.dart'; class PaymobManager extends GetxController { String authanticationToken1 = ""; String orderId1 = ""; Future getPaymentKey(int amount, String currency) async { try { String authanticationToken = await _getAuthanticationToken(); int orderId = await _getOrderId( authanticationToken: authanticationToken, amount: (100 * amount).toString(), currency: currency, ); String paymentKey = await _getPaymentKey( authanticationToken: authanticationToken, amount: (100 * amount).toString(), currency: currency, orderId: orderId.toString(), ); authanticationToken1 = authanticationToken.toString(); orderId1 = orderId.toString(); update(); return paymentKey; } catch (e) { throw Exception(); } } Future payWithPayMob(int amount, String currency) async { // 1. Fetch Payment Key (Assuming PaymobManager is a custom class) String paymentToken; try { paymentToken = await PaymobManager().getPaymentKey(amount, currency); } on Exception catch (e) { // Handle errors gracefully, e.g., display error message to user return; } // 2. Prepare Payment Data Payload final Map data = { "source": { "identifier": "01010101010", // Replace with actual source identifier "subtype": "WALLET", }, "payment_token": paymentToken, }; // 3. Make Payment Request using Dio final dio = Dio(); try { final response = await dio.post( 'https://accept.paymobsolutions.com/api/acceptance/payments/pay', data: data, ); // 4. Handle Payment Response if (response.statusCode == 200) { final paymentData = response.data; // Assuming JSON response // Navigate to success screen or display success message launchUrl(Uri.parse(paymentData['iframe_redirection_url'])); } else { // Payment failed: Handle errors (e.g., display error message) } } on DioError catch (e) { // Handle network or Dio-related errors } } Future _getStatusAfterPaid() async { final dio.Response response = await Dio().post( "https://accept.paymob.com/api/ecommerce/orders/transaction_inquiry", data: { "auth_token": authanticationToken1, "merchant_order_id": "970960", "order_id": orderId1 }); return response.data["success"]; } Future _getAuthanticationToken() async { final dio.Response response = await Dio().post("https://accept.paymob.com/api/auth/tokens", data: { "api_key": AK.payMobApikey, 'username': AK.usernamePayMob, "password": AK.passwordPayMob, }); return response.data["token"]; } Future _getOrderId({ required String authanticationToken, required String amount, required String currency, }) async { final dio.Response response = await Dio() .post("https://accept.paymob.com/api/ecommerce/orders", data: { "auth_token": authanticationToken, "amount_cents": amount, "currency": currency, "delivery_needed": "false", "items": [], }); return response.data["id"]; } Future _getPaymentKey({ required String authanticationToken, required String orderId, required String amount, required String currency, }) async { final dio.Response response = await Dio() .post("https://accept.paymob.com/api/acceptance/payment_keys", data: { "expiration": 200, "auth_token": authanticationToken.toString(), "order_id": orderId.toString(), "integration_id": 4556056, ////todo wallet or online card int.parse(AK.integrationIdPayMob), "lock_order_when_paid": "false", "amount_cents": amount, "currency": currency, "billing_data": { "first_name": (box.read(BoxName.nameDriver)), "last_name": (box.read(BoxName.lastNameDriver)), "email": (box.read(BoxName.emailDriver)), "phone_number": (box.read(BoxName.phoneDriver)), "apartment": "NA", "floor": "NA", "street": "NA", "building": "NA", "shipping_method": "NA", "postal_code": "NA", "city": "NA", "country": box.read(BoxName.countryCode), "state": "NA" }, }); return response.data["token"]; } } ================================================== FILE PATH: ./lib/controller/payment/payment_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/tts.dart'; import 'package:sefer_driver/controller/payment/paymob/paymob_response.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:flutter_paypal/flutter_paypal.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:get/get.dart'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/info.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../../print.dart'; import '../functions/crud.dart'; import '../functions/encrypt_decrypt.dart'; import '../functions/toast.dart'; import 'paymob/paymob_wallet.dart'; class PaymentController extends GetxController { bool isLoading = false; bool isWalletChecked = true; bool isCashChecked = false; bool isWalletFound = false; bool isPromoSheetDialogue = false; final formKey = GlobalKey(); final promo = TextEditingController(); // double totalPassenger = // double.parse(Get.find().totalPricePassenger); int? selectedAmount = 0; List totalPassengerWalletDetails = []; final walletphoneController = TextEditingController(); String passengerTotalWalletAmount = ''; String ip = '1'; DateTime now = DateTime.now(); late int timestamp; void updateSelectedAmount(int value) { selectedAmount = value; update(); } void changePromoSheetDialogue() { isPromoSheetDialogue = !isPromoSheetDialogue; update(); } getPassengerWallet() async { isLoading = true; update(); await CRUD().getWallet( link: AppLink.getWalletByPassenger, payload: {'passenger_id': box.read(BoxName.passengerID)}).then((value) { box.write(BoxName.passengerWalletTotal, jsonDecode(value)['message'][0]['total'].toString()); }); isLoading = false; update(); } addPassengerWallet() async { isLoading = true; update(); // double sallaryAccountNowBeforeAdding = // double.parse(box.read(BoxName.passengerWalletTotal).toString()); await CRUD().postWallet(link: AppLink.addPassengersWallet, payload: { 'passenger_id': box.read(BoxName.passengerID).toString(), 'balance': selectedAmount.toString() }).then((value) { getPassengerWallet(); // sallaryAccountNowBeforeAdding = sallaryAccountNowBeforeAdding + // double.parse(selectedAmount.toString()); // box.write(BoxName.passengerWalletTotal, sallaryAccountNowBeforeAdding); }); isLoading = false; update(); } // void onChangedPaymentMethodWallet(bool? value) { // if (box.read(BoxName.passengerWalletTotal) == null || // double.parse(box.read(BoxName.passengerWalletTotal).toString()) < // totalPassenger) { // isWalletChecked = false; // isWalletChecked ? isCashChecked = true : isCashChecked = true; // update(); // } else { // isWalletChecked = !isWalletChecked; // isWalletChecked ? isCashChecked = false : isCashChecked = true; // update(); // } // } // void onChangedPaymentMethodCash(bool? value) { // if (box.read(BoxName.passengerWalletTotal) == null || // double.parse(box.read(BoxName.passengerWalletTotal)) < totalPassenger) { // isWalletChecked = false; // isCashChecked = !isCashChecked; // isCashChecked ? isWalletChecked = false : isWalletChecked = false; // update(); // } else { // isCashChecked = !isCashChecked; // isCashChecked ? isWalletChecked = false : isWalletChecked = true; // update(); // } // } late String clientSecret; Future makePaymentStripe( double amount, String currency, Function method) async { var newAmount = (amount * 100).toInt(); try { // Check if local authentication is available bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', ); if (didAuthenticate) { // User authenticated successfully, proceed with payment clientSecret = await getClientSecret(newAmount.toString(), currency); await initializePaymentSheet(clientSecret); await Stripe.instance.presentPaymentSheet(); method(); } else { // Authentication failed, handle accordingly } } else { // Local authentication not available, proceed with payment without authentication clientSecret = await getClientSecret(newAmount.toString(), currency); await initializePaymentSheet(clientSecret); await Stripe.instance.presentPaymentSheet(); method(); } } catch (e) { rethrow; } } Future initializePaymentSheet(String clientSecret) async { await Stripe.instance.initPaymentSheet( paymentSheetParameters: SetupPaymentSheetParameters( // intentConfiguration: IntentConfiguration.fromJson({}), // applePay: const PaymentSheetApplePay(merchantCountryCode: 'US'), // googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US'), paymentIntentClientSecret: clientSecret, merchantDisplayName: AppInformation.appName, billingDetails: BillingDetails( name: (box.read(BoxName.nameDriver)), email: (box.read(BoxName.emailDriver)), phone: (box.read(BoxName.phoneDriver)), address: Address( city: 'city', country: box.read(BoxName.countryCode), //'United States' line1: '', line2: '', postalCode: '12345', state: box.read(BoxName.countryCode) // 'Boston' )), allowsDelayedPaymentMethods: true, customerEphemeralKeySecret: Stripe.merchantIdentifier, appearance: const PaymentSheetAppearance( shapes: PaymentSheetShape(borderRadius: 12), colors: PaymentSheetAppearanceColors( background: AppColor.secondaryColor, ), ), billingDetailsCollectionConfiguration: const BillingDetailsCollectionConfiguration( name: CollectionMode.automatic, phone: CollectionMode.automatic, email: CollectionMode.automatic, // address: CollectionMode.automatic, ), ), ); } Future getClientSecret(String amount, currency) async { var res = await CRUD().postStripe( link: 'https://api.stripe.com/v1/payment_intents', payload: { 'amount': amount, 'currency': currency, 'payment_method_types[0]': 'card' }, ); // Convert the res object to a JSON object final jsonResponse = jsonDecode(res); // Check if the client_secret property exists and is not null if (jsonResponse.containsKey('client_secret') && jsonResponse['client_secret'] != null) { // Return the client_secret property return jsonResponse['client_secret'] as String; } else { throw Exception('Failed to fetch client secret'); } } Future configure3dSecureFuture() async { await Stripe.instance.openApplePaySetup(); } Future makePaymentPayPal(BuildContext context) async { try { // Check if local authentication is available bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', ); if (didAuthenticate) { // User authenticated successfully, proceed with payment if (selectedAmount != 0) { changePromoSheetDialogue(); Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => UsePaypal( sandboxMode: true, clientId: AK.payPalClientId, secretKey: AK.payPalSecret, returnURL: AppInformation.website, cancelURL: "${AppInformation.website}/cancel", transactions: [ { "amount": { //sb-opsju26682403@personal.example.com "total": '$selectedAmount', "currency": box.read(BoxName.countryCode) == 'Egypt' ? 'EGP' : "JOD", "details": { "subtotal": '$selectedAmount', "shipping": '0', "shipping_discount": 0 } }, "description": "The payment transaction description.", "payment_options": const { "allowed_payment_method": "INSTANT_FUNDING_SOURCE" }, "item_list": { "items": [ { "name": "${AppInformation.appName} Wallet ", "quantity": 1, "price": '$selectedAmount', "currency": "USD" } ], // shipping address is not required though "shipping_address": const { "recipient_name": "${AppInformation.appName} Wallet", "line1": "Shafa Badran", "line2": "", "city": "Amman", "country_code": "JO", "postal_code": "13112", "phone": "+962798583052", "state": "Amman" }, } } ], note: "Contact us for any questions on your order.".tr, onSuccess: (Map params) async { addPassengerWallet(); changePromoSheetDialogue(); await getPassengerWallet(); }, onError: (error) { Toast.show(context, ' $error'.tr, AppColor.redColor); }, onCancel: (params) { Toast.show(context, 'Pyament Cancelled .'.tr, AppColor.yellowColor); }), ), ); } else { Toast.show(context, 'You will choose one of above !'.tr, AppColor.redColor); } } else { // Authentication failed, handle accordingly } } } catch (e) { rethrow; } } Map licenseDetailsMap = {}; Future getLicenseInfo() async { var res = await CRUD().get( link: AppLink.getLicense, payload: {'driverID': box.read(BoxName.driverID)}); licenseDetailsMap = jsonDecode(res); } Future createConnectAccount() async { String url = 'https://api.stripe.com/v1/accounts'; await getLicenseInfo(); DateTime dob = DateTime.parse(licenseDetailsMap['message'][0]['dateOfBirth']); int currentTimestamp = (DateTime.now().millisecondsSinceEpoch / 1000).round(); int day = dob.day; int month = dob.month; int year = dob.year; await getIpAddress(); final body = { "type": "custom", "business_profile[name]": box.read(BoxName.nameDriver), "business_profile[product_description]": "Captain", "business_profile[support_address][city]": "San Francisco", "business_profile[support_address][country]": 'US', "business_profile[support_address][line1]": licenseDetailsMap['message'][0]['address'].toString().trim()[0], "business_profile[support_address][postal_code]": licenseDetailsMap['message'][0]['postalCode'], "business_profile[support_address][state]": "MA", "business_profile[support_email]": "support@sefer.live", "business_profile[support_phone]": "555-123-4567", "business_profile[url]": "https://sefer.live", "business_type": "individual", "capabilities[card_payments][requested]": "true", "capabilities[transfers][requested]": "true", "company[address][city]": "ATTLEBORO", "company[address][country]": "US", "company[address][line1]": "1249 NEWPORT AVE", "company[address][postal_code]": "02703 ", "company[address][state]": "MA", "company[name]": AppInformation.companyName, "country": "us", "default_currency": "usd", "email": "support@sefer.live", // "individual[ssn]": "123-45-6789", // "individual[id_number]": licenseDetailsMap['message'][0]['documentNo'], // "individual[id_type]": "drivers_license", // "individual[address][city]": "ATTLEBORO", "individual[address][country]": "US", "individual[address][line1]": licenseDetailsMap['message'][0]['address'], // "individual[address][postal_code]": licenseDetailsMap['message'][0] // ['postalCode'], "individual[address][state]": "MA", // "individual[ssn_last_4]": '1111', //////// "individual[dob][day]": day.toString(), "individual[dob][month]": month.toString(), "individual[dob][year]": year.toString(), "individual[email]": box.read(BoxName.emailDriver), "individual[first_name]": licenseDetailsMap['message'][0]['name'].toString().split(' ')[0], "individual[gender]": licenseDetailsMap['message'][0]['sex'] == 'M' ? 'male' : 'female', "individual[last_name]": licenseDetailsMap['message'][0]['name'].toString().split(' ')[1], // "individual[phone]": box.read(BoxName.phoneDriver),//////////// "tos_acceptance[date]": currentTimestamp.toString(), "tos_acceptance[ip]": ip.toString() }; final response = await CRUD().postStripe( link: url, payload: body, ); final responseData = jsonDecode(response); final accountId = responseData['id']; box.write(BoxName.accountIdStripeConnect, accountId); await updateCaptainAccountBank(); return accountId; } Future updateCaptainAccountBank() async { var res = await CRUD().post(link: AppLink.updateAccountBank, payload: { 'id': box.read(BoxName.driverID), 'accountBank': box.read(BoxName.accountIdStripeConnect), }); if (jsonDecode(res)['status'] == 'success') { mySnackbarSuccess('Account Updated'.tr); // Get.snackbar('Account Updated', ''); } } Future createTransactionToCaptain( String amount, String account) async { String url = 'https://api.stripe.com/v1/transfers'; final body = { 'amount': amount, //amount 'currency': 'usd', 'destination': account //'acct_1OKIjQRgcWrsdyDT' //account id }; final response = await CRUD().postStripe( link: url, payload: body, ); final responseData = jsonDecode(response); final transactionId = responseData['id']; return transactionId; } Future getIpAddress() async { var url = Uri.parse('https://api.ipify.org?format=json'); var response = await http.get(url); if (response.statusCode == 200) { ip = jsonDecode(response.body)['ip']; } else {} } // 'https://accept.paymob.com/unifiedcheckout/?publicKey=egy_pk_live_mbjDC9Ni6FSHKmsz8sOHiVk2xd7oWRve&clientSecret=egy_sk_live_c0904e9cf04506ae64f818d4e075b4a957e3713fdf7a22cb7da30a29e72442b5' Future payWithPayMob( BuildContext context, String amount, currency, Function method) async { String newAmount = (double.parse(amount) * 100).toStringAsFixed(2); try { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { final PaymobResponse? response = await PaymobPayment.instance.pay( context: context, currency: currency, //"EGP", amountInCents: newAmount, // 19.00 EGP billingData: PaymobBillingData(), onPayment: (PaymobResponse response) {}, ); if (response!.responseCode == 'APPROVED') { Get.defaultDialog( barrierDismissible: false, title: 'Payment Successful'.tr, titleStyle: AppStyle.title, content: Text( 'The payment was approved.'.tr, style: AppStyle.title, ), confirm: MyElevatedButton( title: 'OK'.tr, kolor: AppColor.greenColor, onPressed: () async { Get.back(); method(); }, ), ); } else { Get.defaultDialog( barrierDismissible: false, // backgroundColor: AppColor.redColor, title: 'Payment Failed'.tr, content: Text( 'The payment was not approved. Please try again.'.tr, textAlign: TextAlign.center, style: AppStyle.title, ), confirm: MyElevatedButton( title: 'OK'.tr, kolor: AppColor.redColor, onPressed: () async { Get.back(); }, ), ); } } else { Get.snackbar("Authentication Failed", "Please enable Face ID or Fingerprint in your settings."); // Authentication failed, handle accordingly } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); // Authentication failed, handle accordingly } // else { // final PaymobResponse? response = await PaymobPayment.instance.pay( // context: context, // currency: currency, //"EGP", // amountInCents: newAmount, // 19.00 EGP // billingData: PaymobBillingData(), // onPayment: (PaymobResponse response) {}, // ); // if (response!.responseCode == 'APPROVED') { // Get.defaultDialog( // barrierDismissible: false, // title: 'Payment Successful'.tr, // titleStyle: AppStyle.title, // // backgroundColor: AppColor.greenColor, // content: Text( // 'The payment was approved.'.tr, // style: AppStyle.title, // ), // confirm: MyElevatedButton( // kolor: AppColor.greenColor, // title: 'OK'.tr, // onPressed: () async { // Get.back(); // method(); // }, // ), // ); // } else { // Get.defaultDialog( // barrierDismissible: false, // // backgroundColor: AppColor.redColor, // title: 'Payment Failed'.tr, // content: Column( // children: [ // IconButton( // onPressed: () { // Get.find().speakText( // 'The payment was not approved. Please try again.'.tr, // ); // }, // icon: const Icon(Icons.headphones), // ), // Text( // 'The payment was not approved. Please try again.'.tr, // textAlign: TextAlign.center, // style: AppStyle.title, // ), // Text( // '${'The reason is'.tr} ${response.message!.tr}', // textAlign: TextAlign.center, // style: AppStyle.title.copyWith(color: AppColor.redColor), // ), // ], // ), // confirm: MyElevatedButton( // title: 'OK'.tr, // kolor: AppColor.redColor, // onPressed: () async { // Get.back(); // }, // ), // ); // } // } } catch (e) { Get.defaultDialog( title: 'Error'.tr, content: Text( 'An error occurred during the payment process.'.tr, style: AppStyle.title, ), ); rethrow; } } Future payWithPayMobWallet( BuildContext context, String amount, currency, Function method) async { String newAmount = (double.parse(amount) * 100).toStringAsFixed(2); try { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment', options: AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { final PaymobResponseWallet? response = await PaymobPaymentWallet.instance.pay( context: context, currency: currency, //"EGP", amountInCents: newAmount, // 19.00 EGP billingData: PaymobBillingDataWallet(), onPayment: (PaymobResponseWallet response) {}, ); if (response!.success == true && response.message.toString() == 'Approved') { Toast.show(context, 'Payment Successful'.tr, AppColor.greenColor); method(); } else { Get.defaultDialog( barrierDismissible: false, // backgroundColor: AppColor.redColor, title: 'Payment Failed'.tr, content: Column( children: [ IconButton( onPressed: () { Get.find().speakText( 'The payment was not approved. Please try again.'.tr, ); }, icon: const Icon(Icons.headphones), ), Text( 'The payment was not approved. Please try again.'.tr, textAlign: TextAlign.center, style: AppStyle.title, ), Text( '${'The reason is'.tr} ${response.message!.tr}', textAlign: TextAlign.center, style: AppStyle.title.copyWith(color: AppColor.redColor), ), ], ), confirm: MyElevatedButton( title: 'OK'.tr, kolor: AppColor.redColor, onPressed: () async { Get.back(); }, ), ); } } else { // Authentication failed, handle accordingly MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); // final PaymobResponse? response = await PaymobPayment.instance.pay( // context: context, // currency: currency, //"EGP", // amountInCents: newAmount, // 19.00 EGP // billingData: PaymobBillingData(), // onPayment: (PaymobResponse response) {}, // ); // // if (response!.responseCode == 'APPROVED') { // if (response!.responseCode == '200' && response.success == true) { // Toast.show(context, 'Payment Successful'.tr, AppColor.greenColor); // method(); // Get.defaultDialog( // barrierDismissible: false, // title: 'Payment Successful'.tr, // titleStyle: AppStyle.title, // // backgroundColor: AppColor.greenColor, // content: Text( // 'The payment was approved.'.tr, // style: AppStyle.title, // ), // confirm: MyElevatedButton( // kolor: AppColor.greenColor, // title: 'OK'.tr, // onPressed: () async { // Get.back(); // method(); // }, // ), // ); // } else { // Get.defaultDialog( // barrierDismissible: false, // // backgroundColor: AppColor.redColor, // title: 'Payment Failed'.tr, // content: Text( // 'The payment was not approved. Please try again.'.tr, // textAlign: TextAlign.center, // style: AppStyle.title, // ), // confirm: MyElevatedButton( // title: 'OK'.tr, // kolor: AppColor.redColor, // onPressed: () async { // Get.back(); // }, // ), // ); // } } } catch (e) { Get.defaultDialog( title: 'Error'.tr, content: Text( 'An error occurred during the payment process.'.tr, style: AppStyle.title, ), ); rethrow; } } @override void onInit() { timestamp = now.millisecondsSinceEpoch; if (box.read(BoxName.passengerWalletTotal) == null) { box.write(BoxName.passengerWalletTotal, '0'); } // getPassengerWallet(); final localAuth = LocalAuthentication(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/payment/driver_payment_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; class DriverWalletHistoryController extends GetxController { bool isLoading = false; List archive = []; List weeklyList = []; getArchivePayment() async { isLoading = true; update(); var res = await CRUD().getWallet( link: AppLink.getWalletByDriver, payload: {'driverID': box.read(BoxName.driverID)}); if (res == 'failure') { Get.defaultDialog( barrierDismissible: false, title: 'There is no data yet.'.tr, middleText: '', confirm: MyElevatedButton( title: 'Back'.tr, onPressed: () { Get.back(); // Get.back(); }, )); } archive = jsonDecode(res)['message']; isLoading = false; update(); } getWeekllyArchivePayment() async { isLoading = true; update(); var res = await CRUD().getWallet( link: AppLink.getDriverWeekPaymentMove, payload: {'driverID': box.read(BoxName.driverID)}); if (res == 'failure') { Get.defaultDialog( barrierDismissible: false, title: 'There is no data yet.'.tr, middleText: '', confirm: MyElevatedButton( title: 'Back'.tr, onPressed: () { Get.back(); // Get.back(); }, )); } else { weeklyList = jsonDecode(res)['message']; } isLoading = false; update(); } @override void onInit() { // getArchivePayment(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/payment/stripe.dart ================================================== ================================================== FILE PATH: ./lib/controller/payment/smsPaymnet/payment_services.dart ================================================== import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; // تأكد من استيراد الملفات الصحيحة حسب مشروع السائق الخاص بك import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import '../../../constant/box_name.dart'; import '../../../main.dart'; // import '../../../print.dart'; // إذا كنت تستخدمه // --- خدمة الدفع للسائق (نفس المنطق الخاص بالسائق) --- class PaymentService { final String _baseUrl = "${AppLink.paymentServer}/ride/shamcash"; Future createInvoice({required double amount}) async { final url = "$_baseUrl/create_invoice_shamcash.php"; try { final response = await CRUD().postWallet( link: url, payload: { 'driverID': box.read(BoxName.driverID), // استخدام driverID 'amount': amount.toString(), }, ).timeout(const Duration(seconds: 15)); if (response != 'failure') { final data = response; if (data['status'] == 'success' && data['invoice_number'] != null) { return data['invoice_number'].toString(); } } return null; } catch (e) { return null; } } Future checkInvoiceStatus(String invoiceNumber) async { final url = "$_baseUrl/check_status.php"; try { final response = await CRUD().postWallet(link: url, payload: { 'invoice_number': invoiceNumber, }).timeout(const Duration(seconds: 10)); if (response != 'failure') { final data = response; return data['status'] == 'success' && data['invoice_status'] == 'completed'; } return false; } catch (e) { return false; } } } enum PaymentStatus { creatingInvoice, waitingForPayment, paymentSuccess, paymentTimeout, paymentError } class PaymentScreenSmsProvider extends StatefulWidget { final double amount; final String providerName; final String providerLogo; final String qrImagePath; const PaymentScreenSmsProvider({ super.key, required this.amount, this.providerName = 'شام كاش', this.providerLogo = 'assets/images/shamCash.png', this.qrImagePath = 'assets/images/shamcashsend.png', }); @override _PaymentScreenSmsProviderState createState() => _PaymentScreenSmsProviderState(); } class _PaymentScreenSmsProviderState extends State with SingleTickerProviderStateMixin { final PaymentService _paymentService = PaymentService(); Timer? _pollingTimer; PaymentStatus _status = PaymentStatus.creatingInvoice; String? _invoiceNumber; // العنوان الثابت للدفع (كما في تطبيق الراكب) final String _paymentAddress = "80f23afe40499b02f49966c3340ae0fc"; // متغيرات الأنيميشن (الوميض) late AnimationController _blinkController; late Animation _colorAnimation; late Animation _shadowAnimation; @override void initState() { super.initState(); // إعداد الأنيميشن (وميض أحمر) _blinkController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, )..repeat(reverse: true); _colorAnimation = ColorTween( begin: Colors.red.shade700, end: Colors.red.shade100, ).animate(_blinkController); _shadowAnimation = Tween(begin: 2.0, end: 15.0).animate( CurvedAnimation(parent: _blinkController, curve: Curves.easeInOut), ); _createAndPollInvoice(); } @override void dispose() { _pollingTimer?.cancel(); _blinkController.dispose(); super.dispose(); } void _createAndPollInvoice() async { setState(() => _status = PaymentStatus.creatingInvoice); final invoiceNumber = await _paymentService.createInvoice(amount: widget.amount); if (invoiceNumber != null && mounted) { setState(() { _invoiceNumber = invoiceNumber; _status = PaymentStatus.waitingForPayment; }); _startPolling(invoiceNumber); } else if (mounted) { setState(() => _status = PaymentStatus.paymentError); } } void _startPolling(String invoiceNumber) { const timeoutDuration = Duration(minutes: 5); var elapsed = Duration.zero; _pollingTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { elapsed += const Duration(seconds: 5); if (elapsed >= timeoutDuration) { timer.cancel(); if (mounted) setState(() => _status = PaymentStatus.paymentTimeout); return; } final isCompleted = await _paymentService.checkInvoiceStatus(invoiceNumber); if (isCompleted && mounted) { timer.cancel(); setState(() => _status = PaymentStatus.paymentSuccess); } }); } Future _onPopInvoked() async { if (_status == PaymentStatus.waitingForPayment) { return (await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('إلغاء العملية؟', textAlign: TextAlign.right), content: const Text( 'الخروج الآن سيؤدي لإلغاء متابعة عملية الدفع.', textAlign: TextAlign.right), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('البقاء')), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('خروج', style: TextStyle(color: Colors.red))), ], ), )) ?? false; } return true; } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: _onPopInvoked, child: Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( title: Text("دفع عبر ${widget.providerName}"), centerTitle: true, elevation: 0, backgroundColor: Colors.white, foregroundColor: Colors.black, ), body: SafeArea( child: Padding( padding: const EdgeInsets.all(20.0), child: Center(child: _buildContentByStatus()), ), ), ), ); } Widget _buildContentByStatus() { switch (_status) { case PaymentStatus.creatingInvoice: return const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(height: 20), Text("جاري إنشاء رقم البيان...", style: TextStyle(fontSize: 16)), ], ); case PaymentStatus.waitingForPayment: return _buildWaitingForPaymentUI(); case PaymentStatus.paymentSuccess: return _buildSuccessUI(); case PaymentStatus.paymentTimeout: case PaymentStatus.paymentError: return _buildErrorUI(); } } Widget _buildWaitingForPaymentUI() { final currencyFormat = NumberFormat.decimalPattern('ar_SY'); final invoiceText = _invoiceNumber ?? '---'; return SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // 1. المبلغ المطلوب Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue.shade800, Colors.blue.shade600]), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.blue.withOpacity(0.25), blurRadius: 15, offset: const Offset(0, 8)) ], ), child: Column( children: [ const Text("المبلغ المطلوب شحنه", style: TextStyle(color: Colors.white70, fontSize: 14)), const SizedBox(height: 5), Text( "${currencyFormat.format(widget.amount)} ل.س", style: const TextStyle( color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold), ), ], ), ), const SizedBox(height: 25), // 2. رقم البيان (الإطار الأحمر الوامض) AnimatedBuilder( animation: _blinkController, builder: (context, child) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( color: _colorAnimation.value ?? Colors.red, width: 3.0, // إطار سميك ), boxShadow: [ BoxShadow( color: (_colorAnimation.value ?? Colors.red) .withOpacity(0.4), blurRadius: _shadowAnimation.value, spreadRadius: 2, ) ], ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.warning_rounded, color: Colors.red.shade800, size: 28), const SizedBox(width: 8), Text( "هام جداً: لا تنسَ!", style: TextStyle( color: Colors.red.shade900, fontWeight: FontWeight.bold, fontSize: 18), ), ], ), const SizedBox(height: 10), const Text( "يجب نسخ (رقم البيان) هذا ووضعه في تطبيق شام كاش لضمان نجاح العملية.", textAlign: TextAlign.center, style: TextStyle( fontSize: 15, color: Colors.black87, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 15), InkWell( onTap: () { Clipboard.setData(ClipboardData(text: invoiceText)); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text("تم نسخ رقم البيان ✅", textAlign: TextAlign.center), backgroundColor: Colors.red.shade700, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), margin: const EdgeInsets.all(20), ), ); }, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.symmetric( horizontal: 15, vertical: 12), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.red.shade200, width: 1), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text("رقم البيان (Invoice No)", style: TextStyle( fontSize: 12, color: Colors.grey)), Text(invoiceText, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 2.0, color: Colors.red.shade900)), ], ), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.red.shade100, borderRadius: BorderRadius.circular(8), ), child: Icon(Icons.copy_rounded, color: Colors.red.shade900, size: 24), ), ], ), ), ), ], ), ); }, ), const SizedBox(height: 25), // 3. عنوان الدفع (للتسهيل على السائق) Container( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey.shade300), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text("عنوان الدفع (Payment Address)", style: TextStyle(fontSize: 12, color: Colors.grey)), const SizedBox(height: 8), InkWell( onTap: () { Clipboard.setData(ClipboardData(text: _paymentAddress)); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text("تم نسخ عنوان الدفع ✅", textAlign: TextAlign.center), backgroundColor: Colors.green.shade600, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), margin: const EdgeInsets.all(20), ), ); }, child: Row( children: [ Expanded( child: Text( _paymentAddress, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, fontFamily: 'Courier', color: Colors.black87, ), overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 8), const Icon(Icons.copy, size: 18, color: Colors.grey), ], ), ), ], ), ), const SizedBox(height: 30), // 4. الـ QR Code const Text("امسح الرمز للدفع", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87)), const SizedBox(height: 10), GestureDetector( onTap: () { showDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: InteractiveViewer( child: Image.asset(widget.qrImagePath), ), ), ); }, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(color: Colors.grey.shade300), ), child: Image.asset( widget.qrImagePath, width: 150, height: 150, fit: BoxFit.contain, errorBuilder: (c, o, s) => const Icon(Icons.qr_code_2, size: 100, color: Colors.grey), ), ), ), const SizedBox(height: 40), // مؤشر الانتظار const LinearProgressIndicator(backgroundColor: Colors.white), const SizedBox(height: 10), const Text("ننتظر إشعار الدفع تلقائياً...", style: TextStyle(color: Colors.grey, fontSize: 12)), const SizedBox(height: 20), ], ), ); } Widget _buildSuccessUI() { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.verified_rounded, color: Colors.green, size: 100), const SizedBox(height: 20), const Text("تم الدفع بنجاح!", style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), const SizedBox(height: 10), const Text("تم إضافة الرصيد إلى محفظتك", style: TextStyle(color: Colors.grey)), const SizedBox(height: 40), SizedBox( width: double.infinity, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.green, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12))), onPressed: () => Navigator.of(context).pop(), child: const Text("متابعة", style: TextStyle(fontSize: 18)), ), ), ], ); } Widget _buildErrorUI() { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline_rounded, color: Colors.red.shade400, size: 80), const SizedBox(height: 20), Text( _status == PaymentStatus.paymentTimeout ? "انتهى الوقت" : "لم يتم التحقق", style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), const SizedBox(height: 15), const Padding( padding: EdgeInsets.symmetric(horizontal: 30), child: Text( "لم يصلنا إشعار الدفع. هل تأكدت من وضع (رقم البيان) في الملاحظات؟", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey, height: 1.5)), ), const SizedBox(height: 40), SizedBox( width: double.infinity, child: ElevatedButton.icon( style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12))), onPressed: _createAndPollInvoice, icon: const Icon(Icons.refresh), label: const Text("حاول مرة أخرى"), ), ), const SizedBox(height: 15), TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text("إلغاء", style: TextStyle(color: Colors.grey)), ) ], ); } } ================================================== FILE PATH: ./lib/controller/payment/smsPaymnet/pay_out_syria_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; class PayoutService { final String _baseUrl = "https://walletintaleq.intaleq.xyz/v1/main/sms_webhook"; static const double payoutFee = 5000.0; // عمولة السحب الثابتة /// دالة لإنشاء طلب سحب جديد على السيرفر /// /// تعيد رسالة النجاح من السيرفر، أو رسالة خطأ في حال الفشل. Future requestPayout({ required String driverId, walletType, payoutPhoneNumber, required double amount, }) async { final url = ("$_baseUrl/request_payout.php"); try { // هنا يمكنك إضافة هيدرز المصادقة (JWT) بنفس طريقتك المعتادة final response = await CRUD().postWallet(link: url, payload: { 'driverId': driverId, 'amount': amount.toString(), 'phone': payoutPhoneNumber.toString(), 'wallet_type': walletType.toString(), }).timeout(const Duration(seconds: 20)); if (response != 'failure') { final data = (response); if (data['status'] == 'success') { debugPrint("Payout request successful: ${data['message']}"); return data['message']; // إرجاع رسالة النجاح } else { debugPrint("Payout request failed: ${data['message']}"); return "فشل الطلب: ${data['message']}"; // إرجاع رسالة الخطأ من السيرفر } } else { return "خطأ في الاتصال بالسيرفر: ${response.statusCode}"; } } catch (e) { debugPrint("Exception during payout request: $e"); return "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى."; } } } ================================================== FILE PATH: ./lib/controller/payment/paymob/paymob_wallet.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart'; import 'package:sefer_driver/main.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../../print.dart'; class PaymobResponseWallet { final bool success; final String? transactionID; final String? responseCode; final String? message; PaymobResponseWallet({ required this.success, this.transactionID, this.responseCode, this.message, }); factory PaymobResponseWallet.fromJson(Map json) { return PaymobResponseWallet( success: json['success'] == 'true', transactionID: json['id'], responseCode: json['txn_response_code'], message: json['data']['message'], ); } } class PaymobPaymentWallet { static PaymobPaymentWallet instance = PaymobPaymentWallet(); bool _isInitializedWallet = false; final Dio _dio = Dio(); final _baseURL = 'https://accept.paymob.com/api/'; late String _apiKey; late int _integrationID; late int _iFrameID; late String _iFrameURL; late int _userTokenExpiration; /// Initializing PaymobPayment instance. Future initialize({ /// It is a unique identifier for the merchant which used to authenticate your requests calling any of Accept's API. /// from dashboard Select Settings -> Account Info -> API Key required String apiKey, /// from dashboard Select Developers -> Payment Integrations -> Online Card ID required int integrationID, /// from paymob Select Developers -> iframes required int iFrameID, /// The expiration time of this payment token in seconds. (The maximum is 3600 seconds which is an hour) int userTokenExpiration = 300, }) async { if (_isInitializedWallet) { return true; } _dio.options.baseUrl = _baseURL; _dio.options.validateStatus = (status) => true; _apiKey = apiKey; _integrationID = integrationID; _iFrameID = iFrameID; _iFrameURL = 'https://accept.paymobsolutions.com/api/acceptance/iframes/$_iFrameID?payment_token='; _isInitializedWallet = true; _userTokenExpiration = userTokenExpiration; return _isInitializedWallet; } /// Get authentication token, which is valid for one hour from the creation time. Future _getAuthToken() async { try { final response = await _dio.post( 'auth/tokens', data: { 'api_key': _apiKey, }, ); return response.data['token']; } catch (e) { rethrow; } } /// At this step, you will register an order to Accept's database, so that you can pay for it later using a transaction Future _addOrder({ required String authToken, required String currency, required String amount, required List items, }) async { try { final response = await _dio.post( 'ecommerce/orders', data: { "auth_token": authToken, "delivery_needed": "false", "amount_cents": amount, "currency": currency, "items": items, }, ); return response.data['id']; } catch (e) { rethrow; } } /// At this step, you will obtain a payment_key token. This key will be used to authenticate your payment request. It will be also used for verifying your transaction request metadata. Future _getPurchaseToken({ required String authToken, required String currency, required int orderID, required String amount, required PaymobBillingDataWallet billingData, }) async { final response = await _dio.post( 'acceptance/payment_keys', data: { "auth_token": authToken, "amount_cents": amount, "expiration": _userTokenExpiration, "order_id": orderID, "billing_data": billingData, "currency": currency, "integration_id": _integrationID, "lock_order_when_paid": "false" }, ); // final message = response.data['message']; // if (message != null) { // throw Exception(message); // } return response.data['token']; } Future _getWalletUrl({ required String paymentToken, }) async { final Map data = { "source": { "identifier": box.read(BoxName.phoneWallet).toString(), "subtype": "WALLET", }, "payment_token": paymentToken, }; final dio = Dio(); try { final response = await dio.post( 'https://accept.paymobsolutions.com/api/acceptance/payments/pay', data: data, ); // 4. Handle Payment Response if (response.statusCode == 200) { final paymentData = response.data; // Assuming JSON response return paymentData['iframe_redirection_url']; // Navigate to success screen or display success message } else { // Payment failed: Handle errors (e.g., display error message) } } on DioError catch (e) { // Handle network or Dio-related errors } return ''; } /// Proceed to pay with only calling this function. /// Opens a WebView at Paymob redirectedURL to accept user payment info. Future pay( { /// BuildContext for navigation to WebView required BuildContext context, /// Which Currency you would pay in. required String currency, /// Payment amount in cents EX: 20000 is an 200 EGP required String amountInCents, /// Optional Callback if you can use return result of pay function or use this callback void Function(PaymobResponseWallet response)? onPayment, /// list of json objects contains the contents of the purchase. List? items, /// The billing data related to the customer related to this payment. PaymobBillingDataWallet? billingData}) async { if (!_isInitializedWallet) { throw Exception( 'PaymobPayment is not initialized call:`PaymobPayment.instance.initialize`'); } final authToken = await _getAuthToken(); final orderID = await _addOrder( authToken: authToken, currency: currency, amount: amountInCents, items: items ?? [], ); final purchaseToken = await _getPurchaseToken( authToken: authToken, currency: currency, orderID: orderID, amount: amountInCents, billingData: billingData ?? PaymobBillingDataWallet( // email: box.read(BoxName.email) ?? box.read(BoxName.emailDriver), // firstName: box.read(BoxName.name) ?? box.read(BoxName.nameDriver), // lastName: // box.read(BoxName.lastNameDriver) ?? box.read(BoxName.name), // phoneNumber: // box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver), ), ); final urlWallet = await _getWalletUrl(paymentToken: purchaseToken); Log.print('urlWallet: ${urlWallet}'); if (context.mounted) { final response = await PaymobIFrameWallet.show( context: context, redirectURL: urlWallet, onPayment: onPayment, ); return response; } return null; } } class PaymobBillingDataWallet { String? email; String? firstName; String? lastName; String? phoneNumber; String? apartment; String? floor; String? street; String? building; String? postalCode; String? city; String? state; String? country; String? shippingMethod; PaymobBillingDataWallet({ this.email, this.firstName, this.lastName, this.phoneNumber, this.apartment, this.floor, this.street, this.building, this.postalCode, this.city, this.state, this.country, this.shippingMethod, }); Map toJson() { return { "email": (box.read(BoxName.emailDriver)), "first_name": box.read(BoxName.name) ?? box.read(BoxName.nameDriver), "last_name": box.read(BoxName.name) ?? box.read(BoxName.nameDriver), "phone_number": (box.read(BoxName.phoneWallet)), "apartment": apartment ?? "NA", "floor": floor ?? "NA", "building": building ?? "NA", "street": street ?? "NA", "postal_code": postalCode ?? "NA", "city": city ?? "NA", "state": state ?? "NA", "country": country ?? "NA", "shipping_method": shippingMethod ?? "NA", }; } } class PaymobIFrameWallet extends StatefulWidget { const PaymobIFrameWallet({ Key? key, required this.redirectURL, this.onPayment, }) : super(key: key); final String redirectURL; final void Function(PaymobResponseWallet)? onPayment; static Future show({ required BuildContext context, required String redirectURL, void Function(PaymobResponseWallet)? onPayment, }) => Navigator.of(context).push( MaterialPageRoute( builder: (context) { return PaymobIFrameWallet( onPayment: onPayment, redirectURL: redirectURL, ); }, ), ); @override State createState() => _PaymobIFrameState(); } // class _PaymobIFrameState extends State { // WebViewController? controller; // @override // void initState() { // controller = WebViewController() // ..setJavaScriptMode(JavaScriptMode.unrestricted) // ..setNavigationDelegate( // NavigationDelegate( // onNavigationRequest: (NavigationRequest request) { // Log.print('request.url: ${request.url}'); // if (request.url.contains('txn_response_code') && // request.url.contains('success') && // request.url.contains('id')) { // final params = _getParamFromURL(request.url); // final response = PaymobResponseWallet.fromJson(params); // if (widget.onPayment != null) { // widget.onPayment!(response); // } // Navigator.pop(context, response); // return NavigationDecision.prevent; // } // return NavigationDecision.navigate; // }, // ), // ) // ..loadRequest(Uri.parse(widget.redirectURL)); // super.initState(); // } // @override // Widget build(BuildContext context) { // return Scaffold( // body: controller == null // ? const Center( // child: CircularProgressIndicator.adaptive(), // ) // : SafeArea( // child: WebViewWidget( // controller: controller!, // ), // ), // ); // } // Map _getParamFromURL(String url) { // final uri = Uri.parse(url); // final queryParams = uri.queryParameters; // final data = {}; // queryParams.forEach((key, value) { // if (key.contains('.')) { // final parts = key.split('.'); // data.putIfAbsent(parts.first, () => {}); // (data[parts.first] as Map)[parts.last] = value; // } else { // data[key] = value; // } // }); // return data; // } // } class _PaymobIFrameState extends State { WebViewController? controller; @override void initState() { controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate( NavigationDelegate( onNavigationRequest: (NavigationRequest request) { Log.print('request.url: ${request.url}'); if (request.url.contains('txn_response_code') && request.url.contains('success') && request.url.contains('id')) { final params = _getParamFromURL(request.url); final response = PaymobResponseWallet.fromJson(params); if (widget.onPayment != null) { widget.onPayment!(response); } Navigator.pop(context, response); // Show a dialog after successful payment // _showSuccessDialog(response); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ), ) ..loadRequest(Uri.parse(widget.redirectURL)); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: controller == null ? const Center( child: CircularProgressIndicator.adaptive(), ) : SafeArea( child: WebViewWidget( controller: controller!, ), ), ); } Map _getParamFromURL(String url) { final uri = Uri.parse(url); final queryParams = uri.queryParameters; final data = {}; queryParams.forEach((key, value) { if (key.contains('.')) { final parts = key.split('.'); data.putIfAbsent(parts.first, () => {}); (data[parts.first] as Map)[parts.last] = value; } else { data[key] = value; } }); return data; } void _showSuccessDialog(PaymobResponseWallet response) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Payment Successful'), content: Text('Transaction ID: EGP'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); // Close the dialog }, child: Text('OK'), ), ], ); }, ); } } ================================================== FILE PATH: ./lib/controller/payment/paymob/paymob_response.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart'; import 'package:sefer_driver/main.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class PaymobResponse { bool success; String? transactionID; String? responseCode; String? message; PaymobResponse({ this.transactionID, required this.success, this.responseCode, this.message, }); factory PaymobResponse.fromJson(Map json) { return PaymobResponse( success: json['success'] == 'true', transactionID: json['id'], message: json['message'], responseCode: json['txn_response_code'], ); } } class PaymobPayment { static PaymobPayment instance = PaymobPayment(); bool _isInitialized = false; final Dio _dio = Dio(); final _baseURL = 'https://accept.paymob.com/api/'; late String _apiKey; late int _integrationID; late int _iFrameID; late String _iFrameURL; late int _userTokenExpiration; /// Initializing PaymobPayment instance. Future initialize({ /// It is a unique identifier for the merchant which used to authenticate your requests calling any of Accept's API. /// from dashboard Select Settings -> Account Info -> API Key required String apiKey, /// from dashboard Select Developers -> Payment Integrations -> Online Card ID required int integrationID, /// from paymob Select Developers -> iframes required int iFrameID, /// The expiration time of this payment token in seconds. (The maximum is 3600 seconds which is an hour) int userTokenExpiration = 300, }) async { if (_isInitialized) { return true; } _dio.options.baseUrl = _baseURL; _dio.options.validateStatus = (status) => true; _apiKey = apiKey; _integrationID = integrationID; _iFrameID = iFrameID; _iFrameURL = 'https://accept.paymobsolutions.com/api/acceptance/iframes/$_iFrameID?payment_token='; _isInitialized = true; _userTokenExpiration = userTokenExpiration; return _isInitialized; } /// Get authentication token, which is valid for one hour from the creation time. Future _getAuthToken() async { try { final response = await _dio.post( 'auth/tokens', data: { 'api_key': _apiKey, }, ); return response.data['token']; } catch (e) { rethrow; } } /// At this step, you will register an order to Accept's database, so that you can pay for it later using a transaction Future _addOrder({ required String authToken, required String currency, required String amount, required List items, }) async { try { final response = await _dio.post( 'ecommerce/orders', data: { "auth_token": authToken, "delivery_needed": "false", "amount_cents": amount, "currency": currency, "items": items, }, ); return response.data['id']; } catch (e) { rethrow; } } /// At this step, you will obtain a payment_key token. This key will be used to authenticate your payment request. It will be also used for verifying your transaction request metadata. Future _getPurchaseToken({ required String authToken, required String currency, required int orderID, required String amount, required PaymobBillingData billingData, }) async { final response = await _dio.post( 'acceptance/payment_keys', data: { "auth_token": authToken, "amount_cents": amount, "expiration": _userTokenExpiration, "order_id": orderID, "billing_data": billingData, "currency": currency, "integration_id": _integrationID, "lock_order_when_paid": "false" }, ); final message = response.data['message']; if (message != null) { throw Exception(message); } return response.data['token']; } /// Proceed to pay with only calling this function. /// Opens a WebView at Paymob redirectedURL to accept user payment info. Future pay( { /// BuildContext for navigation to WebView required BuildContext context, /// Which Currency you would pay in. required String currency, /// Payment amount in cents EX: 20000 is an 200 EGP required String amountInCents, /// Optional Callback if you can use return result of pay function or use this callback void Function(PaymobResponse response)? onPayment, /// list of json objects contains the contents of the purchase. List? items, /// The billing data related to the customer related to this payment. PaymobBillingData? billingData}) async { if (!_isInitialized) { throw Exception( 'PaymobPayment is not initialized call:`PaymobPayment.instance.initialize`'); } final authToken = await _getAuthToken(); final orderID = await _addOrder( authToken: authToken, currency: currency, amount: amountInCents, items: items ?? [], ); final purchaseToken = await _getPurchaseToken( authToken: authToken, currency: currency, orderID: orderID, amount: amountInCents, billingData: billingData ?? PaymobBillingData(), ); if (context.mounted) { final response = await PaymobIFrame.show( context: context, redirectURL: _iFrameURL + purchaseToken, onPayment: onPayment, ); return response; } return null; } //51624 } class PaymobBillingData { String? email; String? firstName; String? lastName; String? phoneNumber; String? apartment; String? floor; String? street; String? building; String? postalCode; String? city; String? state; String? country; String? shippingMethod; PaymobBillingData({ this.email, this.firstName, this.lastName, this.phoneNumber, this.apartment, this.floor, this.street, this.building, this.postalCode, this.city, this.state, this.country, this.shippingMethod, }); Map toJson() { return { "email": (box.read(BoxName.emailDriver)), "first_name": box.read(BoxName.nameDriver), "last_name": box.read(BoxName.nameDriver), "phone_number": (box.read(BoxName.phoneDriver)), "apartment": apartment ?? "NA", "floor": floor ?? "NA", "building": building ?? "NA", "street": street ?? "NA", "postal_code": postalCode ?? "NA", "city": city ?? "NA", "state": state ?? "NA", "country": country ?? "NA", "shipping_method": shippingMethod ?? "NA", }; } } class PaymobIFrame extends StatefulWidget { const PaymobIFrame({ Key? key, required this.redirectURL, this.onPayment, }) : super(key: key); final String redirectURL; final void Function(PaymobResponse)? onPayment; static Future show({ required BuildContext context, required String redirectURL, void Function(PaymobResponse)? onPayment, }) => Navigator.of(context).push( MaterialPageRoute( builder: (context) { return PaymobIFrame( onPayment: onPayment, redirectURL: redirectURL, ); }, ), ); @override State createState() => _PaymobIFrameState(); } class _PaymobIFrameState extends State { WebViewController? controller; @override void initState() { controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate( NavigationDelegate( onNavigationRequest: (NavigationRequest request) { if (request.url.contains('txn_response_code') && request.url.contains('success') && request.url.contains('id')) { final params = _getParamFromURL(request.url); final response = PaymobResponse.fromJson(params); if (widget.onPayment != null) { widget.onPayment!(response); } Navigator.pop(context, response); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ), ) ..loadRequest(Uri.parse(widget.redirectURL)); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: controller == null ? const Center( child: CircularProgressIndicator.adaptive(), ) : SafeArea( child: WebViewWidget( controller: controller!, ), ), ); } Map _getParamFromURL(String url) { final uri = Uri.parse(url); Map data = {}; uri.queryParameters.forEach((key, value) { data[key] = value; }); return data; } } ================================================== FILE PATH: ./lib/controller/payment/mtn_new/mtn_payment_new_screen.dart ================================================== import 'dart:async'; import 'package:flutter/material.dart'; // import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:sefer_driver/constant/links.dart'; // افترض وجود هذا الملف import 'package:sefer_driver/controller/functions/crud.dart'; // افترض وجود هذا الملف import '../../../main.dart'; // افترض وجود box هنا import '../../../constant/box_name.dart'; // افترض وجود هذا الملف // Service class to handle MTN payment logic class MtnPaymentService { final String _baseUrl = "${AppLink.paymentServer}/ride/mtn_new"; // تأكد من تعديل المسار // Function to create a new invoice Future createInvoice({ required String userId, required String userType, // 'driver' or 'passenger' required double amount, required String mtnPhone, }) async { final url = "$_baseUrl/create_mtn_invoice.php"; try { final response = await CRUD().postWallet( // استخدام نفس دالة CRUD link: url, payload: { 'user_id': userId, 'user_type': userType, 'amount': amount.toString(), 'mtn_phone': mtnPhone, }, ).timeout(const Duration(seconds: 15)); if (response != 'failure') { final data = response; if (data['status'] == 'success' && data['invoice_number'] != null) { debugPrint("MTN Invoice created: ${data['invoice_number']}"); return data['invoice_number'].toString(); } else { debugPrint("Failed to create MTN invoice: ${data['message']}"); return null; } } else { debugPrint("Server error during MTN invoice creation."); return null; } } catch (e) { debugPrint("Exception during MTN invoice creation: $e"); return null; } } // Function to check invoice status (polling) Future checkInvoiceStatus(String invoiceNumber) async { // This should point to a new script on your server that checks mtn_invoices table final url = "$_baseUrl/check_mtn_invoice_status.php"; try { final response = await CRUD().postWallet(link: url, payload: { 'invoice_number': invoiceNumber, }).timeout(const Duration(seconds: 10)); if (response != 'failure') { final data = response; return data['status'] == 'success' && data['invoice_status'] == 'completed'; } return false; } catch (e) { debugPrint("Error checking MTN invoice status: $e"); return false; } } } enum PaymentStatus { creatingInvoice, waitingForPayment, paymentSuccess, paymentTimeout, paymentError } class PaymentScreenMtn extends StatefulWidget { final double amount; // يمكنك إضافة متغير لتحديد هل المستخدم سائق أم راكب final String userType; // 'driver' or 'passenger' const PaymentScreenMtn({ super.key, required this.amount, required this.userType, }); @override _PaymentScreenMtnState createState() => _PaymentScreenMtnState(); } class _PaymentScreenMtnState extends State { final MtnPaymentService _paymentService = MtnPaymentService(); Timer? _pollingTimer; PaymentStatus _status = PaymentStatus.creatingInvoice; String? _invoiceNumber; // جلب البيانات من الـ box final String userId = box.read(BoxName.driverID) ?? box.read(BoxName.passengerID); final String phone = box.read(BoxName.phoneWallet); @override void initState() { super.initState(); _createAndPollInvoice(); } @override void dispose() { _pollingTimer?.cancel(); super.dispose(); } void _createAndPollInvoice() async { setState(() => _status = PaymentStatus.creatingInvoice); final invoiceNumber = await _paymentService.createInvoice( userId: userId, userType: widget.userType, amount: widget.amount, mtnPhone: phone, ); if (invoiceNumber != null && mounted) { setState(() { _invoiceNumber = invoiceNumber; _status = PaymentStatus.waitingForPayment; }); _startPolling(invoiceNumber); } else if (mounted) { setState(() => _status = PaymentStatus.paymentError); } } void _startPolling(String invoiceNumber) { const timeoutDuration = Duration(minutes: 15); // زيادة المهلة var elapsed = Duration.zero; _pollingTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { elapsed += const Duration(seconds: 5); if (elapsed >= timeoutDuration) { timer.cancel(); if (mounted) setState(() => _status = PaymentStatus.paymentTimeout); return; } debugPrint("Polling... Checking MTN invoice: $invoiceNumber"); final isCompleted = await _paymentService.checkInvoiceStatus(invoiceNumber); if (isCompleted && mounted) { timer.cancel(); setState(() => _status = PaymentStatus.paymentSuccess); } }); } @override Widget build(BuildContext context) { return PopScope( canPop: _status != PaymentStatus.waitingForPayment, onPopInvoked: (didPop) async { if (didPop) return; if (_status == PaymentStatus.waitingForPayment) { final shouldPop = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('هل أنت متأكد؟'), content: const Text( 'إذا خرجت الآن، قد تفشل عملية الدفع. عليك إتمامها من تطبيق MTN.'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('البقاء')), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('الخروج')), ], ), ); if (shouldPop ?? false) { Navigator.of(context).pop(); } } }, child: Scaffold( appBar: AppBar(title: const Text("الدفع عبر MTN Cash")), body: Padding( padding: const EdgeInsets.all(16.0), child: Center(child: _buildContentByStatus()), ), ), ); } Widget _buildContentByStatus() { switch (_status) { case PaymentStatus.creatingInvoice: return const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(height: 20), Text("جاري إنشاء فاتورة دفع...", style: TextStyle(fontSize: 16)), ], ); case PaymentStatus.waitingForPayment: return _buildWaitingForPaymentUI(); case PaymentStatus.paymentSuccess: return _buildSuccessUI(); case PaymentStatus.paymentTimeout: case PaymentStatus.paymentError: return _buildErrorUI(); } } Widget _buildWaitingForPaymentUI() { final currencyFormat = NumberFormat.decimalPattern('ar_SY'); return SingleChildScrollView( child: Column( children: [ // **مهم**: استبدل هذا المسار بمسار شعار MTN الصحيح في مشروعك Image.asset('assets/images/cashMTN.png', width: 120), const SizedBox(height: 24), Text("تعليمات الدفع", style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 12), Text( "المبلغ المطلوب: ${currencyFormat.format(widget.amount)} ل.س", style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 16), Card( elevation: 1.5, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: const Padding( padding: EdgeInsets.all(16), child: Column( children: [ _StepTile(number: 1, text: "افتح تطبيق MTN Cash Mobile."), _StepTile( number: 2, text: "اذهب إلى قسم 'دفع الفواتير' أو 'خدمات الدفع'."), _StepTile( number: 3, text: "ابحث عن 'Intaleq App' في قائمة المفوترين."), _StepTile( number: 4, text: "أدخل رقم هاتفك المسجل لدينا للاستعلام عن الفاتورة."), _StepTile( number: 5, text: "ستظهر لك فاتورة بالمبلغ المطلوب. قم بتأكيد الدفع."), ], ), ), ), const SizedBox(height: 24), const LinearProgressIndicator(minHeight: 2), const SizedBox(height: 12), Text("بانتظار تأكيد الدفع من MTN...", style: TextStyle(color: Colors.grey.shade700)), const SizedBox(height: 4), const Text("هذه الشاشة ستتحدث تلقائيًا عند اكتمال الدفع", style: TextStyle(color: Colors.grey), textAlign: TextAlign.center), ], ), ); } Widget _buildSuccessUI() { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.check_circle, color: Colors.green, size: 80), const SizedBox(height: 20), const Text("تم الدفع بنجاح!", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)), const SizedBox(height: 8), const Text("تمت إضافة النقاط إلى حسابك.", style: TextStyle(fontSize: 16)), const SizedBox(height: 20), ElevatedButton( onPressed: () => Navigator.of(context).pop(), child: const Text("العودة إلى المحفظة"), ), ], ); } Widget _buildErrorUI() { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error, color: Colors.red, size: 80), const SizedBox(height: 20), Text( _status == PaymentStatus.paymentTimeout ? "انتهى الوقت المحدد للدفع" : "حدث خطأ أثناء إنشاء الفاتورة", style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), const SizedBox(height: 8), const Text("يرجى المحاولة مرة أخرى.", style: TextStyle(fontSize: 16)), const SizedBox(height: 20), ElevatedButton( onPressed: _createAndPollInvoice, child: const Text("المحاولة مرة أخرى"), ), ], ); } } // ويدجت مساعد لعرض خطوات التعليمات بشكل أنيق class _StepTile extends StatelessWidget { final int number; final String text; const _StepTile({required this.number, required this.text}); @override Widget build(BuildContext context) { return ListTile( contentPadding: const EdgeInsets.symmetric(vertical: 4.0), leading: CircleAvatar( radius: 14, backgroundColor: Theme.of(context).primaryColor, child: Text("$number", style: const TextStyle( fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold)), ), title: Text(text), ); } } ================================================== FILE PATH: ./lib/controller/local/local_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; import '../themes/themes.dart'; class LocaleController extends GetxController { Locale? language; String countryCode = ''; ThemeData appTheme = lightThemeEnglish; void changeLang(String langcode) { Locale locale; switch (langcode) { case "ar": locale = const Locale("ar"); appTheme = lightThemeArabic; box.write(BoxName.lang, 'ar'); break; case "en": locale = const Locale("en"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'en'); break; case "tr": locale = const Locale("tr"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'tr'); break; case "fr": locale = const Locale("fr"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'fr'); break; case "it": locale = const Locale("it"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'it'); break; case "de": locale = const Locale("de"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'de'); break; case "el": locale = const Locale("el"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'el'); break; case "es": locale = const Locale("es"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'es'); break; case "fa": locale = const Locale("fa"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'fa'); break; case "zh": locale = const Locale("zh"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'zh'); break; case "ru": locale = const Locale("ru"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'ru'); break; case "hi": locale = const Locale("hi"); appTheme = lightThemeEnglish; box.write(BoxName.lang, 'hi'); break; case "ar-ma": locale = const Locale("ar-ma"); appTheme = lightThemeArabic; box.write(BoxName.lang, 'ar-ma'); break; case "ar-gulf": locale = const Locale("ar-gulf"); appTheme = lightThemeArabic; box.write(BoxName.lang, 'ar-gulf'); break; default: locale = Locale(Get.deviceLocale!.languageCode); box.write(BoxName.lang, Get.deviceLocale!.languageCode); appTheme = lightThemeEnglish; break; } box.write(BoxName.lang, langcode); Get.changeTheme(appTheme); Get.updateLocale(locale); update(); } @override void onInit() { String? storedLang = box.read(BoxName.lang); if (storedLang == null) { // Use device language if no language is stored storedLang = Get.deviceLocale!.languageCode; box.write(BoxName.lang, storedLang); } changeLang(storedLang); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/local/translations.dart ================================================== import 'package:get/get.dart'; class MyTranslation extends Translations { @override Map> get keys => { "ar": { "Order": "طلب", "OrderVIP": "طلب VIP", "Cancel Trip": "إلغاء الرحلة", "Passenger Cancel Trip": "الراكب ألغى الرحلة", "VIP Order": "طلب VIP", 'Hi ,I Arrive your site': "مرحبًا، لقد وصلت إلى موقعك", "The driver accepted your trip": "السائق قبل رحلتك", "message From passenger": "رسالة من الراكب", "Cancel": "إلغاء", "Trip Cancelled. The cost of the trip will be added to your wallet.": "تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.", "token change": "تغيير الرمز", "face detect": "كشف الوجه", "Face Detection Result": "نتيجة كشف الوجه", "similar": "مشابه", "not similar": "غير مشابه", "Hi ,I will go now": "مرحبًا، سأذهب الآن", "Passenger come to you": "الراكب قادم إليك", "Call Income": "مكالمة واردة", "Call Income from Passenger": "مكالمة واردة من الراكب", "Criminal Document Required": "مطلوب وثيقة جنائية", "You should have upload it .": "يجب عليك تحميلها.", "Call End": "انتهاء المكالمة", "The order has been accepted by another driver.": "تم قبول الطلب من قبل سائق آخر.", "The order Accepted by another Driver": "تم قبول الطلب من قبل سائق آخر", "We regret to inform you that another driver has accepted this order.": "نأسف لإعلامك بأن سائقًا آخر قد قبل هذا الطلب.", "Driver Applied the Ride for You": "السائق قدم الطلب لك", "Applied": "تم التقديم", 'Pay by Sham Cash': 'الدفع عبر شام كاش', 'Pay with Debit Card': 'الدفع ببطاقة الخصم', "Please go to Car Driver": "يرجى الذهاب إلى سائق السيارة", "Ok I will go now.": "حسنًا، سأذهب الآن.", "Accepted Ride": "تم قبول الرحلة", "Driver Accepted the Ride for You": "السائق قبل الرحلة لك", "Promo": "عرض ترويجي", "Show latest promo": "عرض أحدث عرض ترويجي", "Trip Monitoring": "مراقبة الرحلة", "Driver Is Going To Passenger": "السائق في طريقه إليك", "Please stay on the picked point.": "يرجى البقاء في نقطة الالتقاط المحددة.", "message From Driver": "رسالة من السائق", "Trip is Begin": "بدأت الرحلة", 'Rides': 'الرحلات', "Invalid customer MSISDN": "رقم هاتف العميل غير صالح", 'Your Activity': 'نشاطك', "Customer MSISDN doesn’t have customer wallet": "رقم هاتف العميل لا يحتوي على محفظة عميل", 'Please enter the number without the leading 0': 'يرجى إدخال الرقم بدون الصفر الأولي', 'witout zero': 'بدون صفر', 'You Can Cancel the Trip and get Cost From ': 'يمكنك إلغاء الرحلة واسترداد التكلفة من ', 'Please enter a correct phone': 'يرجى إدخال رقم هاتف صحيح', 'Only Syrian phone numbers are allowed': 'يسمح بأرقام الهواتف السورية فقط', 'Go to passenger:': 'اذهب إلى الراكب:', 'Birth year must be 4 digits': 'يجب أن يكون سنة الميلاد مكونة من 4 أرقام', 'Required field': 'حقل مطلوب', 'You are not near': 'أنت لست بالقرب من', 'Please enter your phone number': 'يرجى إدخال رقم هاتفك', 'Enter a valid year': 'أدخل سنة صحيحة', 'Phone number seems too short': 'يبدو أن رقم الهاتف قصير جدًا', 'You have upload Criminal documents': 'لقد قمت بتحميل وثائق جنائية', 'Close': 'إغلاق', "Cancel Trip from driver": "إلغاء الرحلة من السائق", "We will look for a new driver.\nPlease wait.": "هنبحث عن سائق جديد.\nمن فضلك انتظر.", "The driver canceled your ride.": "السائق ألغى رحلتك.", "Driver Finish Trip": "السائق أنهى الرحلة", "you will pay to Driver": "هتدفع للسائق", "Don’t forget your personal belongings.": "متنساش حاجاتك الشخصية.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "من فضلك تأكد إن معاك كل حاجاتك الشخصية وإن أي مبلغ متبقي، لو موجود، تم إضافته لمحفظتك قبل ما تمشي. شكرًا لاستخدامك تطبيق انطلق", "Finish Monitor": "إنهاء المراقبة", "Trip finished": "الرحلة انتهت", "Call Income from Driver": "مكالمة واردة من السائق", "Driver Cancelled Your Trip": "السائق ألغى رحلتك", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "هتدفع للسائق هتدفع تكلفة وقت السائق شوف محفظة Intaleq بتاعتك", "Order Applied": "تم تطبيق الطلب", //firebase above "Driver Portal": "بوابة السائق", "Sign in to start your journey": "سجّل الدخول لبدء رحلتك", "Sign in with a provider for easy access": "سجّل الدخول عبر أحد المزودين للوصول بسهولة", "Sign In with Google": "تسجيل الدخول باستخدام جوجل", "Sign in with Apple": "تسجيل الدخول باستخدام آبل", "Or": "أو", "Create Account with Email": "إنشاء حساب بالبريد الإلكتروني", "Need help? Contact Us": "هل تحتاج للمساعدة؟ تواصل معنا", "Create Driver Account": "إنشاء حساب سائق", "Driver Login": "تسجيل دخول السائق", "Email": "البريد الإلكتروني", "Enter your email": "أدخل بريدك الإلكتروني", "Please enter a valid email": "الرجاء إدخال بريد إلكتروني صالح", "Password": "كلمة المرور", "Enter your password": "أدخل كلمة المرور", "Password must be at least 6 characters": "يجب أن تتكون كلمة المرور من 6 أحرف على الأقل", "Create Account": "إنشاء حساب", 'Pay by MTN Wallet': 'الدفع عبر محفظة MTN', 'Pay by Syriatel Wallet': 'الدفع عبر محفظة سيريتل', "Login": "تسجيل الدخول", "Back to other sign-in options": "العودة إلى خيارات التسجيل الأخرى", "Driver Agreement": "اتفاقية السائق", "To become a driver, you must review and agree to the ": "لتصبح سائقًا، يجب عليك مراجعة والموافقة على ", "Terms of Use": "شروط الاستخدام", " and acknowledge our Privacy Policy.": " والإقرار بسياسة الخصوصية الخاصة بنا.", "I Agree": "أنا أوافق", "Continue": "متابعة", "Customer not found": "العميل غير موجود", "Wallet is blocked": "المحفظة محظورة", "Customer phone is not active": "هاتف العميل غير نشط", "Balance not enough": "الرصيد غير كافٍ", "Balance limit exceeded": "تم تجاوز حد الرصيد", "Privacy Policy": "سياسة الخصوصية", "Location Access Required": "مطلوب الوصول إلى الموقع", "We need access to your location to match you with nearby passengers and provide accurate navigation.": "نحتاج للوصول إلى موقعك لمطابقتك مع الركاب القريبين وتوفير توجيه دقيق.", "Please allow location access \"all the time\" to receive ride requests even when the app is in the background.": "الرجاء السماح بالوصول إلى الموقع \"طوال الوقت\" لاستقبال طلبات الرحلات حتى عندما يكون التطبيق في الخلفية.", "Allow Location Access": "السماح بالوصول إلى الموقع", "Open Settings": "فتح الإعدادات", "payment_success": "تمت العملية بنجاح", "transaction_id": "رقم العملية", "amount_paid": "المبلغ المدفوع", "bonus_added": "البونص المضاف", "points": "نقطة", "transaction_failed": "فشل العملية", "connection_failed": "فشل الاتصال", "server_error": "خطأ في الخادم", "server_error_message": "حدث خطأ أثناء الاتصال بالخادم", "cancel": "إلغاء", "Syria": "‏سوريا", "Security Warning": "تحذير أمني", "Potential security risks detected. The application will close in @seconds seconds.": "تم اكتشاف مخاطر أمنية محتملة. سيتم إغلاق التطبيق خلال @seconds ثانية.", 'please order now': " ‏الرجاء الطلب مرة أخرى", 'Session expired. Please log in again.': 'انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.', "Security Warning": "⚠️ تحذير أمني", "Potential security risks detected. The application may not function correctly.": "تم اكتشاف ثغرات أمنية على هذا الجهاز. للحفاظ على أمان بياناتك، سيتم حذف جميع البيانات وإغلاق التطبيق.", "How to use Intaleq": "كيفية استخدام Intaleq", "What are the order details we provide to you?": "ما هي تفاصيل الطلب التي نوفرها لك؟", 'An OTP has been sent to your number.': 'تم إرسال رمز التحقق إلى رقمك.', "Intaleq Wallet Features:\n\nTransfer money multiple times.\nTransfer to anyone.\nMake purchases.\nCharge your account.\nCharge a friend's Intaleq account.\nStore your money with us and receive it in your bank as a monthly salary.": "ميزات محفظة Intaleq:\n\nتحويل الأموال عدة مرات.\nالتحويل إلى أي شخص.\nإجراء عمليات شراء.\nشحن حسابك.\nشحن حساب Intaleq لصديق.\nقم بتخزين أموالك معنا واستلامها في بنكك كراتب شهري.", "What is the feature of our wallet?": "ما هي مميزات محفظتنا؟", "What is Types of Trips in Intaleq?": "ما هي أنواع الرحلات في Intaleq؟", "No rides available for your vehicle type.": "لا توجد رحلات متاحة .", "Failed to fetch rides. Please try again.": "فشل في جلب الرحلات. يرجى المحاولة مرة أخرى.", '''Types of Trips in Intaleq: Comfort: For cars newer than 2017 with air conditioning. Lady: For girl drivers. Speed: For fixed salary and endpoints. Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements. Raih Gai: For same-day return trips longer than 50km. ''': """أنواع الرحلات في Intaleq: راحة: للسيارات الأحدث من 2017 مع تكييف الهواء. للسائقات الإناث. سبيد: براتب ثابت ونقاط نهاية محددة. مشاوير: للرحلات المرنة حيث يختار الركاب السيارة والسائق باتفاق مسبق. رحّي غاي: للرحلات ذات العودة في نفس اليوم التي تزيد عن 50 كم. """, "I will go now": "هروح دلوقتي", "Yes": "نعم", 'Privacy Policy': "سياسة الخصوصية", 'Ride info': "معلومات الرحلة", 'you dont have accepted ride': "ليس لديك رحلة مقبولة", 'Total Points': "إجمالي النقاط", "No,I want": "لا، أنا عاوز", "Your fee is": "المبلغ بتاعك هو", "Do you want to pay Tips for this Driver": "عاوز تدفع إكرامية للسائق ده؟", "Tip is": "الإكرامية هي", "No i want": "لا، أنا عاوز", "Call Passenger": "اتصل بالراكب", "Send Message": "إرسال رسالة", "Open in Maps": "فتح في الخرائط", "Duration": "المدة", "Distance": "المسافة", "Passenger": "الراكب", "Cost": "التكلفة", // "Order": "طلب", "Car Type": "نوع السيارة", "Start the Ride": "ابدأ الرحلة", // "Accepted Ride": "تم قبول الرحلة", "Is the Passenger in your Car?": "هل الراكب في سيارتك؟", "Don't start trip if passenger not in your car": "لا تبدأ الرحلة إذا لم يكن الراكب في سيارتك", "your ride is Accepted": "تم قبول رحلتك", // "Driver Accepted the Ride for You": "السائق قبل الرحلة لك", "I Arrive": "لقد وصلت", // "Trip is Begin": "بدأت الرحلة", "You are not near the passenger location": "أنت لست بالقرب من موقع الراكب", // "Driver Finish Trip": "السائق أنهى الرحلة", "Please go to the pickup location exactly": "يرجى الذهاب إلى موقع الالتقاط بالضبط", "You Can Cancel the Trip and get Cost From": "يمكنك إلغاء الرحلة واسترداد التكلفة من", "Are you sure to cancel?": "هل أنت متأكد من الإلغاء؟", // "Driver Cancelled Your Trip": "السائق ألغى رحلتك", "You will need to pay the cost to the driver, or it will be deducted from your next trip": "سيتم دفع التكلفة للسائق أو خصمها من رحلتك القادمة", "Select a quick message": "اختر رسالة سريعة", "Where are you, sir?": "أين أنت يا سيدي؟", "I've been trying to reach you but your phone is off.": "كنت أحاول الوصول إليك لكن هاتفك مغلق.", "Please don't be late, I'm waiting for you at the specified location.": "يرجى عدم التأخير، أنا في انتظارك في الموقع المحدد.", "Please don't be late": "يرجى عدم التأخير", "Type something": "اكتب شيئًا", "Passenger Information": "معلومات الراكب", "Name": "الاسم", "wallet_updated": "تم تحديث المحفظة", "wallet_credited_message": "تم إضافة", "default_tone": "النغمة الافتراضية", "No orders available": "لا توجد طلبات متوفرة", "Phone": "رقم الهاتف", "A promotion record for this driver already exists for today.": "يوجد بالفعل سجل ترويج لهذا السائق لهذا اليوم.", "Gender": "الجنس", "time Selected": "الوقت المختار", "Ride Status": "حالة الرحلة", "If you need any help or have questions, this is the right place to do that. You are welcome!": "إذا كنت بحاجة إلى أي مساعدة أو لديك أي أسئلة، فهذا هو المكان المناسب لذلك. أهلاً وسهلاً بك!", "ID Mismatch": "عدم تطابق الرقم التعريفي", // "face detect": "كشف الوجه", "Would you like to proceed with health insurance?": "هل ترغب في الاستمرار مع التأمين الصحي؟", "Confirmation": "تأكيد", "Enter Health Insurance Provider": "أدخل مزود التأمين الصحي", // "Yes": "نعم", "No": "لا", "You need to complete 500 trips": "يجب عليك إكمال 500 رحلة", "Please enter a valid insurance provider": "الرجاء إدخال مزود تأمين صالح", "Opted out": "اختيار عدم الاستمرار", "You have chosen not to proceed with health insurance.": "لقد اخترت عدم الاستمرار مع التأمين الصحي.", "Do you have a disease for a long time?": "هل لديك مرض منذ فترة طويلة؟", "When you complete 500 trips, you will be eligible for exclusive health insurance offers.": "عند إكمال 500 رحلة، ستكون مؤهلاً للحصول على عروض حصرية للتأمين الصحي.", "We have partnered with health insurance providers to offer you special health coverage. Complete 500 trips and receive a 20% discount on health insurance premiums.": "لقد عقدنا شراكة مع مزودي التأمين الصحي لتقديم تغطية صحية خاصة لك. أكمل 500 رحلة واحصل على خصم 20% على أقساط التأمين الصحي.", "Show health insurance providers near me": "اعرض مزودي التأمين الصحي القريبين مني", "Health Insurance": "التأمين الصحي", "An error occurred while saving driver data": "حدث خطأ أثناء حفظ بيانات السائق", // "Face Detection Result": "نتيجة كشف الوجه", "false": "خطأ", "true": "صحيح", "Failed to save driver data": "فشل حفظ بيانات السائق", // "similar": "مشابه", // "not similar": "غير مشابه", "error": "خطأ", "error_processing_document": "خطأ في معالجة المستند", "expected": "متوقع", "detected": "تم الكشف عنه", "car_license_front": "الجانب الأمامي لرخصة السيارة", "car_license_back": "الجانب الخلفي لرخصة السيارة", "id_card_front": "الجانب الأمامي لبطاقة الهوية", "id_card_back": "الجانب الخلفي لبطاقة الهوية", "driver_license": "رخصة القيادة", "unknown_document": "وثيقة غير معروفة", "incorrect_document_title": "وثيقة غير صحيحة", "incorrect_document_message": "الرجاء تحميل {expected} الصحيحة. تم الكشف عن {detected}.", "minute": "دقيقة", "kilometer": "كم", "You have successfully charged your account": "تم شحن حسابك بنجاح", "has been added to your budget": "تمت إضافته إلى ميزانيتك", "id_front": "هوية_أمامية", "id_back": "هوية_خلفية", "car_back": "سيارة_خلفية", "car_front": "سيارة_أمامية", "ID Documents Front": "الوثيقه الشخصية - الأمامية", "Vehicle Details Front": "تفاصيل المركبة - الأمامية", "Vehicle Details Back": "تفاصيل المركبة - الخلفية", "Criminal Record": "السجل الجنائي", "ID Documents Back": "الوثيقه الشخصية - الخلفية", "Driver's License": "رخصة القيادة", "No, still Waiting.": "لا، ما زلت في انتظار.", "you can show video how to setup": "يمكنك عرض فيديو حول كيفية الإعداد", "don't start trip if not": "لا تبدأ الرحلة إذا لم", "you are not moved yet !": "أنت لم تتحرك بعد!", "Update Available": "تحديث متوفر", "A new version of the app is available. Please update to the latest version.": "تتوفر نسخة جديدة من التطبيق. يرجى التحديث إلى أحدث إصدار.", "We use location to get accurate and nearest passengers for you": "نستخدم الموقع للحصول على أقرب الركاب وأكثرهم دقة لك", "This ride is already applied by another driver.": "هذه الرحلة قام بقبولها سائق آخر بالفعل.", "My location is correct. You can search for me using the navigation app": "موقعي صحيح. يمكنك البحث عني باستخدام تطبيق الملاحة", "Hello, I'm at the agreed-upon location": "مرحباً، أنا في المكان المتفق عليه", // "message From Driver": "رسالة من السائق", "How much longer will you be?": "‏قدامك قد إيه", "Phone number is verified before": "تم التحقق من رقم الهاتف مسبقاً", "Change Ride": "تغيير الرحلة", "Authentication failed": "فشل المصادقة", "Biometric Authentication": "المصادقة البيومترية", "You should use Touch ID or Face ID to confirm payment": "يجب عليك استخدام Touch ID أو Face ID لتأكيد الدفع", "Cost Of Trip IS": "تكلفة الرحلة هي", "You must be recharge your Account": "رصيد حسابك غير كافٍ. يرجى إعادة الشحن للمتابعة", "Ahli United Bank": "البنك الأهلي المتحد", "Citi Bank N.A. Egypt": "سيتي بنك مصر", "MIDBANK": "بنك ميد", "Banque Du Caire": "بنك القاهرة", "HSBC Bank Egypt S.A.E": "اتش اس بي سي", "Credit Agricole Egypt S.A.E": "كريدي أجريكول مصر", "Egyptian Gulf Bank": "البنك المصري الخليجي", "The United Bank": "البنك المتحد", "Qatar National Bank Alahli": "البنك الأهلي القطري", "Arab Bank PLC": "البنك العربي", "Emirates National Bank of Dubai": "بنك الإمارات دبي الوطني", "Al Ahli Bank of Kuwait – Egypt": "البنك الأهلي الكويتي - مصر", "National Bank of Kuwait – Egypt": "البنك الوطني الكويتي - مصر", "Arab Banking Corporation - Egypt S.A.E": "الشركة العربية المصرفية - مصر", "First Abu Dhabi Bank": "بنك أبوظبي الأول", "Abu Dhabi Islamic Bank – Egypt": "مصرف أبوظبي الإسلامي - مصر", "Commercial International Bank - Egypt S.A.E": "البنك التجاري الدولي - مصر", "Housing And Development Bank": "بنك الإسكان والتعمير", "Banque Misr": "بنك مصر", "Arab African International Bank": "البنك العربي الأفريقي الدولي", "Egyptian Arab Land Bank": "البنك المصري العربي", "Export Development Bank of Egypt": "بنك التنمية والتصدير المصري", "Faisal Islamic Bank of Egypt": "البنك الإسلامي المصري", "Blom Bank": "بلوم بنك", "Abu Dhabi Commercial Bank – Egypt": "بنك أبوظبي التجاري - مصر", "Alex Bank Egypt": "بنك الإسكندرية", "Societe Arabe Internationale De Banque": "البنك العربي الدولي", "National Bank of Egypt": "البنك الأهلي المصري", "Al Baraka Bank Egypt B.S.C.": "بنك البركة مصر", "Egypt Post": "البريد المصري", "Nasser Social Bank": "بنك ناصر الاجتماعي", "Industrial Development Bank": "بنك التنمية الصناعية والعمال", "Suez Canal Bank": "بنك قناة السويس", "Mashreq Bank": "بنك المشرق", "Arab Investment Bank": "البنك العربي للاستثمار", "General Authority For Supply Commodities": "الهيئة العامة للسلع التموينية", "Arab International Bank": "البنك العربي الدولي", "Agricultural Bank of Egypt": "البنك الزراعي المصري", "National Bank of Greece": "البنك الوطني اليوناني", "Central Bank Of Egypt": "البنك المركزي المصري", "ATTIJARIWAFA BANK Egypt": "البنك التجاري وفا مصر", "Morning Promo": "بونص الصباح", "Show my Cars": "عرض سياراتي", 'Behavior Score': "درجة السلوك", 'Fixed Price': 'سعر ثابت', "Driver Behavior": "سلوك السائق", "Last 10 Trips": "آخر 10 رحلات", "Trip ID": "رقم الرحلة", 'Vehicle Details': "تفاصيل المركبة", 'Hard Brake': "فرملة قوية", 'Show behavior page': "عرض صفحة السلوك", 'Coming Soon': "قريبًا", 'Logout': "تسجيل الخروج", 'Contact Support to Recharge': "تواصل مع الدعم لإعادة الشحن", 'Are you sure you want to logout?': "هل أنت متأكد أنك تريد تسجيل الخروج؟", "How to use App": "كيفية استخدام التطبيق", 'This service will be available soon.': "هذه الخدمة ستكون متاحة قريبًا.", 'Change the app language': "تغيير لغة التطبيق", 'Get features for your country': "احصل على ميزات لبلدك", 'Vibration feedback for buttons': "ردود فعل الاهتزاز للأزرار", 'Run Google Maps directly': "تشغيل خرائط جوجل مباشرة", 'reviews': "المراجعات", "Trip Summary with": "ملخص الرحلة مع", "Original Fare": "الأجرة الأصلية", "Your Earnings": "أرباحك", "Exclusive offers and discounts always with the Sefer app": "عروض وخصومات حصرية دائماً مع تطبيق سفر", "Would the passenger like to settle the remaining fare using their wallet?": "هل يرغب الراكب بتسوية الأجرة المتبقية من محفظته؟", "Yes, Pay": "نعم، ادفع", "How much Passenger pay?": "كم دفع الراكب؟", "Passenger paid amount": "المبلغ الذي دفعه الراكب", "Add to Passenger Wallet": "أضف إلى محفظة الراكب", "How was the passenger?": "كيف كان الراكب؟", "Add a comment (optional)": "أضف تعليقاً (اختياري)", "Type something...": "اكتب شيئاً...", "Submit rating": "إرسال التقييم", 'Is device compatible': "هل الجهاز متوافق", 'Exclusive offers and discounts always with the Intaleq app': "عروض وخصومات حصرية دائماً مع تطبيق انطلق", "Driver Registration": "تسجيل السائق", "Driver": "السائق", "Vehicle": "المركبة", "Docs": "الوثائق", "Driver's Personal Information": "المعلومات الشخصية للسائق", "First Name": "الاسم الأول", "Last Name": "اسم العائلة", 'You have gift 30000 SYP': 'لديك هدية 30000 ليرة سورية', "National ID Number": "الرقم الوطني", "License Expiry Date": "تاريخ انتهاء الرخصة", "YYYY-MM-DD": "YYYY-MM-DD", "Please select a date": "يرجى اختيار تاريخ", "Vehicle Information": "معلومات المركبة", "Car Plate Number": "رقم اللوحة", "Car Make (e.g., Toyota)": "نوع السيارة (مثال تويوتا)", "Car Model (e.g., Corolla)": "طراز السيارة (مثال كورولا)", "Year of Manufacture": "سنة الصنع", "Car Color": "لون السيارة", "Upload Documents": "رفع المستندات", "Driver License (Front)": "رخصة السائق (أمام)", "Driver License (Back)": "رخصة السائق (خلف)", "Car Registration (Front)": "ترخيص السيارة (أمام)", "Car Registration (Back)": "ترخيص السيارة (خلف)", "Tap to upload": "اضغط للرفع", "<< BACK": "« السابق", "NEXT >>": "التالي »", "SUBMIT": "إرسال", "Required field": "حقل مطلوب", "Expired License": "الرخصة منتهية", "Your driver’s license has expired.": "انتهت صلاحية رخصة قيادتك.", "Missing Documents": "مستندات ناقصة", "Please upload all 4 required documents.": "يرجى رفع المستندات الأربعة جميعها.", "Success": "تم بنجاح", "Registration completed successfully!": "تم التسجيل بنجاح!", "Error": "خطأ", "Car Color (Name)": "لون السيارة (الاسم)", "Car Color (Hex)": "لون السيارة (كود HEX)", "Required field": "حقل مطلوب", "color.white": "أبيض", "color.black": "أسود", "color.silver": "فضي", "color.gray": "رمادي", "color.gunmetal": "رصاصي غامق", "color.red": "أحمر", "color.blue": "أزرق", "color.navy": "كحلي", "color.green": "أخضر", "color.darkGreen": "أخضر داكن", "color.beige": "بيج", "color.brown": "بني", "color.maroon": "خمري", 'Ride History': "تاريخ الرحلات", "color.burgundy": "برغندي", 'Name must be at least 2 characters': "الاسم يجب أن يكون على الأقل 2 حرف", 'This Trip Was Cancelled': "تم إلغاء هذه الرحلة", 'Trip Details': "تفاصيل الرحلة", 'Could not load trip details.': "تعذر تحميل تفاصيل الرحلة.", 'Trip Info': "معلومات الرحلة", 'Order ID': "رقم الطلب", 'Date': "التاريخ", 'Earnings & Distance': "الأرباح والمسافة", 'Trip Timeline': "جدول الرحلة", 'Time to Passenger': "الوقت للراكب", 'Trip Started': "بدأت الرحلة", 'Trip Finished': "انتهت الرحلة", 'Passenger & Status': "الراكب والحالة", 'Status': "الحالة", 'Passenger Name': "اسم الراكب", 'National ID must be 11 digits': "الرقم الوطني يجب أن يكون 11 رقمًا", "color.yellow": "أصفر", "color.orange": "برتقالي", "color.gold": "ذهبي", "color.bronze": "برونزي", "Verify OTP": "التحقق من الرمز", "Verification Code": "رمز التحقق", "We have sent a verification code to your mobile number:": "لقد أرسلنا رمز التحقق إلى رقم هاتفك المحمول:", "Verify": "تحقق", "Resend Code": "إعادة إرسال الرمز", "You can resend in": "يمكنك إعادة الإرسال خلال", "seconds": "ثوانٍ", "color.champagne": "شامبانيا", "Device Change Detected": "تم اكتشاف تغيير في الجهاز", "Please verify your identity": "يرجى التحقق من هويتك", "color.purple": "بنفسجي", "Registration failed. Please try again.": "فشل التسجيل، حاول مجدداً.", "An unexpected error occurred:": "حدث خطأ غير متوقع:", 'Your email not updated yet': "بريدك الإلكتروني لم يتم تحديثه بعد", 'Enter your email' '''Types of Trips in Intaleq: - Comfort: For cars newer than 2017 with air conditioning. - Lady: For girl drivers. - Speed: For fixed salary and endpoints. - Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements. - Raih Gai: For same-day return trips longer than 50km.''': '''أنواع الرحلات في Intaleq: - راحة: للسيارات الأحدث من 2017 مع تكييف الهواء. - للسائقات الإناث. - سبيد: براتب ثابت ونقاط نهاية محددة. - مشاوير: للرحلات المرنة حيث يختار الركاب السيارة والسائق باتفاق مسبق. - رحّي غاي: للرحلات ذات العودة في نفس اليوم التي تزيد عن 50 كم.''', '''Intaleq Wallet Features: - Transfer money multiple times. - Transfer to anyone. - Make purchases. - Charge your account. - Charge a friend's Intaleq account. - Store your money with us and receive it in your bank as a monthly salary.''': '''ميزات محفظة Intaleq: - تحويل الأموال عدة مرات. - التحويل إلى أي شخص. - إجراء عمليات شراء. - شحن حسابك. - شحن حساب Intaleq لصديق. - قم بتخزين أموالك معنا واستلامها في بنكك كراتب شهري.''', 'Are you sure you want to logout?': "هل أنت متأكد أنك تريد تسجيل الخروج؟", 'My Cars': "سياراتي", 'Bank Account': "الحساب البنكي", 'Behavior Page': "صفحة السلوك", 'Personal Information': "المعلومات الشخصية", "Add criminal page": "إضافة صفحة جنائية", "Overall Behavior Score": "درجة السلوك العامة", "Add new car": "إضافة سيارة جديدة", "You have gift 300 L.E": "لديك هدية بقيمة 300 جنيه.", // "VIP Order": "طلب VIP", "VIP Order Accepted": "تم قبول طلب VIP.", "Incorrect sms code": "⚠️ رمز التحقق الذي أدخلته غير صحيح. يرجى المحاولة مرة أخرى.", // "The driver accepted your trip": "السائق قبل رحلتك.", "this is count of your all trips in the morning promo today from 7:00am-10:00am": "هذا عدد جميع رحلاتك في بونص الصباح اليوم من الساعة 7:00 صباحًا حتى 10:00 صباحًا", "Morning Promo Rides": "رحلات عرض الصباح", "Are you sure to make this car as default": "هل أنت متأكد من تعيين هذه السيارة كافتراضية؟", "Sign In by Google": "تسجيل الدخول باستخدام جوجل", "Not updated": "لم يتم التحديث", "Updated": "تم التحديث", "Remaining time": "الوقت المتبقي", "Add bank Account": "إضافة حساب بنكي", "Are you sure to exit ride?": "هل أنت متأكد من إنهاء الرحلة؟", "Today": "اليوم", "seconds": "ثواني", "You will cancel registration": "ستقوم بإلغاء التسجيل", "Create new Account": "إنشاء حساب جديد", "You haven't moved sufficiently!": "أنت لم تتحرك بما فيه الكفاية!", "This for new registration": "للتسجيل الجديد", "You have received a gift token!": "لقد حصلت على رمز هدية!", "Afternoon Promo": "بونص الظهر", "for ": "ل ", "You dont have invitation code": "ليس لديك رمز دعوة.", "this is count of your all trips in the Afternoon promo today from 3:00pm-6:00 pm": "هذا عدد جميع رحلاتك في بونص بعد الظهر اليوم من الساعة 3:00 مساءً حتى 6:00 مساءً", "Afternoon Promo Rides": "رحلات بونص بعد الظهر", "Heading your way now. Please be ready.": "في طريقي إليك الآن. يرجى الاستعداد.", "Alert": "تنبيه", "Insert Wallet phone number": "أدخل رقم هاتف المحفظة", "You have successfully opted for health insurance.": "لقد اخترت التأمين الصحي بنجاح.", "Please enter a health insurance status.": "يرجى إدخال حالة التأمين الصحي", "Intaleq Driver": "انطلق السائق", "The 300 points equal 300 L.E for you \nSo go and gain your money": "300 نقطة تساوي 300 جنيه لك \nلذا اذهب واحصل على أموالك", "Info": "معلومات", "You dont have money in your Wallet": "ليس لديك أموال في محفظتك", "You dont have money in your Wallet or you should less transfer 5 LE to activate": "ليس لديك أموال في محفظتك أو يجب عليك تحويل 5 جنيهات على الأقل لتفعيل الحساب", "Rejected Orders Count": "عدد الطلبات المرفوضة", "This is the total number of rejected orders per day after accepting the orders": "هذا هو العدد الإجمالي للطلبات المرفوضة يوميًا بعد قبول الطلبات", "Invite": "دعوة", "Drivers": "السائقين", "Passengers": "الركاب", "Your Driver Referral Code": "رمز الإحالة الخاص بالسائق", "DRIVER123": "سائق123", "Share this code with other drivers. Both of you will receive rewards!": "شارك هذا الرمز مع السائقين الآخرين. سيحصل كل منكما على مكافآت!", "Share Code": "مشاركة الرمز", "Invite another driver and both get a gift after he completes 100 trips!": "ادع سائقًا آخر وسيحصل كلاكما على هدية بعد أن يكمل 100 رحلة!", "Enter phone": "أدخل رقم الهاتف", "Send Invite": "إرسال دعوة", "Show Invitations": "عرض الدعوات", "We need access to your location to match you with nearby passengers and ensure accurate navigation.": "نحتاج إلى الوصول إلى موقعك لمطابقتك مع الركاب القريبين وضمان التنقل الدقيق.", "Please allow location access at all times to receive ride requests and ensure smooth service.": "يرجى السماح بالوصول إلى الموقع في جميع الأوقات لتلقي طلبات الرحلات وضمان خدمة سلسة.", "No invitation found yet!": "لم يتم العثور على دعوات حتى الآن!", "Trip": "رحلة", "Your Passenger Referral Code": "رمز الإحالة الخاص بالراكب", "Intaleq123": "انطلق123", "Share this code with passengers and earn rewards when they use it!": "شارك هذا الرمز مع الركاب واكسب مكافآت عند استخدامه!", "Your Rewards": "مكافآتك", "Total Invites": "إجمالي الدعوات", "Active Users": "المستخدمون النشطون", "Total Earnings": "إجمالي الأرباح", "Choose from contact": "اختر من جهات الاتصال", // "Cancel": "إلغاء", "Open App": "افتح التطبيق", // "Ok I will go now.": "حسنًا، سأذهب الآن.", "Hi, I will go now": "مرحبًا، سأذهب الآن.", // "Add new car": "أضف سيارة جديدة", "Rate Our App": "قيّم تطبيقنا", "How would you rate our app?": "كيف تقيم تطبيقنا؟", "write comment here": "اكتب تعليقك هنا", "Submit Rating": "إرسال التقييم", "Rating submitted successfully": "تم إرسال التقييم بنجاح", "Open the app to stay updated and ready for upcoming tasks.": "افتح التطبيق لتبقى على اطلاع واستعداد للمهام القادمة.", "No invitation found": "لم يتم العثور على دعوة", "Please upload this license.": "يرجى تحميل هذه الرخصة.", "If your car license has the new design, upload the front side with two images.": "إذا كانت رخصة سيارتك ذات التصميم الجديد، يرجى تحميل الوجه الأمامي بصورتين.", "If you need assistance, contact us": "إذا كنت بحاجة إلى المساعدة، تواصل معنا", "Please make sure to read the license carefully.": "يرجى التأكد من قراءة الرخصة بعناية", "Videos Tutorials": "فيديوهات تعليمية", "Approaching your area. Should be there in 3 minutes.": "اقترب من منطقتك. يجب أن أكون هناك خلال 3 دقائق.", "There's heavy traffic here. Can you suggest an alternate pickup point?": "هناك حركة مرور كثيفة هنا. هل يمكنك اقتراح نقطة استلام بديلة؟", "This ride is already taken by another driver.": "تم حجز هذه الرحلة من قبل سائق آخر.", "Type Any thing": "اكتب أي شيء", "Price: ": "السعر ", "Add Question": "أضف سؤالاً", "Please enter a valid card 16-digit number.": "الرجاء إدخال رقم بطاقة صحيح مكون من 16 رقمًا.", "Insert card number": "أدخل رقم البطاقة", "Bank account added successfully": "تمت إضافة الحساب البنكي بنجاح", "Updated successfully": "تم التحديث بنجاح", "Create Wallet to receive your money": "أنشئ محفظة لاستقبال أموالك", "Insert Account Bank": "أدخل رقم حسابك البنكي", "Insert Card Bank Details to Receive Your Visa Money Weekly": "أدخل تفاصيل بطاقتك البنكية لاستقبال راتبك عبر فيزا كل أسبوع", "Select Name of Your Bank": "اختر اسم بنكك", "You don't have enough money in your Intaleq wallet": "لا يوجد رصيد كافٍ في محفظة Intaleq الخاصة بك ", "You have transferred to your wallet from": "لقد حولت إلى محفظتك من", "Transfer": "تحويل", "amount": "المبلغ", "This driver is not registered": "هذا السائق غير مسجل", "insert amount": "أدخل المبلغ", "phone number of driver": "رقم هاتف السائق", "Transfer budget": "نقل الميزانية", "Comfort": "كمفورت", "Speed": "سعر ثابت", 'Insert Emergency Number': 'أدخل رقم الطوارئ', 'Emergency Number': 'رقم الطوارئ', 'Save': 'حفظ', 'Stay': 'ابقى', 'Exit': 'خروج', 'Waiting': 'انتظار', 'Your data will be erased after 2 weeks\nAnd you will can\'t return to use app after 1 month ': ',سيتم مسح بياناتك بعد أسبوعين\nولن تتمكن من العودة لاستخدام التطبيق بعد شهر واحد ', "You are in an active ride. Leaving this screen might stop tracking. Are you sure you want to exit?": "أنت في رحلة نشطة. قد يؤدي مغادرة هذه الشاشة إلى إيقاف التتبع. هل أنت متأكد أنك تريد الخروج؟", "Lady": "ليدي", "Permission denied": "تم رفض الإذن", "Contact permission is required to pick a contact": "مطلوب إذن الوصول إلى جهات الاتصال لاختيار جهة اتصال", "No contact selected": "لم يتم تحديد جهة اتصال", "Please select a contact": "يرجى تحديد جهة اتصال", "No phone number": "لا يوجد رقم هاتف", "The selected contact does not have a phone number": "جهة الاتصال المحددة لا تحتوي على رقم هاتف", "Error": "خطأ", "An error occurred while picking a contact": "حدث خطأ أثناء اختيار جهة اتصال", "Are you sure you want to cancel this trip?": "هل أنت متأكد من أنك تريد إلغاء هذه الرحلة؟", // "Cancel Trip from driver": "إلغاء الرحلة من السائق", "Why do you want to cancel this trip?": "لماذا تريد إلغاء هذه الرحلة؟", "Write the reason for canceling the trip": "اكتب سبب الإلغاء:", "Trip Cancelled from driver. We are looking for a new driver. Please wait.": "تم إلغاء الرحلة من قبل السائق. نحن نبحث عن سائق جديد. من فضلك انتظر.", "Delivery": "توصيل", "Mashwari": "‏مشواري", "Total Net": "صافي الإجمالي", "Special Order": "طلب خاص", "Intaleq Order": "طلب سريع", "No data yet!": "لا توجد بيانات حتى الآن!", "You Refused 3 Rides this Day that is the reason \nSee you Tomorrow!": "لقد رفضت 3 رحلات اليوم وهذا هو السبب \nأراك غدًا!", "fromBudget": "من الميزانية", "You must restart the app to change the language.": "يجب إعادة تشغيل التطبيق لتغيير اللغة", "hours before trying again.": "ساعة قبل المحاولة مرة أخرى", "Transaction failed": "فشل المعاملة", "Wallet Type": "نوع المحفظة", "Enter your wallet number": "أدخل رقم محفظتك", "The Amount is less than": "المبلغ أقل من", "Cash Out": "صرف", "Do you want to collect your earnings?": "هل تريد استلام أموالك؟", "Total wallet is ": "إجمالي المحفظة هو ", "Remainder": "‏الباقي", "Call Page": "صفحة المكالمة", // "Call End": "إنهاء المكالمة", "Call Left": "مكالمات متبقية", "Rayeh Gai": "رايح جاي ", "cost is ": " التكلفة هي ", "Total budgets on month": "إجمالي الميزانيات لهذا الشهر", "Counts of budgets on days": "عدد الميزانيات حسب الأيام", "Wallet Added": "تم إضافة المحفظة", "The price must be over than ": "يجب أن يكون السعر أكثر من ", "Total Cost": "إجمالي التكلفة", "This Trip Cancelled": "تم إلغاء هذه الرحلة", "Total price from ": "إجمالي السعر من ", "Wallet Add": "إضافة إلى المحفظة", "Press here": "اضغط هنا", "Would the passenger like to settle the remaining fare using their wallet?": "هل يرغب الراكب بسداد باقي الأجرة باستخدام محفظته؟", "How much Passenger pay?": "كم يدفع الراكب؟", "passenger amount to me": "مبلغ الراكب لي", "Please wait": "الرجاء الانتظار", "minutes before trying again.": " دقيقة قبل المحاولة مرة أخرى.", "Total rides on month": "إجمالي الرحلات في الشهر", "Counts of rides on days": "عدد الرحلات حسب الأيام", "You should restart app to change language": "يجب إعادة تشغيل التطبيق لتغيير اللغة", "No data yet": "لا توجد بيانات حتى الآن", "Question": "استفسار", "Enter your Question here": "اسأل هنا", "History Page": "سجل الرحلات ", "Finished": "مكتملة", "Trip Detail": "تفاصيل الرحلة", "you must insert token code ": "يجب إدخال رمز التحقق", "Invite code already used": "تم استخدام رمز الدعوة بالفعل", "Price is": "السعر", "Times of Trip": "أوقات الرحلة", "Time to Passenger is": "الوقت للوصول للراكب", "TimeStart is": "وقت البداية", "Time Finish is": "وقت الانتهاء", "Status is": "الحالة", "Total Orders": "إجمالي الطلبات", "Completed": "مكتملة", "Canceled Orders": "الطلبات الملغاة", "Rejected Orders": "الطلبات المرفوضة", "Percent Rejected": "نسبة المرفوضة", "Percent Canceled": "نسبة الملغاة", "Percent Completed": "نسبة المكتملة", "Statistic": "إحصائية", "Value": "القيمة", "You Have in": "لديك في", "Total Budget is ": "رصيد ‏التشغيل هو", "Ride Today : ": "‏رحلات اليوم ", "You Earn today is ": "ما كسبته اليوم هو", "registration_date": "تاريخ_التسجيل", "Total Budget from trips by\nCredit card is ": "إجمالي الميزانية من الرحلات عن طريق\nبطاقة الائتمان هي ", "This amount for all trip I get from Passengers and Collected For me in": "هذا المبلغ لجميع الرحلات التي أحصل عليها من الركاب والمجموعة لي في", "Total Budget from trips is ": "إجمالي الميزانية من الرحلات هو ", "You can purchase a budget to enable online access through the options listed below.": "يمكنك ‏إضافة رصيد من هذه القائمة", "You can buy points from your budget": "يمكنك سداد المديونية من حسابك", "expiration_date": "تاريخ الانتهاء", "rating_count": "عدد التقييمات", "rating_driver": "تقييم السائق", "age": "سن/عمر", "vin": "رقم تعريف المركبة", "car_color": "اللون", "car_plate": "لوحة السيارة", "car_model": "طراز السيارة:", "education": "التعليم", "gender": "الجنس", "birthdate": "تاريخ ميلاد", "Approve Driver Documents": "الموافقة على مستندات الشريك السائق", "Total Budget is": "الميزانية الإجمالية", "You will receive code in sms message": "ستتلقى الرمز في رسالة نصية قصيرة", "Please enter": "الرجاء إدخال", "We need your phone number to contact you and to help you receive orders.": "نحتاج إلى رقم هاتفك للاتصال بك ولمساعدتك في تلقي الطلبات.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "لا يتطابق الاسم الكامل في سجلك الجنائي مع الاسم الموجود في رخصة القيادة. يرجى التحقق وتقديم المستندات الصحيحة.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "الرقم الوطني الموجود في رخصة القيادة الخاصة بك لا يتطابق مع الرقم الموجود في مستند هويتك. يرجى التحقق وتقديم المستندات الصحيحة.", "Capture an Image of Your Criminal Record": "التقط صورة لسجلك الجنائي", "IssueDate": "تاريخ الإصدار", "Capture an Image of Your car license front": "التقط صورة لرخصة سيارتك من الأمام", "Capture an Image of Your ID Document front": "التقاط صورة لوثيقة هويتك من الأمام", "NationalID": "الرقم الوطني", "reject your order.": "رفض طلبك.", "Order Under Review": "الطلب قيد المراجعة", "is reviewing your order. They may need more information or a higher price.": "يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.", "FullName": "الاسم الكامل", "If you want order to another person": "إذا كنت تريد الطلب لشخص آخر", // "We will look for a new driver.\nPlease wait.": // "سنبحث عن سائق جديد.\nمن فضلك انتظر.", "No, I want to cancel this trip": "لا، أريد إلغاء هذه الرحلة", "Attention": "تنبيه", // "Trip Cancelled. The cost of the trip will be added to your wallet.": // "تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.", "Trip Cancelled. The cost of the trip will be deducted from your wallet.": "تم إلغاء الرحلة. سيتم خصم تكلفة الرحلة من محفظتك.", "You will be charged for the cost of the driver coming to your location.": "سيتم خصم تكلفة قدوم السائق إلى موقعك.", "Location Tracking Active": "تعقب الموقع نشط", "Your location is being tracked in the background.": "يتم تتبع موقعك في الخلفية.", "Maintenance Center": "‏مركز الصيانة", "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car.": "عندما تكمل 600 رحلة، ستكون مؤهلاً للحصول على عروض لصيانة سيارتك.", // "The driver canceled your ride.": "ألغى السائق رحلتك.", "We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers.": "لم نجد أي سائقين بعد. ضع في اعتبارك زيادة رسوم رحلتك لجعل عرضك أكثر جاذبية للسائقين.", "Allow Location Access": "السماح بالوصول إلى الموقع", "Show My Trip Count": "عرض عدد رحلاتي", "Intaleq is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.": "انطلق هو التطبيق الأكثر أمانًا لمشاركة الركوب الذي يقدم العديد من الميزات لكل من السائقين والركاب. نحن نقدم أقل عمولة بنسبة 8% فقط، مما يضمن حصولك على أفضل قيمة لرحلاتك. يتضمن تطبيقنا التأمين لأفضل السائقين، الصيانة المنتظمة للسيارات مع أفضل المهندسين، والخدمات على الطريق لضمان تجربة محترمة وعالية الجودة لجميع المستخدمين.", "You can contact us during working hours from 10:00 - 17:00.": "يمكنك الاتصال بنا خلال ساعات العمل من 10:00 - 17:00.", "Show maintenance center near my location": "أظهر مركز الصيانة بالقرب من موقعي", "How do I request a ride?": "كيف أطلب رحلة؟", "Step-by-step instructions on how to request a ride through the Intaleq app.": "تعليمات خطوة بخطوة حول كيفية طلب رحلة من خلال تطبيق Intaleq.", "What types of vehicles are available?": "ما هي أنواع المركبات المتاحة؟", "Intaleq offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.": "توفر Intaleq مجموعة متنوعة من خيارات المركبات لتناسب احتياجاتك، بما في ذلك الاقتصادية والمريحة والفخمة. اختر الخيار الذي يناسب ميزانيتك وعدد الركاب.", "How can I pay for my ride?": "كيف يمكنني الدفع لرحلتي؟", "Intaleq offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.": "توفر Intaleq طرق دفع متعددة لراحتك. اختر بين الدفع نقدًا أو بطاقة ائتمان/خصم أثناء تأكيد الرحلة.", "Can I cancel my ride?": "هل يمكنني إلغاء رحلتي؟", "Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Intaleq cancellation policy for details.": "نعم، يمكنك إلغاء رحلتك في ظل ظروف معينة (مثل قبل تعيين السائق). اطلع على سياسة الإلغاء في Intaleq للحصول على التفاصيل.", "Driver Registration & Requirements": "تسجيل السائقين والمتطلبات", "How can I register as a driver?": "كيف يمكنني التسجيل كسائق؟", "What are the requirements to become a driver?": "ما هي المتطلبات للعمل كسائق؟", "Types of Trips in Intaleq:": "أنواع الرحلات في انطلق:", "Comfort: For cars newer than 2017 with air conditioning.": "كمفورت: للسيارات الأحدث من 2017 والمكيفة.", "Lady: For girl drivers.": "ليدي: للسائقات النساء.", "Intaleq: For fixed salary and endpoints.": "انطلق: للرحلات ذات الرواتب الثابتة والنقاط النهائية المحددة.", "Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.": "مشواري: للرحلات المرنة حيث يختار الركاب السيارة والسائق مسبقًا.", "Raih Gai: For same-day return trips longer than 50km.": "رايح جاي: للرحلات ذهاب وعودة في نفس اليوم لمسافات تزيد عن 50 كم.", "What is Types of Trips in Intaleq?": "أنواع الرحلات في انطلق", "Intaleq Wallet Features:": "مميزات محفظة انطلق:", "Transfer money multiple times.": "تحويل الأموال عدة مرات.", "Transfer to anyone.": "تحويل لأي شخص.", "Make purchases.": "الشراء.", "Charge your account.": "شحن حسابك.", "Charge a friend's Intaleq account.": "شحن حساب صديقك في انطلق.", "Store your money with us and receive it in your bank as a monthly salary.": "الاحتفاظ بأموالك معنا واستلامها في حسابك البنكي كراتب شهري.", "No Rides Available": "لا توجد رحلات متاحة حالياً", "What are the order details we provide to you?": "ما هي تفاصيل الطلب التي نقدمها لك؟", "What is the feature of our wallet?": "ما هي ميزة محفظتنا؟", "How to use Intaleq": "كيف تستخدم Intaleq", "Visit our website or contact Intaleq support for information on driver registration and requirements.": "تفضل بزيارة موقعنا الإلكتروني أو اتصل بدعم Intaleq للحصول على معلومات حول تسجيل السائقين والمتطلبات.", "How do I communicate with the other party (passenger/driver)?": "كيف أتواصل مع الطرف الآخر (الراكب/السائق)؟", "Intaleq provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.": "توفر Intaleq ميزة الدردشة داخل التطبيق لتتيح لك التواصل مع سائقك أو راكبك أثناء الرحلة.", "What safety measures does Intaleq offer?": "ما هي تدابير السلامة التي تقدمها Intaleq؟", "Intaleq prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.": "تُولي Intaleq أهمية كبيرة لسلامتك. نحن نقدم ميزات مثل التحقق من هوية السائق ، وتتبع الرحلات داخل التطبيق ، وخيارات الاتصال في حالات الطوارئ.", "Frequently Questions": "الأسئلة الشائعة", "Contact Us": "اتصل بنا", "Choose a contact option": "اختر خيار الاتصال", "You can change the vibration feedback for all buttons": "يمكنك تغيير اهتزاز الرج لجميع الأزرار", "About Us": "نبذة عنا", "Work time is from 10:00 - 17:00.\nYou can send a WhatsApp message or email.": "ساعات العمل من 10:00 - 17:00.\nيمكنك إرسال رسالة عبر واتساب أو بريد إلكتروني.", "Most Secure Methods": "أساليب الأمان الأكثر فاعلية", "In-App VOIP Calls": "مكالمات VOIP داخل التطبيق", "Recorded Trips for Safety": "تسجيل الرحلات من أجل السلامة", "\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.": "\nكما أننا نضع توفير التكاليف في أولوية اهتماماتنا، ونقدم أسعاراً منافسة لجعل رحلاتك في متناول اليد.", "Intaleq is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:": "Intaleq: تطبيق مشاركة الرحلات يضع سلامتك وادخارك في المقدمة Intaleq هو تطبيق مشاركة رحلات مصمم مع وضع سلامتك وتوفيرك في الاعتبار. نربطك بسائقين موثوقين في منطقتك، ونضمن لك تجربة انطلق مريحة وخالية من الضغوط.فيما يلي بعض الميزات الرئيسية التي تميزنا:", "Send WhatsApp Message": "إرسال رسالة واتساب", "Send Email": "إرسال بريد إلكتروني", "You should complete 600 trips": "يجب عليك إكمال 600 رحلة", "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Intaleq app and be part of our Intaleq family.": "لدينا عروض صيانة لسيارتك. يمكنك استخدامها بعد إكمال 600 رحلة للحصول على خصم 20% على إصلاحات السيارة. استمتع باستخدام تطبيق Intaleq وكن جزءًا من عائلتنا.", "Enable Location Permission": "تمكين إذن الموقع", "Allowing location access will help us display orders near you. Please enable it now.": "سيساعدنا السماح بالوصول إلى الموقع في عرض الطلبات القريبة منك. يرجى تمكينه الآن.", "Allow overlay permission": "السماح بإذن‏الظهور فوق التطبيقات", "To display orders instantly, please grant permission to draw over other apps.": "لعرض الطلبات على الفور، يرجى منح إذن لرسم فوق التطبيقات الأخرى.", "InspectionResult": "نتيجة الفحص", // "Criminal Record": "صحيفة الحالة الجنائية", "The email or phone number is already registered.": "البريد الإلكتروني أو رقم الهاتف مسجل بالفعل.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "لتصبح شريكاً سائقاً لمشاركة الرحلات في تطبيق انطلق، يجب عليك تحميل رخصة القيادة ووثيقة الهوية ووثيقة تسجيل السيارة. سيقوم نظام الذكاء الاصطناعي لدينا بمراجعة مصداقيتها والتحقق منها على الفور في غضون 2-3 دقائق فقط. إذا تمت الموافقة على مستنداتك، يمكنك بدء العمل كشريك سائق في تطبيق انطلق. يرجى ملاحظة أن تقديم المستندات المزورة يعد جريمة خطيرة وقد يؤدي إلى الإنهاء الفوري والعواقب القانونية.", "Documents check": "التحقق من المستندات", // "Driver's License": "رخصة القيادة", "License Type": "نوع الترخيص", "National Number": "الرقم القومي:", "Name (Arabic)": "الاسم (عربي)", "Name (English)": "الإنجليزية", "Address": "العنوان", "Issue Date": "تاريخ الإصدار", "Expiry Date": "تاريخ انهاء الصلاحية", "License Categories": "فئات الترخيص", // "driver_license": "رخصة القيادة", "Capture an Image of Your Driver License": "التقط صورة لرخصة القيادة الخاصة بك", // "ID Documents Back": "ظهر وثائق الهوية", "National ID": "الهوية الوطنية", "Occupation": "المهنة", "Your driver’s license and/or car tax has expired. Please renew them before proceeding.": "لقد انتهت صلاحية رخصة القيادة و/أو ضريبة السيارة الخاصة بك. يرجى تجديدها قبل المتابعة.", "Your driver’s license has expired. Please renew it before proceeding.": "لقد انتهت صلاحية رخصة القيادة الخاصة بك. يرجى تجديدها قبل المتابعة.", // "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": // "الرقم الوطني على رخصة القيادة الخاصة بك لا يتطابق مع الرقم الموجود على مستند هويتك. يرجى التحقق وتقديم المستندات الصحيحة.", "Religion": "الدين", "You have 500": "لديك 500", "You have got a gift for invitation": "لقد حصلت على هدية للدعوة", "You have got a gift": "لقد حصلت على هدية", "Share the app with another new driver": "شارك التطبيق مع سائق جديد آخر", "for your first registration!": "للتسجيل الأول!", "Get it Now!": "احصل عليه الآن!", "before": "قبل", "Intaleq": "انطلق", "Code not approved": "الرمز غير موافق عليه", "300 LE": "300 جنيه مصري", "Do you have an invitation code from another driver?": "هل لديك كود دعوة من سائق آخر؟", "Paste the code here": "الصق الكود هنا", "No, I don't have a code": "لا، لا أملك كودا", "Code approved": "تمت الموافقة على الكود", "Install our app:": "قم بتثبيت تطبيقنا:", // "Invite another driver and both get a gift after he completes 100 trips!": // "ادع صديقًا ليكون سائقًا واحصلا على هدية بعد إكماله 100 مشوار!", "Share App": "شارك التطبيق", "You deserve the gift": "أنت تستحق الهدية", "complete, you can claim your gift": " يمكنك المطالبة بهديتك", "When": "‏عندما يكمل", "Enter driver's phone": "أدخل رقم هاتف السائق", // "Send Invite": "أرسل الدعوة", // "Show Invitations": "عرض الدعوات", "The period of this code is 1 hour": "فترة صلاحية هذا الكود هي ساعة واحدة", "Intaleq DRIVER CODE": "كود سائق انطلق", "Use this code in registration": "استخدم هذا الكود عند التسجيل", "To get a gift for both": "للحصول على هدية لكليكما", "Invite a Driver": "ادع سائقًا", "As a new driver, you're eligible for a special offer!": "بصفتك سائقًا جديدًا، فأنت مؤهل للحصول على عرض خاص!", "Welcome Offer!": "عرض ترحيبي!", "Please enter a phone number": "من فضلك أدخل رقم هاتف", "Invite sent successfully": "تم إرسال الدعوة بنجاح", "Failed to send invite": "فشل إرسال الدعوة", "An error occurred": "حدث خطأ", "Air Condition Trip": "رحلة تكييف ", "Passenger name: ": "اسم الراكب: ", // "Criminal Document Required": "الفيش الجنائي مطلوب", "Criminal Document": "الفيش الجنائي", "Marital Status": "الحالة الاجتماعية", "Full Name (Marital)": "الاسم الكامل (الزوجي)", "Payment Method": "طريقة الدفع", "Expiration Date": "تاريخ الانتهاء", "Capture an Image of Your ID Document Back": "التقاط صورة للجهة الخلفية من وثيقة الهوية الخاصة بك", // "ID Documents Front": "الوجه الأمامي لوثائق الهوية", "First Name": "الاسم الأول", "Press to hear": "اضغط للاستماع", "CardID": "التقاط صورة للجهة الخلفية من وثيقة الهوية الخاصة بك", "Full Name": "الاسم الكامل", // "Vehicle Details Front": "تفاصيل المركبة الأمامية", "Plate Number": "رقم اللوحة", "Owner Name": "اسم المالك", // "Vehicle Details Back": "تفاصيل المركبة الخلفية", "Make": "‏نوع السيارة", "Model": "طراز السيارة:", "Year": "السنة", "Chassis": "الشاسيه", "Color": "اللون", "Displacement": "سعه المحرك", "Fuel": "الوقود", "Tax Expiry Date": "تاريخ انهاء الصلاحية", "Inspection Date": "تاريخ الفحص", "Capture an Image of Your car license back": "التقاط صورة لرخصة سيارتك مرة أخرى", "Capture an Image of Your Driver’s License": "التقط صورة لرخصة القيادة الخاصة بك", "Sign in with Google for easier email and name entry": "سجّل الدخول باستخدام جوجل لتسهيل إدخال البريد الإلكتروني والاسم", "You will choose allow all the time to be ready receive orders": "ستختار السماح طوال الوقت بتلقي الطلبات الجاهزة", "Welcome to Intaleq!": "مرحبًا بك في انطلق!", "Get to your destination quickly and easily.": "الوصول إلى وجهتك بسرعة وسهولة.", "Enjoy a safe and comfortable ride.": "استمتع بمشوار آمن ومريح.", "Choose Language": "اختر لغة", "Login": "تسجيل الدخول", "Pay with Wallet": "الدفع باستخدام المحفظة", "Invalid MPIN": "رمز MPIN غير صالح", "Invalid OTP": "رمز التحقق غير صالح", "Enter your email address": "أدخل عنوان بريدك الإلكتروني", "Please enter Your Email.": "يُرجى إدخال...", "Enter your phone number": "أدخل رقم هاتفك", "Please enter your phone number.": "الرجاء إدخال رقم هاتفك.", "Please enter Your Password.": "إدخال كلمة المرور الخاصة بك", "Submit": "إرسال", "if you dont have account": "إذا لم يكن لديك حساب", "Register": "سجل", "Accept Ride's Terms & Review Privacy Notice": "اقبل شروط الرحلة وراجع إشعار الخصوصية", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "من خلال تحديد \"أوافق\" أدناه، فقد راجعت شروط الاستخدام وأوافق عليها وأقر بإشعار الخصوصية.عمري 18 سنة على الأقل.", "I Agree": "أوافق", "First name": "الاسم الأول", "Enter your first name": "أدخل اسمك الأول", "Please enter your first name.": "‏‏الرجاء إدخال اسمك.", "Last name": "اسم العائلة", "Enter your last name": "أدخل اسم العائلة", "Please enter your last name.": "‏‏الرجاء إدخال اسمك.", "City": "المدينة", "Please enter your City.": "يُرجى إدخال...", "Male": "ذكر", "Female": "أنثى", "Verify Email": "التحقق من صحة البريد الإلكتروني", "We sent 5 digit to your Email provided": "أرسلنا 5 أرقام إلى بريدك الإلكتروني المقدم", "5 digit": "PIN(5-أرقام)", "Send Verification Code": "رمز التحقق", "Your Ride Duration is": "مدة مشوارك هي", "You will be thier in": "سوف تكون لهم في", "You trip distance is": "مسافة مشوارك هي", "Fee is": "الرسوم هي", "To :": "إلى:", "Add Promo": "إضافة عرض ترويجي", "Confirm Selection": "تأكيد التحديد", "distance is": "المسافة هي", "duration is": "المدة هي", "I don't need a ride anymore": "لا أحتاج إلى مشوار بعد الآن", "I was just trying the application": "كنت أجرب التطبيق فقط", "No driver accepted my request": "لم يقبل أي شريك سائق طلبي", "I added the wrong pick-up/drop-off location": "أضفت موقع الالتقاء/النزول غير الصحيح", "I don't have a reason": "ليس لدي سبب", "Other": "أخرى", "Can we know why you want to cancel Ride ?": "هل يمكننا معرفة سبب رغبتك في إلغاء الرحلة ؟", "Cancel Ride": "إلغاء!", "Add Payment Method": "أضف طريقة دفع", "Your Wallet balance is": "رصيد محفظتك هو", "Ride Wallet": "محفظة الرحلات", // "Payment Method": "طريقة الدفع", "Type here Place": "اكتب هنا المكان", "Are You sure to ride to": "هل أنت متأكد من إجراء مشوار إلى", "Confirm": "تأكيد", "Back": "عودة", "You are Delete": "أنت تحذف", "Deleted": "محذوف", "You Dont Have Any places yet !": "ليس لديك أي أماكن حتى الآن !", "Favorite Places": "الأماكن المفضلة", "From : Current Location": "الموقع الحالي:", "Where to": "أين؟", "Notifications": "الإشعارات", "Profile": "الملف الشخصي", "go to your passenger location before\nPassenger cancel trip": "اذهب إلى موقع الراكب قبل أن يلغي الراكب الرحلة", "Home": "الصفحة الرئيسية", "My Cared": "ماي كيرت", "Add Card": "أضف بطاقة", "Add Credit Card": "أضف بطاقة ائتمان", "Please enter the cardholder name": "يرجى إدخال اسم حامل البطاقة", "Please enter the expiry date": "يرجى إدخال تاريخ انتهاء الصلاحية", "Please enter the CVV code": "يرجى إدخال رمز التحقق من البطاقة", "Go To Favorite Places": "الانتقال إلى الأماكن المفضلة", "Go to this Target": "انتقل إلى هذا الهدف", "My Profile": "‏ملفي", "Sign Out": "تسجيل الخروج", "Home Page": "الصفحة الرئيسية", "Are you want to go to this site": "هل تريد الذهاب إلى هذا الموقع", "MyLocation": "موقعي", "my location": "موقعي", "Target": "الهدف", "Update": "تحديث", "Are you sure to exit ride ?": "هل أنت متأكد من الإنهاء", "You Should choose rate figure": "يجب عليك اختيار الرقم الصحيح", "Login Captin": "كابتن تسجيل الدخول", "Register Captin": "تسجيل الكابتن", "Send Verfication Code": "إرسال رمز التحقق", "End Ride": "‏إنهاء الرحلة", "Minute": "الدقيقة", "Go to passenger Location": "انتقل إلى موقع الراكب ", "Duration of the Ride is": "مدة المشوار هي", "Distance of the Ride is": "مسافة المشوار هي", "Name of the Passenger is": "اسم الراكب هو", "Hello this is Captain": "مرحبًا، أنا الكابتن", // "Start the Ride": "ابدأ المشوار", "Please Wait If passenger want To Cancel!": "يرجى الانتظار إذا أراد الراكب الإلغاء!", "Total Duration:": "المدة الإجمالية:", "Active Duration:": "‏مدة النشاط الحالي", "Waiting for Captin ...": "في انتظار الكابتن ...", "Age is": "العمر هو", "Rating is": "التقييم هو", "to arrive you.": "للوصول إليك.", "Order History": "سجل تاريخ الأمر", "My Wallet": "محفظتي", "Tariff": "التعريفة", "Settings": "الإعدادات", "Feed Back": "ردود الفعل", "Promos": "العروض الترويجية", "Please enter a valid 16-digit card number": "الرجاء إدخال رقم أمر شراء صالح.", "Add Phone": "الهاتف", // "Please enter a phone number": "الرجاء إدخال رقم الهاتف", "You dont Add Emergency Phone Yet!": "لم تقم بإضافة هاتف الطوارئ بعد!", "You will arrive to your destination after": "ستصل إلى وجهتك بعد", "You can cancel Ride now": "يمكنك إلغاء المشوار الآن", "You Can cancel Ride After Captain did not come in the time": "يمكنك إلغاء المشوار بعد عدم وصول الكابتن في الوقت المناسب", "If you in Car Now. Press Start The Ride": "إذا كنت في السيارة الآن. اضغط على بدء المشوار", "You Dont Have Any amount in": "ليس لديك أي مبلغ في", "Wallet!": "محفظة!", "You Have": "لديك", "Save Credit Card": "احتفظ ببطاقة الائتمان", "Show Promos": "عرض العروض", "10 and get 4% discount": "١٠ واحصل على خصم ٤٪", "20 and get 6% discount": "٢٠ واحصل على خصم ٦٪", "40 and get 8% discount": "40 واحصل على خصم 8%", "100 and get 11% discount": "١٠٠ واحصل على خصم ١١٪", "Pay with Your PayPal": "ادفع باستخدام PayPal", "You will choose one of above !": "سوف تختار واحدة من الخيارات أعلاه!", // "Cancel": "إلغاء", "Delete My Account": "حذف حسابي", "Edit Profile": "تعديل الملف الشخصي", // "Name": "الاسم", "Update Gender": "تحديث الجنس", "Education": "التعليم", "Update Education": "تحديث التعليم", "Employment Type": "نوع الوظيفة", "SOS Phone": "SOS الهاتف", "High School Diploma": "شهادة الثانوية العامة", "Associate Degree": "درجة الدبلوم المشترك", "Bachelor's Degree": "درجة البكالوريوس", "Master's Degree": "درجة الماجستير", "Doctoral Degree": "درجة الدكتوراه", 'Orders Page': 'صفحة الطلبات', 'ShamCash Account': 'حساب شام كاش', 'Trip Completed': 'اكتملت الرحلة', 'Finish & Submit': 'إنهاء وتقديم', 'Collect Cash': 'جمع النقود', "Pay remaining to Wallet?": "هل تدفع الباقي إلى المحفظة؟", "Enter Amount Paid": "أدخل المبلغ المدفوع", "Confirm Payment": "تأكيد الدفع", "Take Photo Now": "التقط صورة الآن", "Later": "لاحقًا", "Profile Photo Required": "صورة الملف الشخصي مطلوبة", "Please upload a clear photo of your face to be identified by passengers.": "يرجى تحميل صورة واضحة لوجهك ليتم التعرف عليك من قبل الركاب.", 'Any comments about the passenger?': 'هل لديك أي تعليقات حول الراكب؟', "Promos For today": "العروض الترويجية لليوم", "Copy this Promo to use it in your Ride!": "انسخ هذا العرض الترويجي لاستخدامه في رحلتك!", "To change some Settings": "لتغيير بعض الإعدادات", "To change Language the App": "لتغيير لغة التطبيق", "Order Request Page": "صفحة طلب الطلبية", "Routs of Trip": "طرق الرحلة", "Passenger Name is": "اسم المسافر", "Total From Passenger is": "إجمالي من الراكب هو", "Duration To Passenger is": "المدة إلى الراكب", "Distance To Passenger is": "مسافة إلى الراكب تكون", "Total For You is": "المجموع بالنسبة لك هو", "Distance is": "المسافة", "KM": "كيلومتر", "Duration of Trip is": "مدة الرحلة هي", "Minutes": "دقائق", "Apply Order": "تطبيق الطلب", "Refuse Order": "رفض الطلب", "Rate Captain": "تقييم الكابتن", "Enter your Note": "أدخل ملاحظتك", "Type something...": "اكتب شيئًا...", "Submit rating": "تقديم التقييم", "Rate Passenger": "تقييم الراكب", "Ride Summary": "ملخص الرحلة", "welcome_message": "رسالة الترحيب", "app_description": "وصف_التطبيق", "get_to_destination": "الوصول إلى الوجهة", "get_a_ride": "احصل على رحلة", "safe_and_comfortable": "آمن ومريح", "committed_to_safety": "ملتزم بالسلامة", // "Driver Applied the Ride for You": "سائق قدم الرحلة من أجلك", // "Show latest promo": "أظهر أحدث عرض ترويجي", // "Cancel Trip": "إلغاء الرحلة", // "Passenger Cancel Trip": "الرحلة ألغيت من قبل المسافر", // "Please stay on the picked point.": "يرجى البقاء على النقطة المحددة.", // "Hi ,I will go now": "مرحبًا، سأذهب الآن", // "Passenger come to you": "الراكب يأتي إليك", // "Hi ,I Arrive your site": "مرحبًا، لقد وصلت إلى موقعك.", // "you will pay to Driver": "سوف تدفع للسائق", "Driver Cancel Your Trip": "ألغِ رحلتك، سائق.", // "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": // "سوف تدفع للسائق ستدفع تكلفة وقت السائق انظر إلى محفظتك Intaleq", // "I will go now": "سأذهب الآن", "You Have Tips": "لديك نصائح", "tips": "نصائح", "Total is": "المجموع هو", // "No,I want": "لا ، أريد", // "Your fee is": "رسومك هي", // "Do you want to pay Tips for this Driver": // "هل ترغب في دفع البقشيش لهذا السائق؟", // "Tip is": "‏إكرامي", "Camera Access Denied.": "تم رفض الوصول إلى الكاميرا.", "Open Settings": "افتح الإعدادات", "GPS Required Allow !.": "GPS مطلوب تمكينه!", "Your Account is Deleted": "تم حذف حسابك", "Are you sure to delete your account?": "هل أنت متأكد من رغبتك في حذف حسابك؟", "Your data will be erased after 2 weeks": "سيتم محو بياناتك بعد مرور أسبوعين", "And you will can't return to use app after 1 month": "وستتمكن من العودة لاستخدام التطبيق بعد شهر واحد", "Enter Your First Name": "أدخل اسمك الأول", "Are you Sure to LogOut?": "هل أنت متأكد من تسجيل الخروج؟", "Email Wrong": "البريد الإلكتروني خاطئ", "Email you inserted is Wrong.": "البريد الإلكتروني الذي أدخلته خاطئ.", "You have finished all times": "لقد انتهيت من كل الأوقات", "if you want help you can email us here": "إذا كنت ترغب في المساعدة يمكنك مراسلتنا عبر البريد الإلكتروني هنا", "Thanks": "شكرًا", "Email Us": "أرسل لنا بريدًا إلكترونيًا", "I cant register in your app in face detection": "لا أستطيع التسجيل في تطبيقك باستخدام كشف الوجه", "Hi": "مرحبا", "No face detected": "لم يتم الكشف عن وجه", "Image detecting result is": "نتيجة كشف الصورة هي", "from 3 times Take Attention": "من 3 مرات خذ انتباهك", "Be sure for take accurate images please": "تأكد من التقاط صور دقيقة من فضلك", "You have": "لديك", "image verified": "الصورة موثقة", "Next": "التالي", "There is no help Question here": "لا يوجد سؤال مساعدة هنا", // "Call End": "انتهاء المكالمة", "You dont have Points": "ليس لديك رصيد تشغيل", "You Are Stopped For this Day !": "تم إيقافك لهذا اليوم!", "You must be charge your Account": "يجب عليك شحن حسابك", "You Refused 3 Rides this Day that is the reason": "رفضت 3 رحلات هذا اليوم وهذا هو السبب", "See you Tomorrow!": "أراك غدًا!", "Recharge my Account": "قم بإعادة شحن حسابي", "Ok , See you Tomorrow": "حسنًا، أراك غدًا", "You are Stopped": "أنت متوقف", "Connected": "متصل", "Not Connected": "غير متصل", "Your are far from passenger location": "أنت بعيد عن موقع الركاب", "go to your passenger location before": "انتقل إلى موقع الراكب الخاص بك قبل", "Passenger cancel trip": "الراكب قام بإلغاء الرحلة", "You will get cost of your work for this trip": "ستحصل على تكلفة عملك لهذه الرحلة", "in your wallet": "في محفظتك", "you gain": "تكسب", "Account": "الحساب", "Wallet": "المحفظة", "Maintenance Offer": "عرض الصيانة", // "Enter your Question here": "أدخل سؤالك هنا", "Ineligible for Offer": "غير مؤهل للحصول على العرض", "You should complete 500 trips to unlock this feature.": "يجب عليك إكمال 500 رحلة لتفعيل هذه الميزة.", "Thank You!": "شكراً لك!", "Your rating has been submitted.": "تم إرسال تقييمك.", "General": "عام", "Language": "اللغة", "You can change the language of the app": "يمكنك تغيير لغة التطبيق", "Change Country": "تغيير الدولة", // "Don't start trip if passenger not in your car": // "لا تبدأ الرحلة إذا لم يكن الراكب في سيارتك", "You can change the Country to get all features": "يمكنك تغيير الدولة للحصول على جميع الميزات", "Slide to End Trip": "‏اسحب لإنهاء الرحلة", "App Preferences": "تفضيلات التطبيق", "For Egypt": "للمصريين", "Non Egypt": "لغير المصريين", "Google Map App": "تطبيق خرائط جوجل", "If you want to make Google Map App run directly when you apply order": "إذا كنت تريد تشغيل تطبيق خرائط جوجل مباشرة عند تطبيق الطلب", "Vibration": "الاهتزاز", "Help & Support": "المساعدة والدعم", "Please select a rating before submitting.": "يرجى تحديد تقييم قبل الإرسال.", "Please check back later for available rides.": "يرجى التحقق مرة أخرى لاحقًا للحصول على الرحلات المتاحة.", "Please enter your question": "يرجى إدخال سؤالك", "Submit Question": "إرسال السؤال", "Your Questions": "أسئلتك", "No questions asked yet.": "لم يتم طرح أي أسئلة بعد.", "Activities": "الأنشطة", "History of Trip": "سجل الرحلات", "Available for rides": "متاح للرحلات", "Support": "الدعم", "Helping Center": "مركز المساعدة", "More": "المزيد", "Order Cancelled": "الطلب ملغى", "Order Cancelled by Passenger": "تم إلغاء الطلب من قبل الراكب", "Success": "‏تمام", "Feedback data saved successfully": "تم حفظ بيانات التقييم بنجاح", "No Promo for today .": "لا ترويج لليوم.", "Select your destination": "اختر وجهتك", "Search for your Start point": "ابحث عن نقطة البداية الخاصة بك", "Search for waypoint": "ابحث عن نقطة الوايبوينت", "Current Location": "الموقع الحالي", "Add Location 1": "أضف الموقع 1", "You must Verify email !.": "يجب التحقق من البريد الإلكتروني!", "Cropper": "القص", "Saved Sucssefully": "تم الحفظ بنجاح", "Select Date": "اختر التاريخ", "Birth Date": "تاريخ الميلاد", "Ok": "حسنا", "the 500 points equal 30 JOD": "الـ 500 نقطة تساوي 30 دينار أردني", "the 500 points equal 30 JOD for you": "الـ500 نقطة تعادل 30 دينار أردني لك", "token updated": "الرمز تم تحديثه", "Add Location 2": "أضف الموقع ٢", "Add Location 3": "أضف الموقع ٣", "Add Location 4": "أضف الموقع ٤", "Waiting for your location": "في انتظار موقعك", "Search for your destination": "ابحث عن وجهتك", "Hi! This is": "مرحبًا! هذا", "I am using": "أنا استخدم", "to ride with": "للركوب مع", "as the driver.": "كسائق.", "is driving a": "يقود", "with license plate": "بوجود لوحة ترخيص", "I am currently located at": "أنا حاليا موجود في", "Please go to Car now": "الرجاء الذهاب إلى السيارة الآن", "If you need to reach me, please contact the driver directly at": "إذا كنت بحاجة للتواصل معي، يرجى التواصل مع السائق مباشرة على", "No Car or Driver Found in your area.": "لم يتم العثور على سيارة أو سائق في منطقتك.", "Please Try anther time": "يرجى المحاولة مرة أخرى", "There no Driver Aplly your order sorry for that": "لا يوجد سائق يمكنه تنفيذ طلبك، نأسف لذلك.", "Trip Cancelled": "تم إلغاء الرحلة", "The Driver Will be in your location soon .": "سيكون السائق في موقعك قريبًا.", "The distance less than 500 meter.": "المسافة أقل من 500 متر.", "Promo End !": "انتهاء العرض!", "There is no notification yet": "لا توجد إشعارات بعد", "Use Touch ID or Face ID to confirm payment": "استخدم معرف اللمس أو معرف الوجه لتأكيد الدفع", "Contact us for any questions on your order.": "اتصل بنا لأي استفسار حول طلبك.", "Pyament Cancelled .": "تم إلغاء الدفع.", "type here": "اكتب هنا", "Scan Driver License": "فحص رخصة القيادة", "Please put your licence in these border": "يرجى وضع رخصتك في هذه الحدود", "Camera not initialized yet": "الكاميرا لم تُهيأ بعد", "Take Image": "خذ صورة", "AI Page": "صفحة الذكاء الاصطناعي", "Take Picture Of ID Card": "خذ صورة لبطاقة الهوية", "Take Picture Of Driver License Card": "خذ صورة لبطاقة رخصة القيادة.", "We are process picture please wait": "نحن نقوم بمعالجة الصور، يرجى الانتظار.", "There is no data yet.": "لا توجد بيانات بعد.", "Name :": "الاسم:", "Drivers License Class:": "رخصة القيادة الفئة:", "Document Number:": "رقم الوثيقة:", "Address:": "العنوان:", "Height:": "الطول:", "Expiry Date:": "تاريخ الانتهاء:", "Date of Birth:": "تاريخ الميلاد:", "You can't continue with us .": "لا يمكنك الاستمرار معنا.", "You should renew Driver license": "يجب عليك تجديد رخصة القيادة", "Detect Your Face": "اكتشاف وجهك", "Go to next step": "انتقل إلى الخطوة التالية", "scan Car License.": "فحص رخصة السيارة.", "Name in arabic": "الاسم بالعربية", "Drivers License Class": "رخصة القيادة الفئة", "Date of Birth": "تاريخ الميلاد", "Age": "العمر", "Lets check Car license": "دعونا نتحقق من رخصة السيارة", "Car Kind": "نوع السيارة", "Car Plate": "لوحة السيارة", "Lets check License Back Face": "دعونا نتحقق من رخصة الوجه الخلفي", "Car License Card": "بطاقة ترخيص السيارة", "No image selected yet": "لم يتم اختيار صورة بعد", "Made :": "صنع:", "model :": "الموديل:", "VIN :": "رقم الهيكل:", "year :": "سنة:", "ُExpire Date": "تاريخ الانتهاء", "Login Driver": "تسجيل الدخول للسائق", "Password must br at least 6 character.": "يجب أن تكون كلمة المرور على الأقل 6 أحرف.", "if you don't have account": "إذا لم يكن لديك حساب", "Here recorded trips audio": "هنا تسجيلات رحلات صوتية", "Register as Driver": "التسجيل كشريك سائق", "Privacy Notice": "إشعار الخصوصية", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "من خلال اختيار \"أوافق\" أدناه، قمت بمراجعة الشروط والأحكام وأوافق عليها وأقر بها", ". I am at least 18 years of age.": ". أنا عمري على الأقل 18 عامًا.", "Log Out Page": "صفحة تسجيل الخروج", "Log Off": "سجل الخروج", "Register Driver": "سجل السائق", "Verify Email For Driver": "تحقق من البريد الإلكتروني للسائق", "Admin DashBoard": "لوحة تحكم المشرف", "Your name": "اسمك", "your ride is applied": "تم تطبيق مشوارك", "Your password": "كلمة السر الخاصة بك", "LE": "جنيه مصري", "JOD": "الدينار الأردني", "m": "m", "We search nearst Driver to you": "نحن نبحث عن أقرب شريك سائق إليك", "please wait till driver accept your order": "انتظر من فضلك حتى يقبل السائق طلبك", "No accepted orders? Try raising your trip fee to attract riders.": "لا توجد طلبات مقبولة ؟ حاول زيادة رسوم رحلتك لجذب الركاب.", "You should select one": "يجب عليك اختيار واحد", "The driver accept your order for": "قبل الشريك السائق طلبك مقابل", "Increase Fee": "زيادة الرسوم", "No, thanks": "لا، شكرًا", "The driver on your way": "الشريك السائق في طريقه إليك", "Total price from": "السعر الإجمالي من", "Order Details Intaleq": "تفاصيل الطلب السرعة", // "Order Applied": "تم تطبيق الطلب", "accepted your order": "تم قبول طلبك", // "We regret to inform you that another driver has accepted this order.": // "يؤسفنا إبلاغك بأن شريكاً سائقاً آخر قد قبل هذا الطلب.", "Selected file:": "الملف المحدد:", "Your trip cost is": "تبلغ تكلفة رحلتك", "this will delete all files from your device": "سيقوم هذا بحذف جميع الملفات من جهازك", "you have a negative balance of": "لديك رصيد سلبي قدره", "in your": "فيك", "Exclusive offers and discounts always with the Intaleq app": "عروض وخصومات حصرية دائمًا مع تطبيق انطلق", // "Please go to Car Driver": "من فضلك اذهب إلى سائق السيارة", "wallet due to a previous trip.": "المحفظة بسبب رحلة سابقة.", // "Submit Question": "إرسال السؤال", "Please enter your Question.": "الرجاء إدخال سؤالك.", "Help Details": "تفاصيل المساعدة", "No trip yet found": "لم يتم العثور على رحلة بعد", "No Response yet.": "لا توجد استجابة حتى الآن.", "You Earn today is": "كسبك اليوم هو", // "You Have in": "لديك في", "Total points is": "‏الرصيد التشغيل", "Total Connection Duration:": "إجمالي مدة الاتصال:", "H and": "H و", "Passenger name :": "اسم المسافر:", // "Cost Of Trip IS": "تكلفة الرحلة هي", "Arrival time": "وقت الوصول", "arrival time to reach your point": "وقت الوصول للوصول إلى وجهتك", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "للرحلات السريعة والتوصيل، يتم حساب السعر بشكل ديناميكي. أما بالنسبة للرحلات المريحة، يعتمد السعر على الوقت والمسافة.", "Hello this is Driver": "مرحباً، أنا الشريك السائق", "Please wait for the passenger to enter the car before starting the trip.": "يرجى الانتظار حتى يدخل الراكب السيارة قبل بدء الرحلة.", "No ,still Waiting.": "لا ، ما زلت في انتظارك.", "I arrive you": "لقد وصلت إليك", "I Arrive your site": "لقد وصلت إليك", "please go to picker location exactly": "الرجاء الانتقال إلى موقع الاختيار بالضبط", "You Can Cancel Trip And get Cost of Trip From": "يمكنك إلغاء المشوار والحصول على تكلفة المشوار من", // "Yes": "نعم", "Insert Emergincy Number": "أدخل رقم الطوارئ", "Best choice for comfort car and flexible route and stops point": "أفضل خيار للسيارة المريحة والطريق المرن ونقطة التوقف", "Insert": "إدراج", "Total weekly is ": " ‏مجموع التحصيل الأسبوعي ", "you can buy ": "‏يمكنك شراء", "Which method you will pay": "‏أي طريقة الدفع تفضل", "This is for delivery or a motorcycle.": "هذا للتوصيل أو دراجة نارية.", "by ": "‏ ب", 'Fixed Price': 'سعر ثابت', "Weekly Budget": "‏التقرير الأسبوعي", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "ينتقل هذا المشوار مباشرة من نقطة البداية إلى وجهتك بسعر ثابت. يجب على الشريك السائق اتباع المسار المخطط له", "You can decline a request without any cost": "يمكنك رفض الطلب دون أي تكلفة", "Perfect for adventure seekers who want to experience something new and exciting": "مثالي للباحثين عن المغامرة الذين يرغبون في تجربة شيء جديد ومثير", "My current location is:": "موقعي الحالي هو:", "and I have a trip on": "ولدي رحلة في", "App with Passenger": "تطبيق مع الراكب", "You will be pay the cost to driver or we will get it from you on next trip": "سيتم دفع التكلفة للشريك السائق أو سنحصل عليها منك في المشوار التالي", "Trip has Steps": "الرحلة لها خطوات", "Distance from Passenger to destination is": "مسافة الراكب إلى الوجهة هي", "price is": "السعر هو", "This ride type does not allow changes to the destination or additional stops": "لا يسمح نوع المشوار هذا بإجراء تغييرات على الوجهة أو نقاط توقُّف إضافية", "This price may be changed": "قد يتم تغيير هذا السعر", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "لا توجد بطاقة SIM، لا توجد مشكلة! اتصل بالشريك السائق مباشرة من خلال تطبيقنا. نحن نستخدم التكنولوجيا المتقدمة لضمان خصوصيتك.", "This ride type allows changes, but the price may increase": "يسمح نوع الرحلة هذا بالتغييرات، لكن قد يرتفع السعر", // "message From Driver": "‏رسالة من السائق", // "message From passenger": "رسالة من الراكب", "Select one message": "اختر رسالة واحدة", "I'm waiting for you": "أنا في انتظارك", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "لاحظنا أن السرعة تتجاوز 100 كم/ساعة. يرجى إبطاء السرعة حفاظًا على سلامتك. إذا شعرت بعدم الأمان، يمكنك مشاركة تفاصيل رحلتك مع جهة اتصال أو الاتصال بالشرطة باستخدام الزر الأحمر للاستغاثة.", "Warning: Intaleqing detected!": "تحذير: تم اكتشاف السرعة الزائدة!", "Please help! Contact me as soon as possible.": "من فضلك ساعدني! تواصل معي في أقرب وقت ممكن.", "Email": "البريد الإلكتروني", "Please enter your Email.": "يرجى إدخال بريدك الإلكتروني", "Email must be correct.": "البريد الإلكتروني يجب أن يكون صحيحاً", "Password": "كلمة المرور", "Please enter your Password.": "يرجى إدخال كلمة المرور", "Password must be at least 6 characters.": "يجب أن تكون كلمة المرور مكونة من 6 أحرف على الأقل", "Phone Number": "رقم الهاتف", // "Please enter your phone number.": "يرجى إدخال رقم هاتفك", "Phone number must be valid.": "يجب أن يكون رقم الهاتف صحيحاً", "Share Trip Details": "شارك تفاصيل الرحلة", "Car Plate is": "لوحة السيارة", "L.E": "ج.م", "the 300 points equal 300 L.E for you": "الـ 300 نقطة تعادل 300 جنيه مصري بالنسبة لك", "So go and gain your money": "انطلق واكسب مالك", "the 300 points equal 300 L.E": "الـ 300 نقطة تساوي 300 جنيه مصري", "The payment was not approved. Please try again.": "لم يتم الموافقة على الدفع. يرجى المحاولة مرة أخرى.", "Payment Failed": "تعذرت عملية الدفع", // "Error": "خطأ", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the ": "مِنْ خِلَال اخْتِيَار 'أُوَافِق' أَدْنَاهُ، قُمْتُ بِمُرَاجَعَة وَقَبُول شُرُوط الاسْتِخْدَام وَأُقِرُّ بِإِشْعَار الخُصُوصِيَّة. أَنَا عَلَى الأَقَل 18 عَامًا.", "If you need any help or have question this is right site to do that and your welcome": "إذا كنت بحاجة إلى أي مساعدة أو لديك أي أسئلة، فهذا هو الموقع المناسب للقيام بذلك، ومرحباً بك", "Helping Page": "‏مركز المساعدة", "No ride yet": "‏لا يوجد رحلات متوفرة", "An error occurred during the payment process.": "حدث خطأ أثناء عملية الدفع.", "The payment was approved.": "تمت الموافقة على الدفع.", "Payment Successful": "تم الدفع بنجاح", "No ride found yet": "لم يتم العثور على رحلة بعد", "Accept Order": "قبول الطلب", "Bottom Bar Example": "مثال على الشريط السفلي", "Driver phone": "هاتف الشريك السائق", "Statistics": "الإحصائيات", "is ON for this month": " لهذا الشهر ", "Origin": "الأصل", "Destination": "مكان الوصول", "the 300 points equal 300 L.E for you \nSo go and gain your money": "ال300 نقطة تعادل 300 ج.م لك، فاذهب واكسب مالك.", "Driver Name": "اسم السائق", "Driver Car Plate": "لوحة سيارة السائق", // "Available for rides": "‏الرحلات المتوفرة", "Scan Id": "فحص الهوية", "Camera not initilaized yet": "الكاميرا لم تُهيأ بعد", "Scan ID MklGoogle": "فحص الهوية MklGoogle", // "Language": "اللغة", "Jordan": "الأردن", "USA": "الولايات المتحدة الأمريكية", "Egypt": "مصر", "Turkey": "تركيا", "Saudi Arabia": "السعودية", "Qatar": "قطر", "Bahrain": "البحرين", "Kuwait": "الكويت", "But you have a negative salary of": "لكن لديك راتب سالب من", "Promo Code": "الرمز الترويجي", "Your trip distance is": "مسافة رحلتك هي", "Enter promo code": "أدخِل الرمز الترويجي", "You have promo!": "لديك عرض ترويجي!", "Cost Duration": "مدة التكلفة", "Duration is": "المدة هي", "Leave": "اترك", "Join": "انضم", "You Should be select reason.": "يجب عليك اختيار السبب.", "\$": "\$", "Waiting for Driver ...": "في انتظار الشريك السائق ...", "Latest Recent Trip": "أحدث مشوار", "from your list": "من قائمتك", "Do you want to change Work location": "هل ترغب في تغيير موقع العمل؟", "Do you want to change Home location": "هل ترغب في تغيير موقع المنزل", "We Are Sorry That we dont have cars in your Location!": "نحن نأسف لعدم توفر السيارات في موقعك!", "Choose from Map": "اختر من الخريطة", "Pick your ride location on the map - Tap to confirm": "اختر موقع ركوبك على الخريطة - اضغط لتأكيد", "To Work": "للعمل", "welcome_to_intaleq": "أهلاً بك في انطلق", "welcome to intaleq": "أهلاً بك في انطلق", "login or register subtitle": "أدخل رقم هاتفك للدخول أو إنشاء حساب جديد", "phone number label": "رقم الهاتف", "phone number required": "يرجى إدخال رقم الهاتف", "send otp button": "إرسال رمز التحقق", "verify your number title": "التحقق من الرقم", "otp sent subtitle": "تم إرسال رمز تحقق من 5 أرقام إلى\n@phoneNumber", "verify and continue button": "تحقق ومتابعة", "enter otp validation": "الرجاء إدخال رمز التحقق المكون من 5 أرقام", "one last step title": "خطوة أخيرة", "complete profile subtitle": "أكمل بياناتك الشخصية للبدء", "first name label": "الاسم الأول", "first name required": "يرجى إدخال الاسم الأول", "last name label": "الاسم الأخير", "last name required": "يرجى إدخال الاسم الأخير", "email optional label": "البريد الإلكتروني (اختياري)", "complete registration button": "إكمال التسجيل", "otp sent success": "تم إرسال رمز التحقق إلى واتساب.", "failed to send otp": "فشل إرسال الرمز.", "server error try again": "حدث خطأ بالخادم، يرجى المحاولة لاحقاً.", "an error occurred": "حدث خطأ غير متوقع: @error", "otp verification failed": "رمز التحقق غير صحيح.", "registration failed": "فشلت عملية التسجيل.", "welcome user": "أهلاً بك، @firstName!", 'Balance': 'الرصيد', "Today's Promo": "عرض اليوم", 'Credit': 'رصيد', 'Debit': 'خصم', 'Transactions this week': 'المعاملات هذا الأسبوع', 'Weekly Summary': 'ملخص أسبوعي', 'Total Weekly Earnings': 'إجمالي الأرباح الأسبوعية', 'No transactions this week': 'لا توجد معاملات هذا الأسبوع', "Driver Balance": "رصيد السائق", "The 30000 points equal 30000 S.P for you \nSo go and gain your money": "الـ 30000 نقطة تساوي 30000 ل.س لك \nلذا اذهب واكسب أموالك", "OK": "موافق", "Your Application is Under Review": "طلبك قيد المراجعة", "We have received your application to join us as a driver. Our team is currently reviewing it. Thank you for your patience.": "لقد استلمنا طلبك للانضمام إلينا كسائق. يقوم فريقنا حاليًا بمراجعته. شكرًا لك على صبرك.", "You Will Be Notified": "سيتم إشعارك قريباً", "We will send you a notification as soon as your account is approved. You can safely close this page, and we'll let you know when the review is complete.": "سنرسل لك إشعاراً فور الموافقة على حسابك. يمكنك إغلاق هذه الصفحة بأمان، وسنعلمك عند اكتمال المراجعة.", "Refresh Status": "تحديث الحالة", "Checking for updates...": "جاري التحقق من التحديثات...", "Total Points is": "إجمالي النقاط هو", "Charge your Account": "اشحن حسابك", '''Types of Trips in Intaleq: - Comfort: For cars newer than 2017 with air conditioning. - Lady: For girl drivers. - Speed: For fixed salary and endpoints. - Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements. - Raih Gai: For same-day return trips longer than 50km.''': "أنواع الرحلات في انطلق:\n\n- مريح: للسيارات الأحدث من 2017 مع تكييف الهواء.\n- سيدة: للسائقات الإناث.\n- سرعة: لرحلات ذات راتب ثابت ونقاط نهاية محددة.\n- مشاوير: لرحلات مرنة حيث يختار الركاب السيارة والسائق مع ترتيبات مسبقة.\n- رايح جاي: لرحلات العودة في نفس اليوم لأكثر من 50 كم.", 'L.S': 'ل.س', "Total Amount:": "المبلغ الإجمالي:", "Intaleq Wallet": "رصيد انطلق", "Current Balance": "الرصيد الحالي", "SYP": "ل.س.", "Your total balance:": "رصيدك الإجمالي:", "Payment Method:": "طريقة الدفع:", "e.g., 0912345678": "مثال: 0912345678", "Your balance is less than the minimum withdrawal amount of {minAmount} S.P.": "رصيدك أقل من الحد الأدنى للسحب وهو {minAmount} ل.س.", "This amount for all trip I get from Passengers": "هذا المبلغ عن كل رحلة أحصل عليها من الركاب", "SAFAR Wallet": "محفظة سفر", "Pay from my budget": "ادفع من رصيدي", "You have in account": "لديك في الحساب", "Pay": "دفع", "Your Budget less than needed": "رصيدك أقل من المطلوب", "You do not have enough money in your SAFAR wallet": "ليس لديك ما يكفي من المال في محفظة سفر الخاصة بك", "You can purchase a budget to enable online access through the options listed below": "يمكنك شراء رصيد لتفعيل الوصول عبر الإنترنت من خلال الخيارات المذكورة أدناه", "this is count of your all trips in the morning promo today from 7:00am to 10:00am": "هذا هو عدد جميع رحلاتك في عرض الصباح اليوم من الساعة 7:00 صباحًا حتى 10:00 صباحًا", "this is count of your all trips in the Afternoon promo today from 3:00pm to 6:00 pm": "هذا هو عدد جميع رحلاتك في عرض الظهيرة اليوم من الساعة 3:00 مساءً حتى 6:00 مساءً", "Payment History": "سجل المدفوعات", "Insert Payment Details": "أدخل تفاصيل الدفع", "Insert your mobile wallet details to receive your money weekly": "أدخل تفاصيل محفظتك الإلكترونية لاستلام أموالك أسبوعيًا", "Insert mobile wallet number": "أدخل رقم المحفظة الإلكترونية", "syriatel": "سيريتل", "mtn": "إم تي إن", "Payment details added successfully": "تمت إضافة تفاصيل الدفع بنجاح", "Your Journey Begins Here": "رحلتك تبدأ هنا", "Are you want to go this site": "هل تريد الذهاب إلى هذا الموقع", "Closest & Cheapest": "الأقرب والأرخص", "Work Saved": "‏‏تم حفظ:", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "انطلق هو تطبيق طلب المشاوير الآمن والموثوق به والذي يمكن الوصول إليه.", "With Intaleq, you can get a ride to your destination in minutes.": "مع انطلق، يمكنك إجراء مشوار إلى وجهتك في غضون دقائق.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "يلتزم انطلق بالسلامة، ويتم فحص جميع قادتنا بعناية وفحص الخلفية الجنائية.", "To Home": "إلى الصفحة الرئيسية", "Home Saved": "‏‏تم حفظ:", "Destination selected": "تم تحديد الوجهة", "Now select start pick": "الآن اختر بدء الاختيار", "Pick from map": "اختر من الخريطة", "Click here point": "انقر هنا", "No Car in your site. Sorry!": "لا توجد سيارة في موقعك. عذرًا!", "Nearest Car for you about": "أقرب سيارة لك حوالي", "N/A": "لا توجد معلومات", "From :": "من:", "Get Details of Trip": "احصل على تفاصيل الرحلة", "If you want add stop click here": "إذا كنت ترغب في إضافة توقف، انقر هنا", "Driver": "سائق", "Where you want go": "أين تريد أن تذهب؟", "My Card": "بطاقتي", "Start Record": "بدء التسجيل", // "Wallet": "محفظة", // "History of Trip": "‏أرشيف الرحلات", // "Helping Center": "مركز المساعدة", "Record saved": "تم حفظ السجل", "Trips recorded": "رحلات مسجلة", "Select Your Country": "اختر بلدك", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "لضمان حصولك على أدق المعلومات لموقعك، يرجى تحديد بلدك أدناه. سيساعد هذا في تخصيص تجربة التطبيق والمحتوى لبلدك.", "Are you sure to delete recorded files": "هل أنت متأكد من حذف الملفات المسجلة", "Select recorded trip": "اختر مشوارًا مسجلاً", "Card Number": "رقم البطاقة", "Hi, Where to": "مرحبًا، إلى أين؟", "Pick your destination from Map": "اختر وجهتك من الخريطة", "Add Stops": "أضف توقفات", "Get Direction": "احصل على الاتجاه", "Add Location": "أضف الموقع", "Switch Rider": "تبديل الراكب", "You will arrive to your destination after timer end.": "سوف تصل إلى وجهتك بعد انتهاء المؤقت.", "You can cancel trip": "يمكنك إلغاء الرحلة", "The driver waitting you in picked location .": "الشريك السائق في انتظارك في الموقع المُحدَّد .", "Pay with Your": "ادفع باستخدام", "Pay with Credit Card": "ادفع ببطاقة الائتمان", "Show Promos to Charge": "إظهار العروض الترويجية للشحن", "Point": "نقطة", "Total Budget from trips is": "الميزانية الإجمالية من الرحلات هي", "Total Budget from trips by": "الميزانية الإجمالية من الرحلات حسب", "Credit card is": "بطاقة الائتمان", "You can buy Points to let you online": "يمكنك شراء النقاط لتمكينك من الدخول عبر الإنترنت", "by this list below": "من خلال هذه القائمة أدناه", // "Create Wallet to receive your money": "أنشئ محفظة لاستقبال أموالك", "Enter your feedback here": "أدخل ملاحظاتك هنا", "Please enter your feedback.": "الرجاء إدخال نص ملاحظاتك", "Feedback": "التغذية الراجعة", "Click here to Show it in Map": "انقر هنا لعرضه على الخريطة", "Canceled": "تم الإلغاء", "Type your Email": "اكتب بريدك الإلكتروني", "No I want": "لا، أريد", "Email is": "البريد الإلكتروني", "Phone Number is": "رقم الهاتف هو", "Date of Birth is": "تاريخ الميلاد هو", "Sex is": "الجنس هو", "Car Details": "تفاصيل السيارة", "VIN is": "رقم الهيكل", "Color is": "اللون هو", "Make is": "الصنع هو", "Model is": "النموذج من:", "Year is": "السنة", "Edit Your data": "تعديل بياناتك", "write vin for your car": "اكتب رقم الهيكل الخاص بسيارتك", "VIN": "رقم هيكل السيارة", "write Color for your car": "اكتب لون سيارتك", "write Make for your car": "اكتب صنع لسيارتك", "write Model for your car": "اكتب نموذج سيارتك", "write Year for your car": "اكتب سنة لسيارتك", "write Expiration Date for your car": "اكتب تاريخ انتهاء الصلاحية لسيارتك", "Tariffs": "تعريفات", "Minimum fare": "الحد الأدنى للأجرة", "Maximum fare": "أقصى سعر", "Flag-down fee": "رسوم التوقف", "Including Tax": "بما في ذلك الضريبة", "BookingFee": "رسوم الحجز", "Morning": "الصباح", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "من الساعة 07:30 حتى الساعة 10:30 (الخميس، الجمعة، السبت، الاثنين)", "Evening": "مساء", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "من الساعة 12:00 حتى الساعة 15:00 (الخميس، الجمعة، السبت، الاثنين)", "Night": "الليل", "You have in account": "لديك في الحساب", "Select Country": "اختر البلد", "Ride Today :": "اطلب مشواراً اليوم :", "After this period": "بعد هذه الفترة", "You can't cancel!": "لا يمكنك الإلغاء!", "from 23:59 till 05:30": "من 23:59 حتى 05:30", "Rate Driver": "قيم السائق", "Total Cost is": "التكلفة الإجمالية هي", "Write note": "اكتب ملاحظة", "Time to arrive": "الوقت المتوقع للوصول", "Ride Summaries": "ملخصات الرحلات", // "Total Cost": "التكلفة الإجمالية", "Average of Hours of": "متوسط ساعات العمل", // "is ON for this month": "قيد التشغيل لهذا الشهر", "Days": "أيام", "Total Hours on month": "إجمالي عدد الساعات في الشهر", "Counts of Hours on days": "عدد الساعات في الأيام", "OrderId": "رقم الطلب", "created time": "وقت الإنشاء", "Intaleq Over": "السرعة فوق", "I will slow down": "سأبطئ", "Map Passenger": "خريطة الراكب", "Be Slowly": "كن بطيئًا", // "If you want to make Google Map App run directly when you apply order": // "إذا كنت تريد تشغيل تطبيق خرائط جوجل مباشرة عند تطبيق الأمر", "Your Budget less than needed": "ميزانيتك أقل من المطلوب", // "You can change the Country to get all features": // "يمكنك تغيير البلد للحصول على جميع الميزات", // "Change Country": "غير البلد" }, "tr": { "Order": "Sipariş", "OrderVIP": "VIP Sipariş", "Cancel Trip": "Yolculuğu İptal Et", "Passenger Cancel Trip": "Yolcu Yolculuğu İptal Etti", "VIP Order": "VIP Sipariş", "The driver accepted your trip": "Sürücü yolculuğunuzu kabul etti", "message From passenger": "Yolcudan mesaj", "Cancel": "İptal", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Yolculuk İptal Edildi. Yolculuk ücreti cüzdanınıza eklenecektir.", "token change": "token değişikliği", "face detect": "yüz algılama", "Face Detection Result": "Yüz Algılama Sonucu", "similar": "benzer", "not similar": "benzer değil", "Hi ,I will go now": "Merhaba, şimdi gideceğim", "Passenger come to you": "Yolcu size geliyor", "Call Income": "Gelen Arama", "Call Income from Passenger": "Yolcudan Gelen Arama", "Criminal Document Required": "Adli Belge Gerekli", "You should have upload it .": "Yüklemeniz gerekiyor.", "Call End": "Arama Sonu", "The order has been accepted by another driver.": "Sipariş başka bir sürücü tarafından kabul edildi.", "The order Accepted by another Driver": "Sipariş başka bir Sürücü tarafından Kabul Edildi", "We regret to inform you that another driver has accepted this order.": "Başka bir sürücünün bu siparişi kabul ettiğini bildirmekten üzgünüz.", "Driver Applied the Ride for You": "Sürücü Sizin İçin Yolculuğa Başvurdu", "Applied": "Başvuruldu", "Hi ,I Arrive your site": "Merhaba, konumunuza geldim", "Please go to Car Driver": "Lütfen Araç Sürücüsüne gidin", "Ok I will go now.": "Tamam, şimdi gideceğim.", "Accepted Ride": "Kabul Edilen Yolculuk", "Driver Accepted the Ride for You": "Sürücü Sizin İçin Yolculuğu Kabul Etti", "Promo": "Promosyon", "Show latest promo": "En son promosyonu göster", "Trip Monitoring": "Yolculuk İzleme", "Driver Is Going To Passenger": "Sürücü Yolcuya Gidiyor", "Please stay on the picked point.": "Lütfen seçilen noktada kalın.", "message From Driver": "Sürücüden mesaj", "Trip is Begin": "Yolculuk Başladı", "Cancel Trip from driver": "Sürücüden Yolculuk İptali", "We will look for a new driver.\nPlease wait.": "Yeni bir sürücü arayacağız.\nLütfen bekleyin.", "The driver canceled your ride.": "Sürücü yolculuğunuzu iptal etti.", "Driver Finish Trip": "Sürücü Yolculuğu Bitirdi", "you will pay to Driver": "Sürücüye ödeme yapacaksınız", "Don’t forget your personal belongings.": "Kişisel eşyalarınızı unutmayın.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Lütfen ayrılmadan önce tüm kişisel eşyalarınızın yanınızda olduğundan ve varsa kalan ücretin cüzdanınıza eklendiğinden emin olun. Intaleq uygulamasını seçtiğiniz için teşekkür ederiz", "Finish Monitor": "İzlemeyi Bitir", "Trip finished": "Yolculuk bitti", "Call Income from Driver": "Sürücüden Gelen Arama", "Driver Cancelled Your Trip": "Sürücü Yolculuğunuzu İptal Etti", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Sürücüye ödeme yapacaksınız, sürücü zamanının maliyetini ödeyeceksiniz, Intaleq Cüzdanınıza bakın", "Order Applied": "Sipariş Uygulandı", //firbase }, "fr": { "Order": "Commande", "OrderVIP": "Commande VIP", "Cancel Trip": "Annuler le trajet", "Passenger Cancel Trip": "Passager a annulé le trajet", "VIP Order": "Commande VIP", "The driver accepted your trip": "Le chauffeur a accepté votre trajet", "message From passenger": "Message du passager", "Cancel": "Annuler", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Trajet annulé. Le coût du trajet sera ajouté à votre portefeuille.", "token change": "changement de jeton", "face detect": "détection faciale", "Face Detection Result": "Résultat de la détection faciale", "similar": "similaire", "not similar": "non similaire", "Hi ,I will go now": "Salut, je vais y aller maintenant", "Passenger come to you": "Le passager vient vers vous", "Call Income": "Appel entrant", "Call Income from Passenger": "Appel entrant du passager", "Criminal Document Required": "Document judiciaire requis", "You should have upload it .": "Vous auriez dû le télécharger.", "Call End": "Fin d'appel", "The order has been accepted by another driver.": "La commande a été acceptée par un autre chauffeur.", "The order Accepted by another Driver": "La commande acceptée par un autre chauffeur", "We regret to inform you that another driver has accepted this order.": "Nous regrettons de vous informer qu'un autre chauffeur a accepté cette commande.", "Driver Applied the Ride for You": "Le chauffeur a postulé pour le trajet pour vous", "Applied": "Appliqué", "Hi ,I Arrive your site": "Salut, je suis arrivé à votre emplacement", "Please go to Car Driver": "Veuillez vous rendre au chauffeur de la voiture", "Ok I will go now.": "Ok, j'y vais maintenant.", "Accepted Ride": "Trajet accepté", "Driver Accepted the Ride for You": "Le chauffeur a accepté le trajet pour vous", "Promo": "Promo", "Show latest promo": "Afficher la dernière promo", "Trip Monitoring": "Surveillance du trajet", "Driver Is Going To Passenger": "Le chauffeur se dirige vers le passager", "Please stay on the picked point.": "Veuillez rester au point de prise en charge indiqué.", "message From Driver": "Message du chauffeur", "Trip is Begin": "Le trajet commence", "Cancel Trip from driver": "Annulation du trajet par le chauffeur", "We will look for a new driver.\nPlease wait.": "Nous allons chercher un nouveau chauffeur.\nVeuillez patienter.", "The driver canceled your ride.": "Le chauffeur a annulé votre trajet.", "Driver Finish Trip": "Le chauffeur a terminé le trajet", "you will pay to Driver": "vous paierez le chauffeur", "Don’t forget your personal belongings.": "N'oubliez pas vos effets personnels.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Veuillez vous assurer que vous avez tous vos effets personnels et que tout montant restant, le cas échéant, a été ajouté à votre portefeuille avant de partir. Merci d'avoir choisi l'application Intaleq", "Finish Monitor": "Terminer la surveillance", "Trip finished": "Trajet terminé", "Call Income from Driver": "Appel entrant du chauffeur", "Driver Cancelled Your Trip": "Le chauffeur a annulé votre trajet", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "vous paierez le chauffeur, vous paierez le coût du temps du chauffeur, consultez votre portefeuille Intaleq", "Order Applied": "Commande appliquée", //firbase "registration_date": "Date d'enregistrement", "expiration_date": "Date d'expiration", "rating_count": "Nombre d'évaluations", "rating_driver": "Note du chauffeur", "age": "Âge", "vin": "Parce que je suis les fonctions. J'ai mémorisé les numéros d'identification.", "car_color": "- La couleur.", "car_plate": "Le numéro d'immatriculation ?", "car_model": "Modèle de voiture :", "education": "Les études", "gender": "sexe", "birthdate": "Date de naissance", "Approve Driver Documents": "Approuver les documents du chauffeur", "Total Budget is": "BUDGET TOTAL", "You will recieve code in sms message": "Vous recevrez le code par SMS", "Please enter": "Emplacement du fichier d'agenda pour KAlarm", "We need your phone number to contact you and to help you receive orders.": "Nous avons besoin de votre numéro de téléphone pour vous contacter et vous aider à recevoir des commandes.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "Le nom complet sur votre casier judiciaire ne correspond pas au nom sur votre permis de conduire. Veuillez vérifier et fournir les documents corrects.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "Le numéro national de votre permis de conduire ne correspond pas à celui de votre pièce d'identité. Veuillez vérifier et fournir les documents corrects.", "Capture an Image of Your Criminal Record": "Prenez une photo de votre casier judiciaire", "IssueDate": "Date de délivrance ", "Capture an Image of Your car license front": "Prenez une photo de votre permis de conduire de face", "Capture an Image of Your ID Document front": "Prenez une photo de votre pièce d'identité de face", "NationalID": "Numéro national", "FullName": "Nom complet", "InspectionResult": "Résultats de l'examen", "Criminal Record": "Casier judiciaire", "The email or phone number is already registered.": "L'adresse e-mail ou le numéro de téléphone est déjà enregistré.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "Pour devenir chauffeur de covoiturage dans l'app Voyages, vous devez télécharger votre permis de conduire, votre pièce d'identité et votre document d'immatriculation du véhicule. Notre système d'IA examinera et vérifiera immédiatement son authenticité en seulement 2 à 3 minutes. Si vos documents sont approuvés, vous pouvez commencer à travailler en tant que chauffeur dans l'application Voyages. Veuillez noter que la fourniture de documents falsifiés est une infraction grave et peut entraîner une résiliation immédiate et des conséquences juridiques.", "Documents check": "Vérification des documents", "Driver's License": "Permis de conduire", "License Type": "Type de licence", "National Number": "Numéro d’identité national :", "Name (Arabic)": "Nom (arabe)", "Name (English)": "Anglais", "Address": "Adresse", "Issue Date": "Date de délivrance ", "Expiry Date": "Date d'expiration", "License Categories": "Autorisation", "driver_license": "Permis de conduire", "Capture an Image of Your Driver License": "Prenez une photo de votre permis de conduire", "ID Documents Back": "B. Pièces d'identité", "National ID": "Carte d'identité nationale", "Occupation": "Profession :", "Gender": "sexe", "Religion": "la religion", "Marital Status": "État civil ", "Full Name (Marital)": "Nom complet", "Expiration Date": "Date d'expiration", "Capture an Image of Your ID Document Back": "Prenez une photo du verso de votre pièce d'identité", "ID Documents Front": "Recto des documents d'identification", "First Name": "Prénom...", "CardID": "Prenez une photo du verso de votre pièce d'identité", "Full Name": "Nom complet", "Vehicle Details Front": "Détails du véhicule avant", "Plate Number": "Plaque d'immatriculation", "Owner Name": "Le nom du propriétaire est Dr.", "Vehicle Details Back": "Détails du véhicule", "Make": "Make", "Model": "Modèle de voiture :", "Year": "Année", "Chassis": "Châssis", "Color": "- La couleur.", "Displacement": "À remplacer", "Fuel": "Carburant !", "Tax Expiry Date": "Date d'expiration", "Inspection Date": "DATE D'EXAMEN:", "Capture an Image of Your car license back": "Prenez à nouveau une photo de votre permis de conduire", "Capture an Image of Your Driver’s License": "Prenez une photo de votre permis de conduire", "Sign in with Google for easier email and name entry": "Connectez-vous avec Google pour saisir facilement votre adresse e-mail et votre nom", "You will choose allow all the time to be ready receive orders": "Vous choisirez d'autoriser les commandes prêtes à l'emploi tout le temps", "Welcome to Intaleq!": "Bienvenue dans", "Get to your destination quickly and easily.": "Accédez à votre destination rapidement et facilement.", "Enjoy a safe and comfortable ride.": "Profitez d'une course sûre et confortable.", "Choose Language": "Choisissez la langue", "Login": "Se connecter", "Pay with Wallet": "Payer avec un portefeuille", "Invalid MPIN": "Code MPIN invalide", "Invalid OTP": "Code de vérification", "Enter your email address": "Saisissez votre adresse e-mail", "Please enter Your Email.": "Veuillez saisir...", "Enter your phone number": "Quel est ton nom ?", "Please enter your phone number.": "Veuillez saisir votre numéro de téléphone.", "Please enter Your Password.": "Veuillez entrer votre mot de passe", "Submit": "Envoyé", "if you dont have account": "Que voulez-vous dire ?", "Register": "C'est parti !", "Accept Ride's Terms & Review Privacy Notice": "Acceptez les conditions de la course et consultez l'avis de confidentialité", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "En sélectionnant « J'accepte » ci-dessous, j'ai examiné et accepté les Conditions d'utilisation et j'accepte la Déclaration de confidentialité.Au moins un an", "I Agree": " Je suis d'accord", "First name": "Prénom...", "Enter your first name": "Saisissez votre nom", "Please enter your first name.": "Veuillez saisir votre nom.", "Last name": "Nom de famille", "Enter your last name": "NOM:", "Please enter your last name.": "Veuillez saisir votre nom.", "City": "Ville", "Please enter your City.": "Veuillez saisir...", "Male": "Homme", "Female": "Femme", "Verify Email": "27\":\"E-mail validé.\":", "We sent 5 digit to your Email provided": "Nous avons envoyé 5 chiffres à l'adresse e-mail que vous avez fournie", "5 digit": "Broche(5chiffres)", "Send Verification Code": "Code de vérification", "Your Ride Duration is": "La durée de votre course est de", "You will be thier in": "Vous les aurez dans", "You trip distance is": "La distance de votre course est de", "Fee is": "Les frais sont", "To :": "À :", "Add Promo": "Ajouter une promotion", "Confirm Selection": "Confirmer la sélection", "distance is": "La distance est", "duration is": "La durée est", "I don't need a ride anymore": "J'en ai plus besoin.", "I was just trying the application": "J'essayais juste l'application", "No driver accepted my request": "Aucun chauffeur n'a accepté ma commande", "I added the wrong pick-up/drop-off location": "Vous avez ajouté le mauvais lieu de prise en charge/destination", "I don't have a reason": "J'en sais rien.", "Other": "Autre …", "Can we know why you want to cancel Ride ?": "Peut-on savoir pourquoi vous souhaitez annuler la course ?", "Cancel Ride": "Avorter!", "Add Payment Method": "Ajouter un mode de paiement", "Your Wallet balance is": "Le solde de votre portefeuille est", "Ride Wallet": "Portefeuille de voyage", "Payment Method": "Mode de paiement", "Type here Place": "C'est ici !", "Are You sure to ride to": "Êtes-vous sûr de vouloir rouler jusqu'à", "Confirm": "Valider", "Back": "Répondez.", "You are Delete": "Vous supprimez", "Deleted": "Supprimé", "You Dont Have Any places yet !": "Vous n'avez pas encore de places !", "Favorite Places": "C'est votre genre d'endroit ?", "From : Current Location": "Utiliser la position actuelle", "Where to": "Où?", "Notifications": "Notifications", "Profile": "Profil personnel", "Home": "Accueil", "My Cared": "MyCurt", "Add Card": "Ajouter une carte", "Add Credit Card": "C'est de la MasterCard.", "Please enter the cardholder name": "Veuillez saisir le nom du titulaire de la carte", "Please enter the expiry date": "la date de péremption", "Please enter the CVV code": "Veuillez saisir le code de vérification de la carte", "Go To Favorite Places": "Accéder aux lieux favoris", "Go to this Target": "Atteindre cet objectif", "My Profile": "Aperçu du profil", "Sign Out": "Se Déconnecter", "Home Page": "Accueil", "Are you want to go to this site": "Voulez-vous aller à cet endroit", "MyLocation": "Ma position", "my location": "Ma position", "Target": "Objectif", "Update": "Mise à jour", "You Should choose rate figure": "Vous devez choisir le bon numéro", "Login Captin": "Se connecter", "Register Captin": "Inscription du capitaine", "Send Verfication Code": "Code de vérification", "End Ride": "Embarquez !", "Minute": "Minute", "Go to passenger Location now": "Accéder à l'emplacement du passager maintenant", "Duration of the Ride is": "La durée de la course est de", "Distance of the Ride is": "La distance parcourue est de", "Name of the Passenger is": "Le nom du passager est", "Hello this is Captain": "Bonjour, je suis le capitaine", "Start the Ride": "Commencer la course", "Please Wait If passenger want To Cancel!": "Veuillez patienter si le passager souhaite annuler !", "Total Duration:": "durée totale de la formation", "Active Duration:": "Durée de l'étape active", "Waiting for Captin ...": "J'attends le capitaine.", "Age is": "C'est l'âge...", "Rating is": "- L'évaluation est...", "to arrive you.": "pour vous joindre.", "Order History": "Enregistrer l'historique des commandes", "My Wallet": "Ma portefeuille", "Tariff": "Tarif", "Settings": "Paramètres", "Feed Back": "- Les réflexes sont normaux.", "Promos": "Promotions", "Please enter a valid 16-digit card number": "Veuillez saisir un numéro de bon de commande valide.", "Add Phone": "Téléphone", "Please enter a phone number": "Veuillez saisir un numéro de téléphone.", "You dont Add Emergency Phone Yet!": "Vous n'avez pas encore ajouté de téléphone d'urgence !", "You will arrive to your destination after": "Vous arriverez à destination après", "You can cancel Ride now": "Vous pouvez annuler la course maintenant", "You Can cancel Ride After Captain did not come in the time": "Vous pouvez annuler la course lorsque le capitaine n'est pas arrivé à temps", "If you in Car Now. Press Start The Ride": "Si vous êtes dans la voiture en ce moment. Appuyez sur Commencer la course.", "You Dont Have Any amount in": "Vous n'avez aucun montant en", "Wallet!": "Ho !", "You Have": "- Euh...", "Save Credit Card": "- La carte.", "Show Promos": "Presentations ", "10 and get 4% discount": "10 et obtenez 4 % de réduction", "20 and get 6% discount": "20 et obtenez 6 % de réduction", "40 and get 8% discount": "40 et obtenez 8 % de réduction", "100 and get 11% discount": "100 % et obtenez 11 % de réduction", "Pay with Your PayPal": "Payer avec PayPal", "You will choose one of above !": "Vous choisirez l'une des options ci-dessus !", "Cancel": "Annuler", "Delete My Account": "Supprimer mon compte", "Edit Profile": "Modifier le profil", "Name": "Nom", "Update Gender": "Mettre à jour le sexe", "Education": "Les études", "Update Education": ":: Moderniser l'enseignement;", "Employment Type": "Catégorie de personnel", "SOS Phone": "Mobile", "High School Diploma": "BACCALAUREAT DE L'ENSEIGNEMENT", "Associate Degree": "Diplôme conjoint", "Bachelor's Degree": "Grade de bachelier", "Master's Degree": "Master", "Doctoral Degree": "Docteur en philosophie.", "Promos For today": "Promotions", "Copy this Promo to use it in your Ride!": "Copiez cette promotion pour l'utiliser lors de votre voyage !", "To change some Settings": "Pour modifier certains paramètres", "To change Language the App": "Pour modifier la langue de l'application", "Order Request Page": "Page de demande de commande", "Rouats of Trip": "Tripp.", "Passenger Name is": "Voyageur.", "Total From Passenger is": "Le total du passager est", "Duration To Passenger is": "Durée jusqu'au passager", "Distance To Passenger is": "distance par rapport au passager est", "Total For You is": "Le total pour vous est de", "Distance is": "Distance", "KM": "Km", "Duration of Trip is": "La durée de la course est de", "Minutes": "Minutes", "Apply Order": "Appliquer la commande", "Refuse Order": "- Demande rejetée.", "Rate Captain": "Cote de capitaine", "Enter your Note": "J'ai eu votre mot.", "Type something...": "Écrire quelque chose...", "Submit rating": "Fournir une évaluation", "Rate Passenger": "Note du passager", "Ride Summary": "Résumé de la course", "welcome_message": "Insérer « & #160; Bonjour monde & #160; »", "app_description": "ApplicationDescription", "get_to_destination": "Destination atteinte. Déblocage des contrôles manuels.", "get_a_ride": "Commandez une course", "safe_and_comfortable": "Sûr et confortable", "committed_to_safety": "Engagé pour la sécurité", "Driver Applied the Ride for You": "Un chauffeur qui a effectué la course pour vous", "Show latest promo": "Afficher la dernière promotion", "Cancel Trip": "Le vol est annulé.", "Passenger Cancel Trip": "Le passager annule la course", "Please stay on the picked point.": "Veuillez rester au point sélectionné.", "Trip is Begin": "Votre initiation a commencé.", "Hi ,I will go now": "Bonjour, j'y vais maintenant", "Passenger come to you": "Votre passager vient vous voir", "Hi ,I Arrive your site": "Bonjour, vous avez atteint votre position.", "Driver Finish Trip": "Fin de la course du chauffeur", "you will pay to Driver": "Sérieux ? Probablement avec mon argent.", "Driver Cancel Your Trip": "Annulez votre course, chauffeur.", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Vous paierez le chauffeur Vous paierez le coût du temps du chauffeur Regardez votre portefeuille Intaleq", "I will go now": "- J'y vais.", "You Have Tips": "Astuces", "tips": "Des paroles sages ?", "Total is": "Chiffre total est de 15", "No,I want": "- Je n'en ai pas envie.", "Your fee is": "Vos frais sont de", "Do you want to pay Tips for this Driver": "Souhaitez-vous laisser un pourboire à ce chauffeur ?", "Tip is": "Monconseil", "Camera Access Denied.": "Accès à la caméra refusé.", "Open Settings": "|||UNTRANSLATED_CONTENT_START|||افتح الإعدادات|||UNTRANSLATED_CONTENT_END|||", "GPS Required Allow !.": "Le GPS doit être activé !", "Your Account is Deleted": "Votre compte a été supprimé", "Are you sure to delete your account?": "Voulez-vous vraiment supprimer votre compte ?", "Your data will be erased after 2 weeks": "Vos données seront effacées après 2 semaines", "And you will can't return to use app after 1 month": "Vous pourrez revenir à l'application après un mois", "Enter Your First Name": "Saisissez votre nom", "Are you Sure to LogOut?": "Voulez-vous vraiment vous déconnecter?", "Email Wrong": "Email ", "Email you inserted is Wrong.": "L'adresse e-mail que vous avez saisie est incorrecte.", "You have finished all times": "J'en ai assez !", "if you want help you can email us here": "Si vous souhaitez de l'aide, vous pouvez nous envoyer un e-mail ici", "Thanks": "Merci.", "Email Us": "Envoyez-nous un e-mail", "I cant register in your app in face detection": "Je ne peux pas m'inscrire à votre application avec la détection de visage", "Hi": "-C'est un plaisir. -Hello.", "No face detected": "Aucun scanner n'a été détécté", "Image detecting result is": "Le résultat de la détection d'image est", "from 3 times Take Attention": "que 3 fois attirent votre attention", "Be sure for take accurate images please": "Assurez-vous de prendre des photos précises s'il vous plaît", "You have": "- Euh...", "image verified": "La photo est notariée", "Next": "Suivant", "There is no help Question here": "Ouais, pas d'aide ici.", "Call End": "Terminer l'appel", "You dont have Points": "- Vous n'avez pas...", "You Are Stopped For this Day !": "Vous avez été mis en pause pour la journée !", "You must be charge your Account": "Vous devez recharger votre compte", "You Refused 3 Rides this Day that is the reason": "Vous avez refusé 3 courses aujourd'hui et c'est pourquoi", "See you Tomorrow!": "Je te verrais demain.", "Recharge my Account": "Recharger mon compte", "Ok , See you Tomorrow": "D'accord, on se voit demain.", "You are Stopped": "Vous êtes arrêté", "Connected": "Online", "Not Connected": "Offiline", "Your are far from passenger location": "Vous êtes loin de l'emplacement des passagers", "go to your passenger location before": "Accédez à l'emplacement de votre passager avant le", "Passenger cancel trip": "Le passager a annulé la course", "You will get cost of your work for this trip": "Vous obtiendrez le coût de votre entreprise pour cette course", "in your wallet": "Elle est dans ton portefeuille.", "you gain": "Vous gagnerez", "Order Cancelled": "Commande annulée", "Order Cancelled by Passenger": "Demande annulée par le passager", "Success": "Je l'ai.", "Feedback data saved successfully": "Données d'évaluation enregistrées avec succès", "No Promo for today .": "Pas de promotion pour aujourd'hui.", "Select your destination": "Sélectionnez la destination;", "Search for your Start point": "Trouvez votre point de départ", "Search for waypoint": "Rechercher un point WIPOINT", "Current Location": "Utiliser la position actuelle", "Add Location 1": "Emplacement & #160;: %1", "You must Verify email !.": "Relever le courriel", "Cropper": "Récolte", "Saved Sucssefully": "Bien reçu.", "Select Date": "Choisir une nouvelle date", "Birth Date": "Date de naissance", "Ok": "D'accord.", "the 500 points equal 30 JOD": "500 points équivaut à 30 JOD", "the 500 points equal 30 JOD for you": "500 points équivaut à 30 JOD pour vous", "token updated": "Code mis à jour", "Add Location 2": "Ajouter un emplacement 2", "Add Location 3": "Ajouter un emplacement 3", "Add Location 4": "Ajouter un emplacement 4", "Waiting for your location": "En attente de votre localisation", "Search for your destination": "Trouvez votre destination", "Hi! This is": "Bienvenue \"moi\": c' est ça.", "I am using": "Du matériel que j'utilisais.", "to ride with": "pour rouler avec", "as the driver.": "On dirait un chauffeur.", "is driving a": "- Je vais le tenter comme ça. - Conduire.", "with license plate": "Avec une plaque d'immatriculation", "I am currently located at": "Je suis actuellement en", "Please go to Car now": "S'il te plaît, va-t-en maintenant.", "If you need to reach me, please contact the driver directly at": "Si vous avez besoin de me joindre, veuillez contacter directement le chauffeur au", "No Car or Driver Found in your area.": "Aucune voiture ou chauffeur trouvé dans votre région.", "Please Try anther time": "Réessayer", "There no Driver Aplly your order sorry for that": "Aucun chauffeur ne peut répondre à votre demande, nous sommes désolés.", "Trip Cancelled": "Course annulée", "The Driver Will be in your location soon .": "Votre chauffeur arrivera bientôt chez vous.", "The distance less than 500 meter.": "La distance est inférieure à 500 mètres.", "Promo End !": "- C'est seulement jusqu'au spectacle.", "There is no notification yet": "Aucune notification pour le moment", "Use Touch ID or Face ID to confirm payment": "Utilisez Touch ID ou Face ID pour confirmer le paiement", "Contact us for any questions on your order.": "Contactez-nous pour toute question concernant votre commande.", "Pyament Cancelled .": "Le paiement a été annulé.", "type here": "Tapez ici", "Scan Driver License": "Permis de conduire", "Please put your licence in these border": "Veuillez placer votre licence dans ces limites", "Camera not initialized yet": "Caméra pas encore configurée", "Take Image": "Prends une photo, parce que demain matin, ces lettres partiront.", "AI Page": "Tu dis que ton système \"IA\"", "Take Picture Of ID Card": "Prenez une photo de votre pièce d'identité", "Take Picture Of Driver License Card": "Prenez une photo de votre permis de conduire.", "We are process picture please wait": "Nous traitons les images, veuillez patienter.", "There is no data yet.": "Aucune donnée trouvée", "Name :": "Nom :", "Drivers License Class:": "Catégorie de permis de conduire :", "Document Number:": "Numéro du document", "Address:": "Adresse:", "Height:": "& Hauteur & #160;:", "Expiry Date:": "Expiration & #160;:", "Date of Birth:": "Anniversaire & #160;: @title: group", "You can't continue with us .": "Ça ne peut pas durer.", "You should renew Driver license": "Vous devez renouveler votre permis de conduire", "Detect Your Face": "Découvrez votre visage", "Go to next step": "\"", "scan Car License.": "Vérification de l'immatriculation du véhicule.", "Name in arabic": "Full Name AR", "Drivers License Class": "Permis de conduire", "Date of Birth": "Date de naissance", "Age": "l’âge", "Lets check Car license": "Vérifions le permis de conduire", "Car Kind": "Type de véhicule", "Car Plate": "Le numéro d'immatriculation ?", "Lets check License Back Face": "Vérifions la licence de face arrière", "Car License Card": "Carte d'immatriculation du véhicule", "No image selected yet": "Aucune photo sélectionnée pour le moment", "Made :": "Make", "model :": "Mod.", "VIN :": "Structure :", "year :": "Année", "ُExpire Date": "Date d'expiration", "Login Driver": "Se connecter", "Password must br at least 6 character.": "Le mot de passe doit comporter au moins 6 caractères.", "if you don't have account": "Que voulez-vous dire ?", "Here recorded trips audio": "Voici les enregistrements audio du voyage", "Register as Driver": "Inscrivez-vous en tant que chauffeur", "Privacy Notice": "Avis de confidentialité", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "En sélectionnant « J'accepte » ci-dessous, j'ai lu, j'accepte et j'accepte les conditions générales", ". I am at least 18 years of age.": ". J'ai au moins 18 ans.", "Log Out Page": "Se Déconnecter", "Log Off": "Signe.", "Register Driver": "Le chauffeur...", "Verify Email For Driver": "Consultez l'e-mail du chauffeur", "Admin DashBoard": "Tableau de bord d'administration", "Your name": "Ton... nom.", "your ride is applied": "Votre course a été appliquée", "Your password": "Renouveler votre mot de passe", "LE": "Livre égyptienne", "JOD": "Monnaie: Dinar jordanien", "m": "%1 km", "We search nearst Driver to you": "Nous recherchons le chauffeur le plus proche", "please wait till driver accept your order": "Veuillez attendre que le chauffeur accepte votre demande", "No accepted orders? Try raising your trip fee to attract riders.": "Aucune Essayez d'augmenter les frais de course pour attirer des passagers.", "You should select one": "Vous devez en choisir un", "The driver accept your order for": "Votre chauffeur a accepté votre demande de", "Increase Fee": "Augmenter les frais", "No, thanks": "Non merci", "The driver on your way": "Votre chauffeur est en route", "Total price from": "P.T", "Order Details Intaleq": "Détails du commande", "Order Applied": "Commande appliquée", "accepted your order": "- Retenue.", "We regret to inform you that another driver has accepted this order.": "Nous sommes désolés de vous informer qu'un autre chauffeur a accepté cette demande.", "Selected file:": "Ouvre un fichier existant", "Your trip cost is": "Les frais de votre course", "this will delete all files from your device": "Cela supprimera tous les fichiers de votre appareil", "you have a negative balance of": "Vous avez un solde négatif de", "in your": "En toi.", "Exclusive offers and discounts always with the Intaleq app": "Offres exclusives et réductions toujours avec l'application de voyage", "Please go to Car Driver": "Veuillez vous rendre chez le conducteur de la voiture", "wallet due to a previous trip.": "Portefeuille en raison d'une course précédente.", "Submit Question": "Envoyer la question", "Please enter your Question.": "Veuillez saisir votre question.", "Help Details": "Détails de l'aide", "No trip yet found": "Aucune campagne trouvée", "No Response yet.": "Il n'y a pas de réponses.", "You Earn today is": "- On est euh...", "You Have in": "Vous avez à", "Total points is": "Le score total est de", "Total Connection Duration:": "Durée totale de connexion :", "H and": "H et", "Passenger name :": "Le voyageur.", "Cost Of Trip IS": "Coûts des vols par avion spécial", "Arrival time": "On arrive dans 7 minutes.", "arrival time to reach your point": "Heure d'arrivée pour atteindre votre destination", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Pour les courses et livraisons rapides, le prix est calculé de manière dynamique. Pour des courses confortables, le prix est basé sur la durée et la distance.", "Hello this is Driver": "Bonjour, je suis le chauffeur", "Is the Passenger in your Car ?": "Le passager est-il dans votre véhicule ?", "Please wait for the passenger to enter the car before starting the trip.": "Veuillez attendre que le passager entre dans le véhicule avant de commencer la course.", "No ,still Waiting.": "Non , je t'attends toujours.", "I arrive you": "Elle t'a eue.", "I Arrive your site": "Elle t'a eue.", "You are not in near to passenger location": "Vous n'êtes pas près de l'emplacement du passager", "please go to picker location exactly": "Veuillez vous rendre à l'emplacement exact de la sélection", "You Can Cancel Trip And get Cost of Trip From": "Vous pouvez annuler la course et obtenir le coût de la course auprès de", "Are you sure to cancel?": "Voulez-vous vraiment annuler ?", "Yes": "Oui", "Insert Emergincy Number": "Saisir le numéro d'urgence", "Best choice for comfort car and flexible route and stops point": "Le meilleur choix pour une voiture confortable, un itinéraire flexible et un point d'arrêt", "Insert": "En cours d' utilisation", "This is for delivery or a motorcycle.": "C'est pour la livraison ou une moto.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "Cette course va directement de votre point de départ à votre destination pour un tarif forfaitaire. Le chauffeur doit suivre l'itinéraire prévu", "You can decline a request without any cost": "Vous pouvez refuser la demande sans frais", "Perfect for adventure seekers who want to experience something new and exciting": "Idéal pour les chercheurs d'aventure qui veulent essayer quelque chose de nouveau et d'excitant", "My current location is:": "Mon emplacement actuel est :", "and I have a trip on": "et j'ai un voyage à", "App with Passenger": "Postuler avec le passager", "You will be pay the cost to driver or we will get it from you on next trip": "Le coût sera payé au chauffeur ou nous l'obtiendrons de votre part lors de la prochaine course", "Trip has Steps": "La course comporte des étapes", "Distance from Passenger to destination is": "La distance entre le passager et la destination est", "price is": "C'est cent dollars.", "This ride type does not allow changes to the destination or additional stops": "Ce type de course ne permet pas de modifier la destination ou d'effectuer des arrêts supplémentaires", "This price may be changed": "Ce prix peut changer", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "Pas de carte SIM, pas de problème ! Contactez directement votre chauffeur via notre application. Nous utilisons une technologie de pointe pour garantir votre confidentialité.", "This ride type allows changes, but the price may increase": "Ce type de course peut être modifié, mais le prix peut augmenter", "message From passenger": "Estafette.", "Select one message": "Message un.", "My location is correct. You can search for me using the navigation app": "Ma position est correcte. Vous pouvez me rechercher à l'aide de l'application de navigation", "I'm waiting for you": "- Quand vous voulez.", "Hello, I'm at the agreed-upon location": "Bonjour, je suis à l'endroit convenu", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "Nous avons remarqué que la vitesse dépasse 100 km/h. Veuillez ralentir pour votre propre sécurité. Si vous ne vous sentez pas en sécurité, vous pouvez communiquer les détails de votre course à un contact ou appeler la police à l'aide du bouton de détresse rouge.", "Warning: Intaleqing detected!": "Avertissement : survitesse détectée !", "Please help! Contact me as soon as possible.": "Aide-moi s'il te plaît. Contactez-moi dès que possible.", "Share Trip Details": "Partagez les détails de la", "Car Plate is": "Le numéro d'immatriculation ?", "the 3000 points equal 3000 L.E for you": "3000 points équivaut à 3000 EGP pour vous", "So go and gain your money": "Gagnez de l'argent", "the 3000 points equal 3000 L.E": "3000 points équivaut à 3000 EGP", "The payment was not approved. Please try again.": "Paiement non approuvé. Réessayer", "Payment Failed": "Échec du paiement", "Error": "ⵜⴰⵣⴳⵍⵜ", "An error occurred during the payment process.": "Une erreur s'est produite lors de votre paiement.", "The payment was approved.": "Paiement approuvé.", "Payment Successful": "Paiement réussi", "No ride found yet": "Aucune campagne trouvée", "Accept Order": "Commande acceptée", "reject your order.": "Votre Ordre.", "Bottom Bar Example": "Exemple de barre inférieure", "Driver phone": "Téléphone du chauffeur", "Statistics": "& Statistiques", "Origin": "ORIGINE", "Destination": "- Destination ?", "Driver Name": "Nom de pilote & #160;:", "Driver Car Plate": "Plaque d'immatriculation du conducteur", "Available for rides": "Disponible pour les courses", "Scan Id": "Contrôle d'identité", "Camera not initilaized yet": "Caméra pas encore configurée", "Scan ID MklGoogle": "Vérification d'identité MklGoogle", "Language": "Langue ", "Jordan": "Jordanie", "USA": "Etats Unis d'Amérique", "Egypt": "Egypte", "Turkey": "Turquie", "Saudi Arabia": "Arabie Saoudite", "Qatar": "Qatar", "Bahrain": "Bahreïn", "Kuwait": "Koweït", "But you have a negative salary of": "Mais vous avez un salaire négatif de", "Promo Code": "Code promo", "Your trip distance is": "La distance de votre course est de", "Enter promo code": "Code promo", "You have promo!": "Vous avez une promotion !", "Cost Duration": "Durée du coût", "Duration is": "La durée est", "Leave": "Quitter", "Join": "Joindre", "You Should be select reason.": "Vous devez choisir une raison.", "\$": "\$", "Waiting for Driver ...": "En attente du chauffeur ...", "Latest Recent Trip": "J'ai des choses à faire!", "from your list": "À partir de votre liste", "Do you want to change Work location": "Souhaitez-vous changer de lieu de travail ?", "Do you want to change Home location": "Souhaitez-vous changer l'emplacement de la maison", "We Are Sorry That we dont have cars in your Location!": "Nous sommes désolés que les voitures ne soient pas disponibles chez vous !", "Choose from Map": "Sélectionner sur la carte", "Pick your ride location on the map - Tap to confirm": "Sélectionnez votre lieu de prise en charge sur la carte - appuyez pour confirmer", "To Work": "Pour le boulot", "Are you want to go this site": "Voulez-vous aller à cet endroit", "Closest & Cheapest": "Le plus proche et le moins cher", "Work Saved": "Enregistré :", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq est une application de covoiturage sûre, fiable et accessible.", "With Intaleq, you can get a ride to your destination in minutes.": "En voyageant, vous pouvez vous rendre à destination en quelques minutes.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Safar s'engage pour la sécurité, et tous nos commandants sont soigneusement contrôlés et leurs antécédents vérifiés.", "To Home": "RETOUR À LA PAGE D'ACCUEIL", "Home Saved": "Enregistré :", "Destination selected": "Destination sélectionnée", "Now select start pick": "Maintenant, choisissez Démarrer la sélection", "Pick from map": "Sélectionner sur la carte", "Click here point": "Cliquez ici", "No Car in your site. Sorry!": "Il n'y a pas de voiture dans votre région. Ex... Excusez moi.", "Nearest Car for you about": "La voiture la plus proche de chez vous est d'environ", "N/A": "Aucune information", "From :": "Du :", "Get Details of Trip": "Obtenir les détails de la course", "If you want add stop click here": "Si vous souhaitez ajouter un arrêt, cliquez ici", "Driver": "ⴰⵎⵏⴷⴰⵀ", "Where you want go": "D'où viens-tu ?", "My Card": "Ma carte.", "Start Record": "Début de la campagne d'enregistrement", "Wallet": "Un portefeuille.", "History of Trip": "2.1 Histoire du vol", "Helping Center": "Centre d'aide", "Record saved": "Sauvegarde de l'historique effectuée !", "Trips recorded": "Voyages enregistrés", "Select Your Country": "Selectionnez votre pays", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "Pour vous assurer d'avoir les informations les plus précises pour votre emplacement, veuillez sélectionner votre pays ci-dessous. Cela vous aidera à personnaliser l'expérience et le contenu de l'application pour votre pays.", "Are you sure to delete recorded files": "Êtes-vous sûr de vouloir supprimer les fichiers enregistrés", "Select recorded trip": "Choisissez une course enregistrée", "Card Number": "N  de pièce d'identité:", "Hi, Where to": "Bonjour, oùallez-vous ?", "Pick your destination from Map": "Sélectionner sur la carte", "Add Stops": "Ajouter des arrêts", "Get Direction": "Obtenir une direction", "Add Location": "Ajouter l'emplacement correctement", "Switch Rider": "Changer de passager", "You will arrive to your destination after timer end.": "Vous arriverez à destination après l'expiration de la minuterie.", "You can cancel trip": "Vous pouvez annuler la course", "The driver waitting you in picked location .": "Votre chauffeur vous attend à l'endroit désigné .", "Pay with Your": "Payer avec", "Pay with Credit Card": "- La carte.", "Payment History": "Historique des paiements", "Show Promos to Charge": "Afficher les promotions d'expédition", "Point": "Points", "Driver Balance": "Portefeuille chauffeur", "Total Points is": "Le score total est de", "Total Budget from trips is": "Le budget total des voyages est de", "Total Amount:": "Montant total", "Total Budget from trips by": "Budget total des voyages par", "Credit card is": "Votre carte de crédit.", "This amount for all trip I get from Passengers": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers.", "Pay from my budget": "Payer sur mon budget", "This amount for all trip I get from Passengers and Collected For me in": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers collectés pour moi à", "You can buy points from your budget": "Vous pouvez acheter des points à partir de votre budget", "insert amount": "Entrez le montant", "You can buy Points to let you online": "Vous pouvez acheter des points pour vous permettre d'accéder en ligne", "by this list below": "Grâce à cette liste ci-dessous", "Create Wallet to receive your money": "Créez un portefeuille pour recevoir votre argent", "Enter your feedback here": "Saisissez vos commentaires ici", "Please enter your feedback.": "Veuillez saisir le texte de vos notes", "Feedback": "Feedback:", "Click here to Show it in Map": "Cliquez ici pour le voir sur la carte", "Canceled": "Annulé", "Type your Email": "Votre e-mail", "No I want": "- Je n'en ai pas envie.", "Email is": "Email ", "Phone Number is": "C'est le 92.38.09.06.", "Date of Birth is": "Année de naissance", "Sex is": "Le sexe est cardio.", "Car Details": "Détails du véhicule", "VIN is": "Structure", "Color is": "- Sa couleur?", "Make is": "Make is", "Model is": "Formulaire de :", "Year is": "Année", "Edit Your data": "Modifiez vos informations", "write vin for your car": "Notez le numéro de châssis de votre véhicule", "VIN": "|||UNTRANSLATED_CONTENT_START|||رقم هيكل السيارة|||UNTRANSLATED_CONTENT_END|||", "write Color for your car": "Tapez la couleur de votre voiture", "write Make for your car": "Écrivez une marque pour votre voiture", "write Model for your car": "Tapez votre modèle de voiture", "write Year for your car": "Saisissez une année pour votre voiture", "write Expiration Date for your car": "la date de péremption", "Tariffs": "Définitions ", "Minimum fare": "Prix minimum", "Maximum fare": "Prix maximum", "Flag-down fee": "Frais d'escale", "Including Tax": "Incluant...", "BookingFee": "Frais de réservation", "Morning": "- Bonjour.", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07h30 - 10h30 (jeudi, vendredi, samedi, lundi)", "Evening": "- Bonsoir.", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12h00 - 15h00 (jeudi, vendredi, samedi, lundi)", "Night": "la nuit", "You have in account": "Vous avez dans le compte", "Select Country": "Sélectionner un pays.", "Ride Today :": "Commandez une course aujourd'hui :", "After this period": "Après cette période", "You can't cancel!": "- Vous pouvez plus...", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "Le chauffeur...", "Total Cost is": "Coût total", "Write note": "J'écris une lettre de menace.", "Time to arrive": "Bobby, Qu'elle est notre e. t. a.?", "Ride Summaries": "Résumés des courses", "Total Cost": "Coût total", "Average of Hours of": "Nombre moyen d'heures de travail", "is ON for this month": "En cours ce mois-ci", "Days": "Quelques mois, semaines... quelques jours.", "Total Hours on month": "Nombre total d'heures", "Counts of Hours on days": "Heures en jours", "OrderId": "Commande N°", "created time": "Date de création", "Intaleq Over": "Et c'est là qu'on l'aura.", "I will slow down": "Je vais ralentir.", "Map Passenger": "Carte du passager", "Be Slowly": "Soyez lent", "If you want to make Google Map App run directly when you apply order": "Si vous souhaitez lancer Google Maps directement lorsque vous appliquez la commande", "You can change the language of the app": "Vous pouvez modifier la langue de l'application", "Your Budget less than needed": "Votre budget est sous-estimé", "You can change the Country to get all features": "Vous pouvez modifier le pays pour obtenir toutes les fonctionnalités", "Change Country": "Non-pays" }, "it": { "Order": "Ordine", "OrderVIP": "Ordine VIP", "Cancel Trip": "Annulla Viaggio", "Passenger Cancel Trip": "Passeggero Annulla Viaggio", "VIP Order": "Ordine VIP", "The driver accepted your trip": "L'autista ha accettato il tuo viaggio", "message From passenger": "Messaggio dal passeggero", "Cancel": "Annulla", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Viaggio Annullato. Il costo del viaggio sarà aggiunto al tuo portafoglio.", "token change": "cambio token", "face detect": "rilevamento facciale", "Face Detection Result": "Risultato Rilevamento Facciale", "similar": "simile", "not similar": "non simile", "Hi ,I will go now": "Ciao, vado ora", "Passenger come to you": "Il passeggero sta venendo da te", "Call Income": "Chiamata in Entrata", "Call Income from Passenger": "Chiamata in Entrata dal Passeggero", "Criminal Document Required": "Documento Penale Richiesto", "You should have upload it .": "Avresti dovuto caricarlo.", "Call End": "Fine Chiamata", "The order has been accepted by another driver.": "L'ordine è stato accettato da un altro autista.", "The order Accepted by another Driver": "Ordine Accettato da un altro Autista", "We regret to inform you that another driver has accepted this order.": "Siamo spiacenti di informarti che un altro autista ha accettato questo ordine.", "Driver Applied the Ride for You": "L'Autista Ha Applicato la Corsa per Te", "Applied": "Applicato", "Hi ,I Arrive your site": "Ciao, sono arrivato al tuo sito", "Please go to Car Driver": "Per favore vai dall'Autista", "Ok I will go now.": "Ok, vado ora.", "Accepted Ride": "Corsa Accettata", "Driver Accepted the Ride for You": "L'Autista Ha Accettato la Corsa per Te", "Promo": "Promo", "Show latest promo": "Mostra l'ultima promo", "Trip Monitoring": "Monitoraggio Viaggio", "Driver Is Going To Passenger": "L'Autista Sta Andando dal Passeggero", "Please stay on the picked point.": "Per favore rimani nel punto di prelievo selezionato.", "message From Driver": "Messaggio dall'Autista", "Trip is Begin": "Il Viaggio è Iniziato", "Cancel Trip from driver": "Annulla Viaggio dall'autista", "We will look for a new driver.\nPlease wait.": "Cercheremo un nuovo autista.\nPer favore aspetta.", "The driver canceled your ride.": "L'autista ha annullato la tua corsa.", "Driver Finish Trip": "L'Autista Ha Finito il Viaggio", "you will pay to Driver": "pagherai l'Autista", "Don’t forget your personal belongings.": "Non dimenticare i tuoi effetti personali.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Assicurati di avere con te tutti i tuoi effetti personali e che eventuali tariffe rimanenti, se applicabili, siano state aggiunte al tuo portafoglio prima di partire. Grazie per aver scelto l'app Intaleq", "Finish Monitor": "Termina Monitoraggio", "Trip finished": "Viaggio finito", "Call Income from Driver": "Chiamata in Entrata dall'Autista", "Driver Cancelled Your Trip": "L'Autista Ha Annullato il Tuo Viaggio", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "pagherai l'Autista pagherai il costo del tempo dell'autista guarda il tuo Portafoglio Intaleq", "Order Applied": "Ordine Applicato", //firebase "registration_date": "Data di registrazione", "expiration_date": "Data di scadenza", "rating_count": "Recensioni", "rating_driver": "Valutazione del conducente", "age": "Età", "vin": "Perche' mi affido alla tecnologia. Numero di telaio memorizzato.", "car_color": "- E' il colore...", "car_plate": "Colore? Numero di targa?", "car_model": "Modello dell'auto:", "education": "Istruzione", "gender": "Sesso", "birthdate": "Compleanno", "Approve Driver Documents": "Approva i documenti dell'autista partner", "Total Budget is": "Budget totale", "You will recieve code in sms message": "Riceverai il codice in un SMS", "Please enter": "Inserisci un nome di calendario. @option: check", "We need your phone number to contact you and to help you receive orders.": "Abbiamo bisogno del tuo numero di telefono per contattarti e aiutarti a ricevere gli ordini.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "Il nome completo sulla tua fedina penale non corrisponde al nome sulla tua patente di guida. Controlla e fornisci i documenti corretti.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "Il numero nazionale sulla patente di guida non corrisponde al numero sul documento d'identità. Controlla e fornisci i documenti corretti.", "Capture an Image of Your Criminal Record": "Scatta una foto della tua fedina penale", "IssueDate": "Data emissione", "Capture an Image of Your car license front": "Scatta una foto della tua patente di guida dalla parte anteriore", "Capture an Image of Your ID Document front": "Scatta una foto del tuo documento d'identità dalla parte anteriore", "NationalID": "Numero nazionale", "FullName": "Nome completo", "InspectionResult": "Risultato del test", "Criminal Record": "Fedina Penale ", "The email or phone number is already registered.": "L'e-mail o il numero di telefono sono già registrati.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "Per diventare un autista partner in condivisione nell'app Viaggi, devi caricare la patente di guida, il documento di identità e il documento di immatricolazione del veicolo. Il nostro sistema di intelligenza artificiale esaminerà e verificherà immediatamente la sua autenticità in soli 2-3 minuti. Se i tuoi documenti sono stati approvati, puoi iniziare a lavorare come autista partner nell'app Viaggi. Si prega di notare che fornire documenti falsi è un reato grave e può comportare la risoluzione immediata e conseguenze legali.", "Documents check": "Verifica del documento", "Driver's License": "La patente di guida.", "License Type": "Passa?", "National Number": "N. ID nazionale: ", "Name (Arabic)": "Nome (arabo)", "Name (English)": "- Inglese...", "Address": "Indirizzo ", "Issue Date": "Data emissione", "Expiry Date": "Data di scadenza", "License Categories": "Passa?", "driver_license": "La patente di guida.", "Capture an Image of Your Driver License": "Scatta una foto della tua patente di guida", "ID Documents Back": "Comparsa di documenti di identità", "National ID": "Documento d'identità", "Occupation": "Professione ", "Gender": "Sesso", "Religion": "La religione.", "Marital Status": "Stato Civile", "Full Name (Marital)": "Nome completo", "Expiration Date": "Data di scadenza", "Capture an Image of Your ID Document Back": "Scatta una foto del retro del tuo documento d'identità", "ID Documents Front": "Fronte dei documenti di identificazione", "First Name": "Nome", "CardID": "Scatta una foto del retro del tuo documento d'identità", "Full Name": "Nome completo", "Vehicle Details Front": "Dettagli del veicolo anteriore", "Plate Number": "Numero di targa", "Owner Name": "|||UNTRANSLATED_CONTENT_START|||اسم المالك|||UNTRANSLATED_CONTENT_END|||", "Vehicle Details Back": "Di nuovo i dettagli del veicolo", "Make": "A %1", "Model": "Modello dell'auto:", "Year": "Anno", "Chassis": "Telaio", "Color": "- E' il colore...", "Displacement": "Schemi sostituzioni", "Fuel": "Alimentazione", "Tax Expiry Date": "Data di scadenza", "Inspection Date": "Data esame:", "Capture an Image of Your car license back": "Scatta di nuovo una foto della tua patente di guida", "Capture an Image of Your Driver’s License": "Scatta una foto della tua patente di guida", "Sign in with Google for easier email and name entry": "Accedi con Google per facilitare l'inserimento di email e nome", "You will choose allow all the time to be ready receive orders": "Sceglierai di consentire sempre gli ordini già pronti", "Welcome to Intaleq!": "Benvenuto in Safar!", "Get to your destination quickly and easily.": "Raggiungi la tua destinazione in modo rapido e semplice.", "Enjoy a safe and comfortable ride.": "Goditi una corsa sicura e confortevole.", "Choose Language": "Scegli la lingua", "Login": "Chiamo per il controllo.", "Pay with Wallet": "Paga con il portafoglio", "Invalid MPIN": "Codice MPIN non valido", "Invalid OTP": "Codice di verifica non valido", "Enter your email address": "Immetti il tuo indirizzo e-mail", "Please enter Your Email.": "Inserisci...", "Enter your phone number": "Inserisci il tuo numero di telefono", "Please enter your phone number.": "Please enter your mob.", "Please enter Your Password.": "Immetti la password", "Submit": "Hut!", "if you dont have account": "- Se non le dispiace...", "Register": "Contribuisci.", "Accept Ride's Terms & Review Privacy Notice": "Accetta i termini della corsa e consulta l'informativa sulla privacy", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "Selezionando \"Accetto\" di seguito, ho letto e accetto i Termini di utilizzo e accetto l'Informativa sulla privacy.Almeno un anno", "I Agree": "- Concordo.", "First name": "Nome", "Enter your first name": "Il nome di battesimo.", "Please enter your first name.": "Inserisci il tuo nome.", "Last name": "Cognome.", "Enter your last name": "Cognome.", "Please enter your last name.": "Inserisci il tuo nome.", "City": "Città", "Please enter your City.": "Inserisci...", "Male": "Maschio", "Female": "Femmina", "Verify Email": "Convalida e-mail", "We sent 5 digit to your Email provided": "Abbiamo inviato 5 cifre all'email che ci hai fornito", "5 digit": "Pin(5cifre)", "Send Verification Code": "Abbiamo un dardo che sta cercando di contattarci.", "Your Ride Duration is": "La durata del tuo viaggio è", "You will be thier in": "Li avrai in", "You trip distance is": "La distanza del tuo viaggio è", "Fee is": "La commissione è", "To :": "a:", "Add Promo": "Aggiungi vista", "Confirm Selection": "Conferma selezione", "distance is": "La distanza è", "duration is": "La durata è", "I don't need a ride anymore": "Non ne ho piu' bisogno.", "I was just trying the application": "Stavo solo provando l'app", "No driver accepted my request": "Nessun autista partner ha accettato il mio ordine", "I added the wrong pick-up/drop-off location": "Hai aggiunto un punto di partenza/arrivo errato", "I don't have a reason": "- lo non l'ho trovata.", "Other": "Altro", "Can we know why you want to cancel Ride ?": "Possiamo sapere perché vuoi cancellare la corsa?", "Cancel Ride": "- Annullare, annullare!", "Add Payment Method": "Un metodo di pagamento?", "Your Wallet balance is": "Il saldo del tuo portafoglio è", "Ride Wallet": "Portafoglio da viaggio", "Payment Method": "MODALITÀ’ DI PAGAMENTO", "Type here Place": "Va bene qui.", "Are You sure to ride to": "Sei sicuro di voler viaggiare fino a", "Confirm": "Conferma", "Back": "- Ne abbiamo parlato! Ma guarda, una reunion della serie.", "You are Delete": "Stai eliminando", "Deleted": "Eliminato", "You Dont Have Any places yet !": "Non hai ancora nessun posto!", "Favorite Places": "Ii tuo genere di posto?", "From : Current Location": "posizione attuale:", "Where to": "Dove?", "Notifications": "Avvisamenti ", "Profile": "Profilo", "Home": "Homepage", "My Cared": "MyCurt", "Add Card": "Aggiungi carta", "Add Credit Card": "Carta di Credito", "Please enter the cardholder name": "Inserisci il nome del titolare della carta", "Please enter the expiry date": "Data scadenza", "Please enter the CVV code": "Inserisci il codice di verifica della carta", "Go To Favorite Places": "Vai ai luoghi preferiti", "Go to this Target": "Vai a questo obiettivo", "My Profile": "Panoramica estensione", "Sign Out": "Mi disconnetto.", "Home Page": "Homepage", "Are you want to go to this site": "Vuoi andare in questa posizione", "MyLocation": "Il mio sito web?", "my location": "Il mio sito web?", "Target": "B-E-R... Bersaglio.", "Update": "- Aggiorna... aggiorna...", "You Should choose rate figure": "Devi scegliere il numero corretto", "Login Captin": "Chiamo per il controllo.", "Register Captin": "Registrazione del capitano", "Send Verfication Code": "Invia codice di verifica", "End Ride": "- ln carrozza!", "Minute": "Minuto", "Go to passenger Location now": "Vai subito alla posizione dell'utente", "Duration of the Ride is": "La durata del viaggio è", "Distance of the Ride is": "La distanza del viaggio è", "Name of the Passenger is": "Il nome dell'utente è", "Hello this is Captain": "Ciao, sono il capitano", "Start the Ride": "Inizia corsa", "Please Wait If passenger want To Cancel!": "Attendi se l'utente desidera cancellare la corsa!", "Total Duration:": "Durata totale:", "Active Duration:": "Durata fase attiva", "Waiting for Captin ...": "Aspettando il capitano ...", "Age is": "- L'eta' e' un numero.", "Rating is": "- La valutazione e'...", "to arrive you.": "per raggiungerti.", "Order History": "Registra cronologia ordini", "My Wallet": "Dov'è il mio portafogli?", "Tariff": "tariffa", "Settings": "& Impostazioni", "Feed Back": "Riflessi?", "Promos": "PROMOZIONI", "Please enter a valid 16-digit card number": "Inserisci un numero di ordine d'acquisto valido.", "Add Phone": "Telefono", "Please enter a phone number": "Inserisci il numero di telefono", "You dont Add Emergency Phone Yet!": "Non hai ancora aggiunto un telefono di emergenza!", "You will arrive to your destination after": "Arriverai a destinazione dopo", "You can cancel Ride now": "Ora puoi cancellare la corsa", "You Can cancel Ride After Captain did not come in the time": "Puoi cancellare la corsa dopo che il capitano non è arrivato in tempo", "If you in Car Now. Press Start The Ride": "Se sei in macchina in questo momento. Tocca Inizia corsa.", "You Dont Have Any amount in": "Non hai alcun importo in", "Wallet!": "Il portafoglio.", "You Have": "Ce l'avevi tu!", "Save Credit Card": "Conserva carta di credito", "Show Promos": "Offerte", "10 and get 4% discount": "10 e ottieni il 4% di sconto", "20 and get 6% discount": "20 e ottieni il 6% di sconto", "40 and get 8% discount": "40 e ottieni l'8% di sconto", "100 and get 11% discount": "100% e 11% di sconto", "Pay with Your PayPal": "Paga con PayPal", "You will choose one of above !": "Sceglierai una delle opzioni di cui sopra!", "Cancel": "Annullare", "Delete My Account": "Elimina il mio account", "Edit Profile": "Modifier le profil", "Name": "Nom", "Update Gender": "Mettre à jour le sexe", "Education": "Les études", "Update Education": ":: Moderniser l'enseignement;", "Employment Type": "Catégorie de personnel", "SOS Phone": "Mobile", "High School Diploma": "BACCALAUREAT DE L'ENSEIGNEMENT", "Associate Degree": "Diplôme conjoint", "Bachelor's Degree": "Grade de bachelier", "Master's Degree": "Master", "Doctoral Degree": "Docteur en philosophie.", "Promos For today": "Promotions", "Copy this Promo to use it in your Ride!": "Copiez cette promotion pour l'utiliser lors de votre voyage !", "To change some Settings": "Pour modifier certains paramètres", "To change Language the App": "Pour modifier la langue de l'application", "Order Request Page": "Page de demande de commande", "Rouats of Trip": "Tripp.", "Passenger Name is": "Voyageur.", "Total From Passenger is": "Le total du passager est", "Duration To Passenger is": "Durée jusqu'au passager", "Distance To Passenger is": "distance par rapport au passager est", "Total For You is": "Le total pour vous est de", "Distance is": "Distance", "KM": "Km", "Duration of Trip is": "La durée de la course est de", "Minutes": "Minutes", "Apply Order": "Appliquer la commande", "Refuse Order": "- Demande rejetée.", "Rate Captain": "Cote de capitaine", "Enter your Note": "J'ai eu votre mot.", "Type something...": "Écrire quelque chose...", "Submit rating": "Fournir une évaluation", "Rate Passenger": "Note du passager", "Ride Summary": "Résumé de la course", "welcome_message": "Insérer « & #160; Bonjour monde & #160; »", "app_description": "ApplicationDescription", "get_to_destination": "Destination atteinte. Déblocage des contrôles manuels.", "get_a_ride": "Commandez une course", "safe_and_comfortable": "Sûr et confortable", "committed_to_safety": "Engagé pour la sécurité", "Driver Applied the Ride for You": "Un chauffeur qui a effectué la course pour vous", "Show latest promo": "Afficher la dernière promotion", "Cancel Trip": "Le vol est annulé.", "Passenger Cancel Trip": "Le passager annule la course", "Please stay on the picked point.": "Veuillez rester au point sélectionné.", "Trip is Begin": "Votre initiation a commencé.", "Hi ,I will go now": "Bonjour, j'y vais maintenant", "Passenger come to you": "Votre passager vient vous voir", "Hi ,I Arrive your site": "Bonjour, vous avez atteint votre position.", "Driver Finish Trip": "Fin de la course du chauffeur", "you will pay to Driver": "Sérieux ? Probablement avec mon argent.", "Driver Cancel Your Trip": "Annulez votre course, chauffeur.", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Vous paierez le chauffeur Vous paierez le coût du temps du chauffeur Regardez votre portefeuille Intaleq", "I will go now": "- J'y vais.", "You Have Tips": "Astuces", "tips": "Des paroles sages ?", "Total is": "Chiffre total est de 15", "No,I want": "- Je n'en ai pas envie.", "Your fee is": "Vos frais sont de", "Do you want to pay Tips for this Driver": "Souhaitez-vous laisser un pourboire à ce chauffeur ?", "Tip is": "Monconseil", "Camera Access Denied.": "Accès à la caméra refusé.", "Open Settings": "|||UNTRANSLATED_CONTENT_START|||افتح الإعدادات|||UNTRANSLATED_CONTENT_END|||", "GPS Required Allow !.": "Le GPS doit être activé !", "Your Account is Deleted": "Votre compte a été supprimé", "Are you sure to delete your account?": "Voulez-vous vraiment supprimer votre compte ?", "Your data will be erased after 2 weeks": "Vos données seront effacées après 2 semaines", "And you will can't return to use app after 1 month": "Vous pourrez revenir à l'application après un mois", "Enter Your First Name": "Saisissez votre nom", "Are you Sure to LogOut?": "Voulez-vous vraiment vous déconnecter?", "Email Wrong": "Email ", "Email you inserted is Wrong.": "L'adresse e-mail que vous avez saisie est incorrecte.", "You have finished all times": "J'en ai assez !", "if you want help you can email us here": "Si vous souhaitez de l'aide, vous pouvez nous envoyer un e-mail ici", "Thanks": "Merci.", "Email Us": "Envoyez-nous un e-mail", "I cant register in your app in face detection": "Je ne peux pas m'inscrire à votre application avec la détection de visage", "Hi": "-C'est un plaisir. -Hello.", "No face detected": "Aucun scanner n'a été détécté", "Image detecting result is": "Le résultat de la détection d'image est", "from 3 times Take Attention": "que 3 fois attirent votre attention", "Be sure for take accurate images please": "Assurez-vous de prendre des photos précises s'il vous plaît", "You have": "- Euh...", "image verified": "La photo est notariée", "Next": "Suivant", "There is no help Question here": "Ouais, pas d'aide ici.", "Call End": "Terminer l'appel", "You dont have Points": "- Vous n'avez pas...", "You Are Stopped For this Day !": "Vous avez été mis en pause pour la journée !", "You must be charge your Account": "Vous devez recharger votre compte", "You Refused 3 Rides this Day that is the reason": "Vous avez refusé 3 courses aujourd'hui et c'est pourquoi", "See you Tomorrow!": "Je te verrais demain.", "Recharge my Account": "Recharger mon compte", "Ok , See you Tomorrow": "D'accord, on se voit demain.", "You are Stopped": "Vous êtes arrêté", "Connected": "Online", "Not Connected": "Offiline", "Your are far from passenger location": "Vous êtes loin de l'emplacement des passagers", "go to your passenger location before": "Accédez à l'emplacement de votre passager avant le", "Passenger cancel trip": "Le passager a annulé la course", "You will get cost of your work for this trip": "Vous obtiendrez le coût de votre entreprise pour cette course", "in your wallet": "Elle est dans ton portefeuille.", "you gain": "Vous gagnerez", "Order Cancelled": "Commande annulée", "Order Cancelled by Passenger": "Demande annulée par le passager", "Success": "Je l'ai.", "Feedback data saved successfully": "Données d'évaluation enregistrées avec succès", "No Promo for today .": "Pas de promotion pour aujourd'hui.", "Select your destination": "Sélectionnez la destination;", "Search for your Start point": "Trouvez votre point de départ", "Search for waypoint": "Rechercher un point WIPOINT", "Current Location": "Utiliser la position actuelle", "Add Location 1": "Emplacement & #160;: %1", "You must Verify email !.": "Relever le courriel", "Cropper": "Récolte", "Saved Sucssefully": "Bien reçu.", "Select Date": "Choisir une nouvelle date", "Birth Date": "Date de naissance", "Ok": "D'accord.", "the 500 points equal 30 JOD": "500 points équivaut à 30 JOD", "the 500 points equal 30 JOD for you": "500 points équivaut à 30 JOD pour vous", "token updated": "Code mis à jour", "Add Location 2": "Ajouter un emplacement 2", "Add Location 3": "Ajouter un emplacement 3", "Add Location 4": "Ajouter un emplacement 4", "Waiting for your location": "En attente de votre localisation", "Search for your destination": "Trouvez votre destination", "Hi! This is": "Bienvenue \"moi\": c' est ça.", "I am using": "Du matériel que j'utilisais.", "to ride with": "pour rouler avec", "as the driver.": "On dirait un chauffeur.", "is driving a": "- Je vais le tenter comme ça. - Conduire.", "with license plate": "Avec une plaque d'immatriculation", "I am currently located at": "Je suis actuellement en", "Please go to Car now": "S'il te plaît, va-t-en maintenant.", "If you need to reach me, please contact the driver directly at": "Si vous avez besoin de me joindre, veuillez contacter directement le chauffeur au", "No Car or Driver Found in your area.": "Aucune voiture ou chauffeur trouvé dans votre région.", "Please Try anther time": "Réessayer", "There no Driver Aplly your order sorry for that": "Aucun chauffeur ne peut répondre à votre demande, nous sommes désolés.", "Trip Cancelled": "Course annulée", "The Driver Will be in your location soon .": "Votre chauffeur arrivera bientôt chez vous.", "The distance less than 500 meter.": "La distance est inférieure à 500 mètres.", "Promo End !": "- C'est seulement jusqu'au spectacle.", "There is no notification yet": "Aucune notification pour le moment", "Use Touch ID or Face ID to confirm payment": "Utilisez Touch ID ou Face ID pour confirmer le paiement", "Contact us for any questions on your order.": "Contactez-nous pour toute question concernant votre commande.", "Pyament Cancelled .": "Le paiement a été annulé.", "type here": "Tapez ici", "Scan Driver License": "Permis de conduire", "Please put your licence in these border": "Veuillez placer votre licence dans ces limites", "Camera not initialized yet": "Caméra pas encore configurée", "Take Image": "Prends une photo, parce que demain matin, ces lettres partiront.", "AI Page": "Tu dis que ton système \"IA\"", "Take Picture Of ID Card": "Prenez une photo de votre pièce d'identité", "Take Picture Of Driver License Card": "Prenez une photo de votre permis de conduire.", "We are process picture please wait": "Nous traitons les images, veuillez patienter.", "There is no data yet.": "Aucune donnée trouvée", "Name :": "Nom :", "Drivers License Class:": "Catégorie de permis de conduire :", "Document Number:": "Numéro du document", "Address:": "Adresse:", "Height:": "& Hauteur & #160;:", "Expiry Date:": "Expiration & #160;:", "Date of Birth:": "Anniversaire & #160;: @title: group", "You can't continue with us .": "Ça ne peut pas durer.", "You should renew Driver license": "Vous devez renouveler votre permis de conduire", "Detect Your Face": "Découvrez votre visage", "Go to next step": "\"", "scan Car License.": "Vérification de l'immatriculation du véhicule.", "Name in arabic": "Full Name AR", "Drivers License Class": "Permis de conduire", "Date of Birth": "Date de naissance", "Age": "l’âge", "Lets check Car license": "Vérifions le permis de conduire", "Car Kind": "Type de véhicule", "Car Plate": "Le numéro d'immatriculation ?", "Lets check License Back Face": "Vérifions la licence de face arrière", "Car License Card": "Carte d'immatriculation du véhicule", "No image selected yet": "Aucune photo sélectionnée pour le moment", "Made :": "Make", "model :": "Mod.", "VIN :": "Structure :", "year :": "Année", "ُExpire Date": "Date d'expiration", "Login Driver": "Se connecter", "Password must br at least 6 character.": "Le mot de passe doit comporter au moins 6 caractères.", "if you don't have account": "Que voulez-vous dire ?", "Here recorded trips audio": "Voici les enregistrements audio du voyage", "Register as Driver": "Inscrivez-vous en tant que chauffeur", "Privacy Notice": "Avis de confidentialité", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "En sélectionnant « J'accepte » ci-dessous, j'ai lu, j'accepte et j'accepte les conditions générales", ". I am at least 18 years of age.": ". J'ai au moins 18 ans.", "Log Out Page": "Se Déconnecter", "Log Off": "Signe.", "Register Driver": "Le chauffeur...", "Verify Email For Driver": "Consultez l'e-mail du chauffeur", "Admin DashBoard": "Tableau de bord d'administration", "Your name": "Ton... nom.", "your ride is applied": "Votre course a été appliquée", "Your password": "Renouveler votre mot de passe", "LE": "Livre égyptienne", "JOD": "Monnaie: Dinar jordanien", "m": "%1 km", "We search nearst Driver to you": "Nous recherchons le chauffeur le plus proche", "please wait till driver accept your order": "Veuillez attendre que le chauffeur accepte votre demande", "No accepted orders? Try raising your trip fee to attract riders.": "Aucune Essayez d'augmenter les frais de course pour attirer des passagers.", "You should select one": "Vous devez en choisir un", "The driver accept your order for": "Votre chauffeur a accepté votre demande de", "Increase Fee": "Augmenter les frais", "No, thanks": "Non merci", "The driver on your way": "Votre chauffeur est en route", "Total price from": "P.T", "Order Details Intaleq": "Détails du commande", "Order Applied": "Commande appliquée", "accepted your order": "- Retenue.", "We regret to inform you that another driver has accepted this order.": "Nous sommes désolés de vous informer qu'un autre chauffeur a accepté cette demande.", "Selected file:": "Ouvre un fichier existant", "Your trip cost is": "Les frais de votre course", "this will delete all files from your device": "Cela supprimera tous les fichiers de votre appareil", "you have a negative balance of": "Vous avez un solde négatif de", "in your": "En toi.", "Exclusive offers and discounts always with the Intaleq app": "Offres exclusives et réductions toujours avec l'application de voyage", "Please go to Car Driver": "Veuillez vous rendre chez le conducteur de la voiture", "wallet due to a previous trip.": "Portefeuille en raison d'une course précédente.", "Submit Question": "Envoyer la question", "Please enter your Question.": "Veuillez saisir votre question.", "Help Details": "Détails de l'aide", "No trip yet found": "Aucune campagne trouvée", "No Response yet.": "Il n'y a pas de réponses.", "You Earn today is": "- On est euh...", "You Have in": "Vous avez à", "Total points is": "Le score total est de", "Total Connection Duration:": "Durée totale de connexion :", "H and": "H et", "Passenger name :": "Le voyageur.", "Cost Of Trip IS": "Coûts des vols par avion spécial", "Arrival time": "On arrive dans 7 minutes.", "arrival time to reach your point": "Heure d'arrivée pour atteindre votre destination", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Pour les courses et livraisons rapides, le prix est calculé de manière dynamique. Pour des courses confortables, le prix est basé sur la durée et la distance.", "Hello this is Driver": "Bonjour, je suis le chauffeur", "Is the Passenger in your Car ?": "Le passager est-il dans votre véhicule ?", "Please wait for the passenger to enter the car before starting the trip.": "Veuillez attendre que le passager entre dans le véhicule avant de commencer la course.", "No ,still Waiting.": "Non , je t'attends toujours.", "I arrive you": "Elle t'a eue.", "I Arrive your site": "Elle t'a eue.", "You are not in near to passenger location": "Vous n'êtes pas près de l'emplacement du passager", "please go to picker location exactly": "Veuillez vous rendre à l'emplacement exact de la sélection", "You Can Cancel Trip And get Cost of Trip From": "Vous pouvez annuler la course et obtenir le coût de la course auprès de", "Are you sure to cancel?": "Voulez-vous vraiment annuler ?", "Yes": "Oui", "Insert Emergincy Number": "Saisir le numéro d'urgence", "Best choice for comfort car and flexible route and stops point": "Le meilleur choix pour une voiture confortable, un itinéraire flexible et un point d'arrêt", "Insert": "En cours d' utilisation", "This is for delivery or a motorcycle.": "C'est pour la livraison ou une moto.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "Cette course va directement de votre point de départ à votre destination pour un tarif forfaitaire. Le chauffeur doit suivre l'itinéraire prévu", "You can decline a request without any cost": "Vous pouvez refuser la demande sans frais", "Perfect for adventure seekers who want to experience something new and exciting": "Idéal pour les chercheurs d'aventure qui veulent essayer quelque chose de nouveau et d'excitant", "My current location is:": "Mon emplacement actuel est :", "and I have a trip on": "et j'ai un voyage à", "App with Passenger": "Postuler avec le passager", "You will be pay the cost to driver or we will get it from you on next trip": "Le coût sera payé au chauffeur ou nous l'obtiendrons de votre part lors de la prochaine course", "Trip has Steps": "La course comporte des étapes", "Distance from Passenger to destination is": "La distance entre le passager et la destination est", "price is": "C'est cent dollars.", "This ride type does not allow changes to the destination or additional stops": "Ce type de course ne permet pas de modifier la destination ou d'effectuer des arrêts supplémentaires", "This price may be changed": "Ce prix peut changer", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "Pas de carte SIM, pas de problème ! Contactez directement votre chauffeur via notre application. Nous utilisons une technologie de pointe pour garantir votre confidentialité.", "This ride type allows changes, but the price may increase": "Ce type de course peut être modifié, mais le prix peut augmenter", "message From passenger": "Estafette.", "Select one message": "Message un.", "My location is correct. You can search for me using the navigation app": "Ma position est correcte. Vous pouvez me rechercher à l'aide de l'application de navigation", "I'm waiting for you": "- Quand vous voulez.", "Hello, I'm at the agreed-upon location": "Bonjour, je suis à l'endroit convenu", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "Nous avons remarqué que la vitesse dépasse 100 km/h. Veuillez ralentir pour votre propre sécurité. Si vous ne vous sentez pas en sécurité, vous pouvez communiquer les détails de votre course à un contact ou appeler la police à l'aide du bouton de détresse rouge.", "Warning: Intaleqing detected!": "Avertissement : survitesse détectée !", "Please help! Contact me as soon as possible.": "Aide-moi s'il te plaît. Contactez-moi dès que possible.", "Share Trip Details": "Partagez les détails de la", "Car Plate is": "Le numéro d'immatriculation ?", "the 3000 points equal 3000 L.E for you": "3000 points équivaut à 3000 EGP pour vous", "So go and gain your money": "Gagnez de l'argent", "the 3000 points equal 3000 L.E": "3000 points équivaut à 3000 EGP", "The payment was not approved. Please try again.": "Paiement non approuvé. Réessayer", "Payment Failed": "Échec du paiement", "Error": "ⵜⴰⵣⴳⵍⵜ", "An error occurred during the payment process.": "Une erreur s'est produite lors de votre paiement.", "The payment was approved.": "Paiement approuvé.", "Payment Successful": "Paiement réussi", "No ride found yet": "Aucune campagne trouvée", "Accept Order": "Commande acceptée", "reject your order.": "Votre Ordre.", "Bottom Bar Example": "Exemple de barre inférieure", "Driver phone": "Téléphone du chauffeur", "Statistics": "& Statistiques", "Origin": "ORIGINE", "Destination": "- Destination ?", "Driver Name": "Nom de pilote & #160;:", "Driver Car Plate": "Plaque d'immatriculation du conducteur", "Available for rides": "Disponible pour les courses", "Scan Id": "Contrôle d'identité", "Camera not initilaized yet": "Caméra pas encore configurée", "Scan ID MklGoogle": "Vérification d'identité MklGoogle", "Language": "Langue ", "Jordan": "Jordanie", "USA": "Etats Unis d'Amérique", "Egypt": "Egypte", "Turkey": "Turquie", "Saudi Arabia": "Arabie Saoudite", "Qatar": "Qatar", "Bahrain": "Bahreïn", "Kuwait": "Koweït", "But you have a negative salary of": "Mais vous avez un salaire négatif de", "Promo Code": "Code promo", "Your trip distance is": "La distance de votre course est de", "Enter promo code": "Code promo", "You have promo!": "Vous avez une promotion !", "Cost Duration": "Durée du coût", "Duration is": "La durée est", "Leave": "Quitter", "Join": "Joindre", "You Should be select reason.": "Vous devez choisir une raison.", "\$": "\$", "Waiting for Driver ...": "En attente du chauffeur ...", "Latest Recent Trip": "J'ai des choses à faire!", "from your list": "À partir de votre liste", "Do you want to change Work location": "Souhaitez-vous changer de lieu de travail ?", "Do you want to change Home location": "Souhaitez-vous changer l'emplacement de la maison", "We Are Sorry That we dont have cars in your Location!": "Nous sommes désolés que les voitures ne soient pas disponibles chez vous !", "Choose from Map": "Sélectionner sur la carte", "Pick your ride location on the map - Tap to confirm": "Sélectionnez votre lieu de prise en charge sur la carte - appuyez pour confirmer", "To Work": "Pour le boulot", "Are you want to go this site": "Voulez-vous aller à cet endroit", "Closest & Cheapest": "Le plus proche et le moins cher", "Work Saved": "Enregistré :", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq est une application de covoiturage sûre, fiable et accessible.", "With Intaleq, you can get a ride to your destination in minutes.": "En voyageant, vous pouvez vous rendre à destination en quelques minutes.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Safar s'engage pour la sécurité, et tous nos commandants sont soigneusement contrôlés et leurs antécédents vérifiés.", "To Home": "RETOUR À LA PAGE D'ACCUEIL", "Home Saved": "Enregistré :", "Destination selected": "Destination sélectionnée", "Now select start pick": "Maintenant, choisissez Démarrer la sélection", "Pick from map": "Sélectionner sur la carte", "Click here point": "Cliquez ici", "No Car in your site. Sorry!": "Il n'y a pas de voiture dans votre région. Ex... Excusez moi.", "Nearest Car for you about": "La voiture la plus proche de chez vous est d'environ", "N/A": "Aucune information", "From :": "Du :", "Get Details of Trip": "Obtenir les détails de la course", "If you want add stop click here": "Si vous souhaitez ajouter un arrêt, cliquez ici", "Driver": "ⴰⵎⵏⴷⴰⵀ", "Where you want go": "D'où viens-tu ?", "My Card": "Ma carte.", "Start Record": "Début de la campagne d'enregistrement", "Wallet": "Un portefeuille.", "History of Trip": "2.1 Histoire du vol", "Helping Center": "Centre d'aide", "Record saved": "Sauvegarde de l'historique effectuée !", "Trips recorded": "Voyages enregistrés", "Select Your Country": "Selectionnez votre pays", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "Pour vous assurer d'avoir les informations les plus précises pour votre emplacement, veuillez sélectionner votre pays ci-dessous. Cela vous aidera à personnaliser l'expérience et le contenu de l'application pour votre pays.", "Are you sure to delete recorded files": "Êtes-vous sûr de vouloir supprimer les fichiers enregistrés", "Select recorded trip": "Choisissez une course enregistrée", "Card Number": "N  de pièce d'identité:", "Hi, Where to": "Bonjour, oùallez-vous ?", "Pick your destination from Map": "Sélectionner sur la carte", "Add Stops": "Ajouter des arrêts", "Get Direction": "Obtenir une direction", "Add Location": "Ajouter l'emplacement correctement", "Switch Rider": "Changer de passager", "You will arrive to your destination after timer end.": "Vous arriverez à destination après l'expiration de la minuterie.", "You can cancel trip": "Vous pouvez annuler la course", "The driver waitting you in picked location .": "Votre chauffeur vous attend à l'endroit désigné .", "Pay with Your": "Payer avec", "Pay with Credit Card": "- La carte.", "Payment History": "Historique des paiements", "Show Promos to Charge": "Afficher les promotions d'expédition", "Point": "Points", "Driver Balance": "Portefeuille chauffeur", "Total Points is": "Le score total est de", "Total Budget from trips is": "Le budget total des voyages est de", "Total Amount:": "Montant total", "Total Budget from trips by": "Budget total des voyages par", "Credit card is": "Votre carte de crédit.", "This amount for all trip I get from Passengers": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers.", "Pay from my budget": "Payer sur mon budget", "This amount for all trip I get from Passengers and Collected For me in": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers collectés pour moi à", "You can buy points from your budget": "Vous pouvez acheter des points à partir de votre budget", "insert amount": "Entrez le montant", "You can buy Points to let you online": "Vous pouvez acheter des points pour vous permettre d'accéder en ligne", "by this list below": "Grâce à cette liste ci-dessous", "Create Wallet to receive your money": "Créez un portefeuille pour recevoir votre argent", "Enter your feedback here": "Saisissez vos commentaires ici", "Please enter your feedback.": "Veuillez saisir le texte de vos notes", "Feedback": "Feedback:", "Click here to Show it in Map": "Cliquez ici pour le voir sur la carte", "Canceled": "Annulé", "Type your Email": "Votre e-mail", "No I want": "- Je n'en ai pas envie.", "Email is": "Email ", "Phone Number is": "C'est le 92.38.09.06.", "Date of Birth is": "Année de naissance", "Sex is": "Le sexe est cardio.", "Car Details": "Détails du véhicule", "VIN is": "Structure", "Color is": "- Sa couleur?", "Make is": "Make is", "Model is": "Formulaire de :", "Year is": "Année", "Edit Your data": "Modifiez vos informations", "write vin for your car": "Notez le numéro de châssis de votre véhicule", "VIN": "|||UNTRANSLATED_CONTENT_START|||رقم هيكل السيارة|||UNTRANSLATED_CONTENT_END|||", "write Color for your car": "Tapez la couleur de votre voiture", "write Make for your car": "Écrivez une marque pour votre voiture", "write Model for your car": "Tapez votre modèle de voiture", "write Year for your car": "Saisissez une année pour votre voiture", "write Expiration Date for your car": "la date de péremption", "Tariffs": "Définitions ", "Minimum fare": "Prix minimum", "Maximum fare": "Prix maximum", "Flag-down fee": "Frais d'escale", "Including Tax": "Incluant...", "BookingFee": "Frais de réservation", "Morning": "- Bonjour.", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07h30 - 10h30 (jeudi, vendredi, samedi, lundi)", "Evening": "- Bonsoir.", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12h00 - 15h00 (jeudi, vendredi, samedi, lundi)", "Night": "la nuit", "You have in account": "Vous avez dans le compte", "Select Country": "Sélectionner un pays.", "Ride Today :": "Commandez une course aujourd'hui :", "After this period": "Après cette période", "You can't cancel!": "- Vous pouvez plus...", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "Le chauffeur...", "Total Cost is": "Coût total", "Write note": "J'écris une lettre de menace.", "Time to arrive": "Bobby, Qu'elle est notre e. t. a.?", "Ride Summaries": "Résumés des courses", "Total Cost": "Coût total", "Average of Hours of": "Nombre moyen d'heures de travail", "is ON for this month": "En cours ce mois-ci", "Days": "Quelques mois, semaines... quelques jours.", "Total Hours on month": "Nombre total d'heures", "Counts of Hours on days": "Heures en jours", "OrderId": "Commande N°", "created time": "Date de création", "Intaleq Over": "Et c'est là qu'on l'aura.", "I will slow down": "Je vais ralentir.", "Map Passenger": "Carte du passager", "Be Slowly": "Soyez lent", "If you want to make Google Map App run directly when you apply order": "Si vous souhaitez lancer Google Maps directement lorsque vous appliquez la commande", "You can change the language of the app": "Vous pouvez modifier la langue de l'application", "Your Budget less than needed": "Votre budget est sous-estimé", "You can change the Country to get all features": "Vous pouvez modifier le pays pour obtenir toutes les fonctionnalités", "Change Country": "Non-pays" }, "ru": { "Order": "Заказ", "OrderVIP": "VIP Заказ", "Cancel Trip": "Отменить поездку", "Passenger Cancel Trip": "Пассажир отменил поездку", "VIP Order": "VIP Заказ", "The driver accepted your trip": "Водитель принял вашу поездку", "message From passenger": "Сообщение от пассажира", "Cancel": "Отмена", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Поездка отменена. Стоимость поездки будет добавлена в ваш кошелек.", "token change": "изменение токена", "face detect": "распознавание лица", "Face Detection Result": "Результат распознавания лица", "similar": "похожий", "not similar": "не похожий", "Hi ,I will go now": "Привет, я сейчас поеду", "Passenger come to you": "Пассажир идет к вам", "Call Income": "Входящий звонок", "Call Income from Passenger": "Входящий звонок от пассажира", "Criminal Document Required": "Требуется справка о несудимости", "You should have upload it .": "Вы должны были загрузить его.", "Call End": "Завершение звонка", "The order has been accepted by another driver.": "Заказ принят другим водителем.", "The order Accepted by another Driver": "Заказ принят другим водителем", "We regret to inform you that another driver has accepted this order.": "К сожалению, другой водитель принял этот заказ.", "Driver Applied the Ride for You": "Водитель подал заявку на поездку для вас", "Applied": "Применено", "Hi ,I Arrive your site": "Привет, я прибыл на ваше место", "Please go to Car Driver": "Пожалуйста, подойдите к водителю автомобиля", "Ok I will go now.": "Хорошо, я сейчас пойду.", "Accepted Ride": "Поездка принята", "Driver Accepted the Ride for You": "Водитель принял поездку для вас", "Promo": "Промо", "Show latest promo": "Показать последнее промо", "Trip Monitoring": "Мониторинг поездки", "Driver Is Going To Passenger": "Водитель едет к пассажиру", "Please stay on the picked point.": "Пожалуйста, оставайтесь в выбранной точке.", "message From Driver": "Сообщение от водителя", "Trip is Begin": "Поездка началась", "Cancel Trip from driver": "Отмена поездки водителем", "We will look for a new driver.\nPlease wait.": "Мы поищем нового водителя.\nПожалуйста, подождите.", "The driver canceled your ride.": "Водитель отменил вашу поездку.", "Driver Finish Trip": "Водитель завершил поездку", "you will pay to Driver": "вы заплатите водителю", "Don’t forget your personal belongings.": "Не забудьте свои личные вещи.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Пожалуйста, убедитесь, что у вас есть все ваши личные вещи и что любая оставшаяся плата, если таковая имеется, была добавлена в ваш кошелек перед уходом. Спасибо за выбор приложения Intaleq", "Finish Monitor": "Завершить мониторинг", "Trip finished": "Поездка завершена", "Call Income from Driver": "Входящий звонок от водителя", "Driver Cancelled Your Trip": "Водитель отменил вашу поездку", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "вы заплатите водителю, вы оплатите стоимость времени водителя, посмотрите в своем кошельке Intaleq", "Order Applied": "Заказ применен", // firebase "registration_date": "Дата регистрации", "expiration_date": "banners|Дата окончания показа", "rating_count": "Количество оценок", "rating_driver": "Рейтинг водителя", "age": "Возраст", "vin": "VIN", "car_color": "Цвет", "car_plate": "Номерной знак", "car_model": "Модель автомобиля:", "education": "образование", "gender": "Пол", "birthdate": "Дата рождения", "Approve Driver Documents": "Утвердить документы водителя", "Total Budget is": "Общий бюджет", "You will recieve code in sms message": "Вы получите код в SMS", "Please enter": "dynprops|Укажите название", "We need your phone number to contact you and to help you receive orders.": "Нам нужен ваш номер телефона, чтобы связаться с вами и помочь вам получать заказы.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "Полное имя в вашей судимости не совпадает с именем в водительских правах. Пожалуйста, проверьте и предоставьте правильные документы.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "Национальный номер в водительском удостоверении не совпадает с номером в удостоверении личности. Пожалуйста, проверьте и предоставьте правильные документы.", "Capture an Image of Your Criminal Record": "Сфотографируйте свою судимость", "IssueDate": "Дата выдачи", "Capture an Image of Your car license front": "Сфотографируйте водительские права спереди", "Capture an Image of Your ID Document front": "Сфотографируйте удостоверение личности спереди", "NationalID": "Национальный идентификатор:", "FullName": "full name", "InspectionResult": "Результат осмотра", "Criminal Record": "Судимость", "The email or phone number is already registered.": "Электронная почта или номер телефона уже зарегистрированы.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "Чтобы стать водителем-партнером в приложении для путешествий, загрузите водительские права, документ, удостоверяющий личность, и документ о регистрации транспортного средства. Наша система искусственного интеллекта немедленно рассмотрит и проверит ее подлинность всего за 2-3 минуты. Если документы будут одобрены, вы сможете стать водителем-партнером в приложении для путешествий. Обратите внимание, что предоставление поддельных документов является серьезным преступлением и может привести к немедленному расторжению и юридическим последствиям.", "Documents check": "Проверка документов", "Driver's License": "Водительские права", "License Type": "Тип лицензии", "National Number": "Национальный номер", "Name (Arabic)": "Наименование", "Name (English)": "Английский", "Address": "Адрес", "Issue Date": "Дата выдачи", "Expiry Date": "Дата истечения срока действия", "License Categories": "Категории лицензий", "driver_license": "Водительские права", "Capture an Image of Your Driver License": "Сфотографируйте водительские права", "ID Documents Back": "Оборудование для изготовления удостоверений личности", "National ID": ":: национальная идентичность;", "Occupation": "Профессия", "Gender": "Пол", "Religion": "Религия", "Marital Status": "Семейное положение", "Full Name (Marital)": "(расшифровка подписи)", "Expiration Date": "banners|Дата окончания показа", "Capture an Image of Your ID Document Back": "Сфотографируйте оборотную сторону удостоверения личности", "ID Documents Front": "Лицевая сторона документов, удостоверяющих личность", "First Name": "Имя:", "CardID": "Сфотографируйте оборотную сторону удостоверения личности", "Full Name": "full name", "Vehicle Details Front": "Сведения о переднем транспортном средстве", "Plate Number": "Номерной знак", "Owner Name": "Имя владельца", "Vehicle Details Back": "Сведения об автомобиле снова", "Make": "Марка", "Model": "Модель автомобиля:", "Year": "год", "Chassis": "Шасси", "Color": "Цвет", "Displacement": "Замена", "Fuel": "Горючее", "Tax Expiry Date": "Дата истечения срока действия", "Inspection Date": "Дата Обследования", "Capture an Image of Your car license back": "Сфотографируйте водительские права еще раз", "Capture an Image of Your Driver’s License": "Сфотографируйте водительские права", "Sign in with Google for easier email and name entry": "Войдите в систему с помощью Google, чтобы упростить ввод адреса электронной почты и имени", "You will choose allow all the time to be ready receive orders": "Вы будете разрешать готовые заказы все время", "Welcome to Intaleq!": "Добро пожаловать в Safar!", "Get to your destination quickly and easily.": "Быстро и легко добирайтесь до места назначения.", "Enjoy a safe and comfortable ride.": "Безопасная и комфортная поездка.", "Choose Language": "Выбрать", "Login": "Войти", "Pay with Wallet": "Оплатить с помощью кошелька", "Invalid MPIN": "Неверный MPIN-код", "Invalid OTP": "Неверный код подтверждения", "Enter your email address": "Email", "Please enter Your Email.": "Пожалуйста, введите...", "Enter your phone number": "Введите номер телефона", "Please enter your phone number.": "Введите номер телефона.", "Please enter Your Password.": "Введите пароль", "Submit": " Отправка ", "if you dont have account": "Если у вас нет аккаунта", "Register": "записать", "Accept Ride's Terms & Review Privacy Notice": "Примите условия поездки и ознакомьтесь с Заявлением о конфиденциальности", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "Нажимая «Я согласен (-на)» ниже, я подтверждаю, что ознакомился (-ась) и принимаю Условия использования, а также Уведомление о конфиденциальности.Мне не менее 18 лет.", "I Agree": "Согласиться", "First name": "Имя:", "Enter your first name": "Введите имя", "Please enter your first name.": "Пожалуйста, введите ваше имя.", "Last name": "Фамилия", "Enter your last name": "(фамилия)", "Please enter your last name.": "Пожалуйста, введите ваше имя.", "City": "Город", "Please enter your City.": "Пожалуйста, введите...", "Male": "Муж.", "Female": "Самка", "Verify Email": "Подтвердить адрес электронной почты", "We sent 5 digit to your Email provided": "Мы отправили 5 цифр на указанный вами адрес электронной почты", "5 digit": "PIN-код(5-значный)", "Send Verification Code": "Код подтверждения", "Your Ride Duration is": "Продолжительность поездки:", "You will be thier in": "Вы получите их в", "You trip distance is": "Расстояние поездки:", "Fee is": "Сбор составляет", "To :": "Действительна до", "Add Promo": "Добавить промокод", "Confirm Selection": "Подтвердить выбор", "distance is": "Расстояние составляет", "duration is": "Продолжительность составляет", "I don't need a ride anymore": "Меня больше не нужно подвозить", "I was just trying the application": "Я только что опробовал приложение", "No driver accepted my request": "Ни один водитель не принял мой заказ", "I added the wrong pick-up/drop-off location": "Вы указали неправильное место посадки/высадки", "I don't have a reason": "У меня нет причин", "Other": "Прочее", "Can we know why you want to cancel Ride ?": "Почему вы хотите отменить поездку?", "Cancel Ride": "Отменить", "Add Payment Method": "Добавить способ оплаты", "Your Wallet balance is": "Баланс вашего кошелька", "Ride Wallet": "Кошелек для поездок", "Payment Method": "Форма расчетов", "Type here Place": "Введите здесь место", "Are You sure to ride to": "Вы уверены, что хотите совершить поездку в", "Confirm": "Подтверждения", "Back": "Назад", "You are Delete": "Вы удаляете", "Deleted": "Удален", "You Dont Have Any places yet !": "У вас пока нет мест!", "Favorite Places": "Избранные места", "From : Current Location": "Текущее местоположение:", "Where to": "Где Аллах?", "Notifications": "Извещения", "Profile": "Профиль", "Home": "Главная страница ", "My Cared": "MyCurt", "Add Card": "Добавить карту", "Add Credit Card": "Добавить кредитную карту", "Please enter the cardholder name": "Введите имя владельца карты", "Please enter the expiry date": "Дата истечения срока аккредитива", "Please enter the CVV code": "Введите код подтверждения карты", "Go To Favorite Places": "Перейти к избранным местам", "Go to this Target": "Перейти к этой цели", "My Profile": "Профиль", "Sign Out": "Выйти", "Home Page": "Главная страница ", "Are you want to go to this site": "Вы хотите поехать в это место", "MyLocation": "Мое местоположение", "my location": "Мое местоположение", "Target": "Цель", "Update": "Модернизация", "You Should choose rate figure": "Вы должны выбрать правильный номер", "Login Captin": "bills|Логин", "Register Captin": "Регистрация капитана", "Send Verfication Code": "Отправить код подтверждения", "End Ride": "Поездка", "Minute": "Минута", "Go to passenger Location now": "Перейти к местоположению пользователя", "Duration of the Ride is": "Продолжительность поездки:", "Distance of the Ride is": "Расстояние поездки:", "Name of the Passenger is": "Имя пользователя Uber:", "Hello this is Captain": "Здравствуйте, я капитан", "Start the Ride": "Начать поездку", "Please Wait If passenger want To Cancel!": "Если пользователь хочет отменить поездку, подождите.", "Total Duration:": "Общая длительность", "Active Duration:": "Продолжительность активного шага", "Waiting for Captin ...": "В ожидании капитана ...", "Age is": "Возраст", "Rating is": "Целью оценки является:", "to arrive you.": "чтобы связаться с вами.", "Order History": "Записать историю заказов", "My Wallet": "Мой кошелек", "Tariff": "Тариф", "Settings": "spasibo", "Feed Back": "Обратная связь", "Promos": "Категория «Акции»", "Please enter a valid 16-digit card number": "Введите действительный номер заказа на закупку.", "Add Phone": "Телефон", "Please enter a phone number": "Введите номер телефона", "You dont Add Emergency Phone Yet!": "Вы еще не добавили телефон экстренной помощи!", "You will arrive to your destination after": "Вы прибудете в пункт назначения через", "You can cancel Ride now": "Вы можете отменить поездку прямо сейчас", "You Can cancel Ride After Captain did not come in the time": "Вы можете отменить поездку после того, как капитан не прибыл вовремя", "If you in Car Now. Press Start The Ride": "Если вы сейчас в машине. Нажмите Начать поездку.", "You Dont Have Any amount in": "У вас нет средств в", "Wallet!": "Wallet", "You Have": "Есть?", "Save Credit Card": "Сохранить кредитную карту", "Show Promos": "АКЦИИ", "10 and get 4% discount": "10 и получите скидку 4%", "20 and get 6% discount": "20 и получите скидку 6%", "40 and get 8% discount": "40 и получите скидку 8%", "100 and get 11% discount": "100% и получите скидку 11%", "Pay with Your PayPal": "Оплатить через PayPal", "You will choose one of above !": "Вы выберете один из вариантов выше!", "Cancel": "Отменить", "Delete My Account": "Удалить мой аккаунт", "Edit Profile": "Modifier le profil", "Name": "Nom", "Update Gender": "Mettre à jour le sexe", "Education": "Les études", "Update Education": ":: Moderniser l'enseignement;", "Employment Type": "Catégorie de personnel", "SOS Phone": "Mobile", "High School Diploma": "BACCALAUREAT DE L'ENSEIGNEMENT", "Associate Degree": "Diplôme conjoint", "Bachelor's Degree": "Grade de bachelier", "Master's Degree": "Master", "Doctoral Degree": "Docteur en philosophie.", "Promos For today": "Promotions", "Copy this Promo to use it in your Ride!": "Copiez cette promotion pour l'utiliser lors de votre voyage !", "To change some Settings": "Pour modifier certains paramètres", "To change Language the App": "Pour modifier la langue de l'application", "Order Request Page": "Page de demande de commande", "Rouats of Trip": "Tripp.", "Passenger Name is": "Voyageur.", "Total From Passenger is": "Le total du passager est", "Duration To Passenger is": "Durée jusqu'au passager", "Distance To Passenger is": "distance par rapport au passager est", "Total For You is": "Le total pour vous est de", "Distance is": "Distance", "KM": "Km", "Duration of Trip is": "La durée de la course est de", "Minutes": "Minutes", "Apply Order": "Appliquer la commande", "Refuse Order": "- Demande rejetée.", "Rate Captain": "Cote de capitaine", "Enter your Note": "J'ai eu votre mot.", "Type something...": "Écrire quelque chose...", "Submit rating": "Fournir une évaluation", "Rate Passenger": "Note du passager", "Ride Summary": "Résumé de la course", "welcome_message": "Insérer « & #160; Bonjour monde & #160; »", "app_description": "ApplicationDescription", "get_to_destination": "Destination atteinte. Déblocage des contrôles manuels.", "get_a_ride": "Commandez une course", "safe_and_comfortable": "Sûr et confortable", "committed_to_safety": "Engagé pour la sécurité", "Driver Applied the Ride for You": "Un chauffeur qui a effectué la course pour vous", "Show latest promo": "Afficher la dernière promotion", "Cancel Trip": "Le vol est annulé.", "Passenger Cancel Trip": "Le passager annule la course", "Please stay on the picked point.": "Veuillez rester au point sélectionné.", "Trip is Begin": "Votre initiation a commencé.", "Hi ,I will go now": "Bonjour, j'y vais maintenant", "Passenger come to you": "Votre passager vient vous voir", "Hi ,I Arrive your site": "Bonjour, vous avez atteint votre position.", "Driver Finish Trip": "Fin de la course du chauffeur", "you will pay to Driver": "Sérieux ? Probablement avec mon argent.", "Driver Cancel Your Trip": "Annulez votre course, chauffeur.", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Vous paierez le chauffeur Vous paierez le coût du temps du chauffeur Regardez votre portefeuille Intaleq", "I will go now": "- J'y vais.", "You Have Tips": "Astuces", "tips": "Des paroles sages ?", "Total is": "Chiffre total est de 15", "No,I want": "- Je n'en ai pas envie.", "Your fee is": "Vos frais sont de", "Do you want to pay Tips for this Driver": "Souhaitez-vous laisser un pourboire à ce chauffeur ?", "Tip is": "Monconseil", "Camera Access Denied.": "Accès à la caméra refusé.", "Open Settings": "|||UNTRANSLATED_CONTENT_START|||افتح الإعدادات|||UNTRANSLATED_CONTENT_END|||", "GPS Required Allow !.": "Le GPS doit être activé !", "Your Account is Deleted": "Votre compte a été supprimé", "Are you sure to delete your account?": "Voulez-vous vraiment supprimer votre compte ?", "Your data will be erased after 2 weeks": "Vos données seront effacées après 2 semaines", "And you will can't return to use app after 1 month": "Vous pourrez revenir à l'application après un mois", "Enter Your First Name": "Saisissez votre nom", "Are you Sure to LogOut?": "Voulez-vous vraiment vous déconnecter?", "Email Wrong": "Email ", "Email you inserted is Wrong.": "L'adresse e-mail que vous avez saisie est incorrecte.", "You have finished all times": "J'en ai assez !", "if you want help you can email us here": "Si vous souhaitez de l'aide, vous pouvez nous envoyer un e-mail ici", "Thanks": "Merci.", "Email Us": "Envoyez-nous un e-mail", "I cant register in your app in face detection": "Je ne peux pas m'inscrire à votre application avec la détection de visage", "Hi": "-C'est un plaisir. -Hello.", "No face detected": "Aucun scanner n'a été détécté", "Image detecting result is": "Le résultat de la détection d'image est", "from 3 times Take Attention": "que 3 fois attirent votre attention", "Be sure for take accurate images please": "Assurez-vous de prendre des photos précises s'il vous plaît", "You have": "- Euh...", "image verified": "La photo est notariée", "Next": "Suivant", "There is no help Question here": "Ouais, pas d'aide ici.", "Call End": "Terminer l'appel", "You dont have Points": "- Vous n'avez pas...", "You Are Stopped For this Day !": "Vous avez été mis en pause pour la journée !", "You must be charge your Account": "Vous devez recharger votre compte", "You Refused 3 Rides this Day that is the reason": "Vous avez refusé 3 courses aujourd'hui et c'est pourquoi", "See you Tomorrow!": "Je te verrais demain.", "Recharge my Account": "Recharger mon compte", "Ok , See you Tomorrow": "D'accord, on se voit demain.", "You are Stopped": "Vous êtes arrêté", "Connected": "Online", "Not Connected": "Offiline", "Your are far from passenger location": "Vous êtes loin de l'emplacement des passagers", "go to your passenger location before": "Accédez à l'emplacement de votre passager avant le", "Passenger cancel trip": "Le passager a annulé la course", "You will get cost of your work for this trip": "Vous obtiendrez le coût de votre entreprise pour cette course", "in your wallet": "Elle est dans ton portefeuille.", "you gain": "Vous gagnerez", "Order Cancelled": "Commande annulée", "Order Cancelled by Passenger": "Demande annulée par le passager", "Success": "Je l'ai.", "Feedback data saved successfully": "Données d'évaluation enregistrées avec succès", "No Promo for today .": "Pas de promotion pour aujourd'hui.", "Select your destination": "Sélectionnez la destination;", "Search for your Start point": "Trouvez votre point de départ", "Search for waypoint": "Rechercher un point WIPOINT", "Current Location": "Utiliser la position actuelle", "Add Location 1": "Emplacement & #160;: %1", "You must Verify email !.": "Relever le courriel", "Cropper": "Récolte", "Saved Sucssefully": "Bien reçu.", "Select Date": "Choisir une nouvelle date", "Birth Date": "Date de naissance", "Ok": "D'accord.", "the 500 points equal 30 JOD": "500 points équivaut à 30 JOD", "the 500 points equal 30 JOD for you": "500 points équivaut à 30 JOD pour vous", "token updated": "Code mis à jour", "Add Location 2": "Ajouter un emplacement 2", "Add Location 3": "Ajouter un emplacement 3", "Add Location 4": "Ajouter un emplacement 4", "Waiting for your location": "En attente de votre localisation", "Search for your destination": "Trouvez votre destination", "Hi! This is": "Bienvenue \"moi\": c' est ça.", "I am using": "Du matériel que j'utilisais.", "to ride with": "pour rouler avec", "as the driver.": "On dirait un chauffeur.", "is driving a": "- Je vais le tenter comme ça. - Conduire.", "with license plate": "Avec une plaque d'immatriculation", "I am currently located at": "Je suis actuellement en", "Please go to Car now": "S'il te plaît, va-t-en maintenant.", "If you need to reach me, please contact the driver directly at": "Si vous avez besoin de me joindre, veuillez contacter directement le chauffeur au", "No Car or Driver Found in your area.": "Aucune voiture ou chauffeur trouvé dans votre région.", "Please Try anther time": "Réessayer", "There no Driver Aplly your order sorry for that": "Aucun chauffeur ne peut répondre à votre demande, nous sommes désolés.", "Trip Cancelled": "Course annulée", "The Driver Will be in your location soon .": "Votre chauffeur arrivera bientôt chez vous.", "The distance less than 500 meter.": "La distance est inférieure à 500 mètres.", "Promo End !": "- C'est seulement jusqu'au spectacle.", "There is no notification yet": "Aucune notification pour le moment", "Use Touch ID or Face ID to confirm payment": "Utilisez Touch ID ou Face ID pour confirmer le paiement", "Contact us for any questions on your order.": "Contactez-nous pour toute question concernant votre commande.", "Pyament Cancelled .": "Le paiement a été annulé.", "type here": "Tapez ici", "Scan Driver License": "Permis de conduire", "Please put your licence in these border": "Veuillez placer votre licence dans ces limites", "Camera not initialized yet": "Caméra pas encore configurée", "Take Image": "Prends une photo, parce que demain matin, ces lettres partiront.", "AI Page": "Tu dis que ton système \"IA\"", "Take Picture Of ID Card": "Prenez une photo de votre pièce d'identité", "Take Picture Of Driver License Card": "Prenez une photo de votre permis de conduire.", "We are process picture please wait": "Nous traitons les images, veuillez patienter.", "There is no data yet.": "Aucune donnée trouvée", "Name :": "Nom :", "Drivers License Class:": "Catégorie de permis de conduire :", "Document Number:": "Numéro du document", "Address:": "Adresse:", "Height:": "& Hauteur & #160;:", "Expiry Date:": "Expiration & #160;:", "Date of Birth:": "Anniversaire & #160;: @title: group", "You can't continue with us .": "Ça ne peut pas durer.", "You should renew Driver license": "Vous devez renouveler votre permis de conduire", "Detect Your Face": "Découvrez votre visage", "Go to next step": "\"", "scan Car License.": "Vérification de l'immatriculation du véhicule.", "Name in arabic": "Full Name AR", "Drivers License Class": "Permis de conduire", "Date of Birth": "Date de naissance", "Age": "l’âge", "Lets check Car license": "Vérifions le permis de conduire", "Car Kind": "Type de véhicule", "Car Plate": "Le numéro d'immatriculation ?", "Lets check License Back Face": "Vérifions la licence de face arrière", "Car License Card": "Carte d'immatriculation du véhicule", "No image selected yet": "Aucune photo sélectionnée pour le moment", "Made :": "Make", "model :": "Mod.", "VIN :": "Structure :", "year :": "Année", "ُExpire Date": "Date d'expiration", "Login Driver": "Se connecter", "Password must br at least 6 character.": "Le mot de passe doit comporter au moins 6 caractères.", "if you don't have account": "Que voulez-vous dire ?", "Here recorded trips audio": "Voici les enregistrements audio du voyage", "Register as Driver": "Inscrivez-vous en tant que chauffeur", "Privacy Notice": "Avis de confidentialité", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "En sélectionnant « J'accepte » ci-dessous, j'ai lu, j'accepte et j'accepte les conditions générales", ". I am at least 18 years of age.": ". J'ai au moins 18 ans.", "Log Out Page": "Se Déconnecter", "Log Off": "Signe.", "Register Driver": "Le chauffeur...", "Verify Email For Driver": "Consultez l'e-mail du chauffeur", "Admin DashBoard": "Tableau de bord d'administration", "Your name": "Ton... nom.", "your ride is applied": "Votre course a été appliquée", "Your password": "Renouveler votre mot de passe", "LE": "Livre égyptienne", "JOD": "Monnaie: Dinar jordanien", "m": "%1 km", "We search nearst Driver to you": "Nous recherchons le chauffeur le plus proche", "please wait till driver accept your order": "Veuillez attendre que le chauffeur accepte votre demande", "No accepted orders? Try raising your trip fee to attract riders.": "Aucune Essayez d'augmenter les frais de course pour attirer des passagers.", "You should select one": "Vous devez en choisir un", "The driver accept your order for": "Votre chauffeur a accepté votre demande de", "Increase Fee": "Augmenter les frais", "No, thanks": "Non merci", "The driver on your way": "Votre chauffeur est en route", "Total price from": "P.T", "Order Details Intaleq": "Détails du commande", "Order Applied": "Commande appliquée", "accepted your order": "- Retenue.", "We regret to inform you that another driver has accepted this order.": "Nous sommes désolés de vous informer qu'un autre chauffeur a accepté cette demande.", "Selected file:": "Ouvre un fichier existant", "Your trip cost is": "Les frais de votre course", "this will delete all files from your device": "Cela supprimera tous les fichiers de votre appareil", "you have a negative balance of": "Vous avez un solde négatif de", "in your": "En toi.", "Exclusive offers and discounts always with the Intaleq app": "Offres exclusives et réductions toujours avec l'application de voyage", "Please go to Car Driver": "Veuillez vous rendre chez le conducteur de la voiture", "wallet due to a previous trip.": "Portefeuille en raison d'une course précédente.", "Submit Question": "Envoyer la question", "Please enter your Question.": "Veuillez saisir votre question.", "Help Details": "Détails de l'aide", "No trip yet found": "Aucune campagne trouvée", "No Response yet.": "Il n'y a pas de réponses.", "You Earn today is": "- On est euh...", "You Have in": "Vous avez à", "Total points is": "Le score total est de", "Total Connection Duration:": "Durée totale de connexion :", "H and": "H et", "Passenger name :": "Le voyageur.", "Cost Of Trip IS": "Coûts des vols par avion spécial", "Arrival time": "On arrive dans 7 minutes.", "arrival time to reach your point": "Heure d'arrivée pour atteindre votre destination", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Pour les courses et livraisons rapides, le prix est calculé de manière dynamique. Pour des courses confortables, le prix est basé sur la durée et la distance.", "Hello this is Driver": "Bonjour, je suis le chauffeur", "Is the Passenger in your Car ?": "Le passager est-il dans votre véhicule ?", "Please wait for the passenger to enter the car before starting the trip.": "Veuillez attendre que le passager entre dans le véhicule avant de commencer la course.", "No ,still Waiting.": "Non , je t'attends toujours.", "I arrive you": "Elle t'a eue.", "I Arrive your site": "Elle t'a eue.", "You are not in near to passenger location": "Vous n'êtes pas près de l'emplacement du passager", "please go to picker location exactly": "Veuillez vous rendre à l'emplacement exact de la sélection", "You Can Cancel Trip And get Cost of Trip From": "Vous pouvez annuler la course et obtenir le coût de la course auprès de", "Are you sure to cancel?": "Voulez-vous vraiment annuler ?", "Yes": "Oui", "Insert Emergincy Number": "Saisir le numéro d'urgence", "Best choice for comfort car and flexible route and stops point": "Le meilleur choix pour une voiture confortable, un itinéraire flexible et un point d'arrêt", "Insert": "En cours d' utilisation", "This is for delivery or a motorcycle.": "C'est pour la livraison ou une moto.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "Cette course va directement de votre point de départ à votre destination pour un tarif forfaitaire. Le chauffeur doit suivre l'itinéraire prévu", "You can decline a request without any cost": "Vous pouvez refuser la demande sans frais", "Perfect for adventure seekers who want to experience something new and exciting": "Idéal pour les chercheurs d'aventure qui veulent essayer quelque chose de nouveau et d'excitant", "My current location is:": "Mon emplacement actuel est :", "and I have a trip on": "et j'ai un voyage à", "App with Passenger": "Postuler avec le passager", "You will be pay the cost to driver or we will get it from you on next trip": "Le coût sera payé au chauffeur ou nous l'obtiendrons de votre part lors de la prochaine course", "Trip has Steps": "La course comporte des étapes", "Distance from Passenger to destination is": "La distance entre le passager et la destination est", "price is": "C'est cent dollars.", "This ride type does not allow changes to the destination or additional stops": "Ce type de course ne permet pas de modifier la destination ou d'effectuer des arrêts supplémentaires", "This price may be changed": "Ce prix peut changer", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "Pas de carte SIM, pas de problème ! Contactez directement votre chauffeur via notre application. Nous utilisons une technologie de pointe pour garantir votre confidentialité.", "This ride type allows changes, but the price may increase": "Ce type de course peut être modifié, mais le prix peut augmenter", "message From passenger": "Estafette.", "Select one message": "Message un.", "My location is correct. You can search for me using the navigation app": "Ma position est correcte. Vous pouvez me rechercher à l'aide de l'application de navigation", "I'm waiting for you": "- Quand vous voulez.", "Hello, I'm at the agreed-upon location": "Bonjour, je suis à l'endroit convenu", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "Nous avons remarqué que la vitesse dépasse 100 km/h. Veuillez ralentir pour votre propre sécurité. Si vous ne vous sentez pas en sécurité, vous pouvez communiquer les détails de votre course à un contact ou appeler la police à l'aide du bouton de détresse rouge.", "Warning: Intaleqing detected!": "Avertissement : survitesse détectée !", "Please help! Contact me as soon as possible.": "Aide-moi s'il te plaît. Contactez-moi dès que possible.", "Share Trip Details": "Partagez les détails de la", "Car Plate is": "Le numéro d'immatriculation ?", "the 3000 points equal 3000 L.E for you": "3000 points équivaut à 3000 EGP pour vous", "So go and gain your money": "Gagnez de l'argent", "the 3000 points equal 3000 L.E": "3000 points équivaut à 3000 EGP", "The payment was not approved. Please try again.": "Paiement non approuvé. Réessayer", "Payment Failed": "Échec du paiement", "Error": "ⵜⴰⵣⴳⵍⵜ", "An error occurred during the payment process.": "Une erreur s'est produite lors de votre paiement.", "The payment was approved.": "Paiement approuvé.", "Payment Successful": "Paiement réussi", "No ride found yet": "Aucune campagne trouvée", "Accept Order": "Commande acceptée", "reject your order.": "Votre Ordre.", "Bottom Bar Example": "Exemple de barre inférieure", "Driver phone": "Téléphone du chauffeur", "Statistics": "& Statistiques", "Origin": "ORIGINE", "Destination": "- Destination ?", "Driver Name": "Nom de pilote & #160;:", "Driver Car Plate": "Plaque d'immatriculation du conducteur", "Available for rides": "Disponible pour les courses", "Scan Id": "Contrôle d'identité", "Camera not initilaized yet": "Caméra pas encore configurée", "Scan ID MklGoogle": "Vérification d'identité MklGoogle", "Language": "Langue ", "Jordan": "Jordanie", "USA": "Etats Unis d'Amérique", "Egypt": "Egypte", "Turkey": "Turquie", "Saudi Arabia": "Arabie Saoudite", "Qatar": "Qatar", "Bahrain": "Bahreïn", "Kuwait": "Koweït", "But you have a negative salary of": "Mais vous avez un salaire négatif de", "Promo Code": "Code promo", "Your trip distance is": "La distance de votre course est de", "Enter promo code": "Code promo", "You have promo!": "Vous avez une promotion !", "Cost Duration": "Durée du coût", "Duration is": "La durée est", "Leave": "Quitter", "Join": "Joindre", "You Should be select reason.": "Vous devez choisir une raison.", "\$": "\$", "Waiting for Driver ...": "En attente du chauffeur ...", "Latest Recent Trip": "J'ai des choses à faire!", "from your list": "À partir de votre liste", "Do you want to change Work location": "Souhaitez-vous changer de lieu de travail ?", "Do you want to change Home location": "Souhaitez-vous changer l'emplacement de la maison", "We Are Sorry That we dont have cars in your Location!": "Nous sommes désolés que les voitures ne soient pas disponibles chez vous !", "Choose from Map": "Sélectionner sur la carte", "Pick your ride location on the map - Tap to confirm": "Sélectionnez votre lieu de prise en charge sur la carte - appuyez pour confirmer", "To Work": "Pour le boulot", "Are you want to go this site": "Voulez-vous aller à cet endroit", "Closest & Cheapest": "Le plus proche et le moins cher", "Work Saved": "Enregistré :", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq est une application de covoiturage sûre, fiable et accessible.", "With Intaleq, you can get a ride to your destination in minutes.": "En voyageant, vous pouvez vous rendre à destination en quelques minutes.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Safar s'engage pour la sécurité, et tous nos commandants sont soigneusement contrôlés et leurs antécédents vérifiés.", "To Home": "RETOUR À LA PAGE D'ACCUEIL", "Home Saved": "Enregistré :", "Destination selected": "Destination sélectionnée", "Now select start pick": "Maintenant, choisissez Démarrer la sélection", "Pick from map": "Sélectionner sur la carte", "Click here point": "Cliquez ici", "No Car in your site. Sorry!": "Il n'y a pas de voiture dans votre région. Ex... Excusez moi.", "Nearest Car for you about": "La voiture la plus proche de chez vous est d'environ", "N/A": "Aucune information", "From :": "Du :", "Get Details of Trip": "Obtenir les détails de la course", "If you want add stop click here": "Si vous souhaitez ajouter un arrêt, cliquez ici", "Driver": "ⴰⵎⵏⴷⴰⵀ", "Where you want go": "D'où viens-tu ?", "My Card": "Ma carte.", "Start Record": "Début de la campagne d'enregistrement", "Wallet": "Un portefeuille.", "History of Trip": "2.1 Histoire du vol", "Helping Center": "Centre d'aide", "Record saved": "Sauvegarde de l'historique effectuée !", "Trips recorded": "Voyages enregistrés", "Select Your Country": "Selectionnez votre pays", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "Pour vous assurer d'avoir les informations les plus précises pour votre emplacement, veuillez sélectionner votre pays ci-dessous. Cela vous aidera à personnaliser l'expérience et le contenu de l'application pour votre pays.", "Are you sure to delete recorded files": "Êtes-vous sûr de vouloir supprimer les fichiers enregistrés", "Select recorded trip": "Choisissez une course enregistrée", "Card Number": "N  de pièce d'identité:", "Hi, Where to": "Bonjour, oùallez-vous ?", "Pick your destination from Map": "Sélectionner sur la carte", "Add Stops": "Ajouter des arrêts", "Get Direction": "Obtenir une direction", "Add Location": "Ajouter l'emplacement correctement", "Switch Rider": "Changer de passager", "You will arrive to your destination after timer end.": "Vous arriverez à destination après l'expiration de la minuterie.", "You can cancel trip": "Vous pouvez annuler la course", "The driver waitting you in picked location .": "Votre chauffeur vous attend à l'endroit désigné .", "Pay with Your": "Payer avec", "Pay with Credit Card": "- La carte.", "Payment History": "Historique des paiements", "Show Promos to Charge": "Afficher les promotions d'expédition", "Point": "Points", "Driver Balance": "Portefeuille chauffeur", "Total Points is": "Le score total est de", "Total Budget from trips is": "Le budget total des voyages est de", "Total Amount:": "Montant total", "Total Budget from trips by": "Budget total des voyages par", "Credit card is": "Votre carte de crédit.", "This amount for all trip I get from Passengers": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers.", "Pay from my budget": "Payer sur mon budget", "This amount for all trip I get from Passengers and Collected For me in": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers collectés pour moi à", "You can buy points from your budget": "Vous pouvez acheter des points à partir de votre budget", "insert amount": "Entrez le montant", "You can buy Points to let you online": "Vous pouvez acheter des points pour vous permettre d'accéder en ligne", "by this list below": "Grâce à cette liste ci-dessous", "Create Wallet to receive your money": "Créez un portefeuille pour recevoir votre argent", "Enter your feedback here": "Saisissez vos commentaires ici", "Please enter your feedback.": "Veuillez saisir le texte de vos notes", "Feedback": "Feedback:", "Click here to Show it in Map": "Cliquez ici pour le voir sur la carte", "Canceled": "Annulé", "Type your Email": "Votre e-mail", "No I want": "- Je n'en ai pas envie.", "Email is": "Email ", "Phone Number is": "C'est le 92.38.09.06.", "Date of Birth is": "Année de naissance", "Sex is": "Le sexe est cardio.", "Car Details": "Détails du véhicule", "VIN is": "Structure", "Color is": "- Sa couleur?", "Make is": "Make is", "Model is": "Formulaire de :", "Year is": "Année", "Edit Your data": "Modifiez vos informations", "write vin for your car": "Notez le numéro de châssis de votre véhicule", "VIN": "|||UNTRANSLATED_CONTENT_START|||رقم هيكل السيارة|||UNTRANSLATED_CONTENT_END|||", "write Color for your car": "Tapez la couleur de votre voiture", "write Make for your car": "Écrivez une marque pour votre voiture", "write Model for your car": "Tapez votre modèle de voiture", "write Year for your car": "Saisissez une année pour votre voiture", "write Expiration Date for your car": "la date de péremption", "Tariffs": "Définitions ", "Minimum fare": "Prix minimum", "Maximum fare": "Prix maximum", "Flag-down fee": "Frais d'escale", "Including Tax": "Incluant...", "BookingFee": "Frais de réservation", "Morning": "- Bonjour.", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07h30 - 10h30 (jeudi, vendredi, samedi, lundi)", "Evening": "- Bonsoir.", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12h00 - 15h00 (jeudi, vendredi, samedi, lundi)", "Night": "la nuit", "You have in account": "Vous avez dans le compte", "Select Country": "Sélectionner un pays.", "Ride Today :": "Commandez une course aujourd'hui :", "After this period": "Après cette période", "You can't cancel!": "- Vous pouvez plus...", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "Le chauffeur...", "Total Cost is": "Coût total", "Write note": "J'écris une lettre de menace.", "Time to arrive": "Bobby, Qu'elle est notre e. t. a.?", "Ride Summaries": "Résumés des courses", "Total Cost": "Coût total", "Average of Hours of": "Nombre moyen d'heures de travail", "is ON for this month": "En cours ce mois-ci", "Days": "Quelques mois, semaines... quelques jours.", "Total Hours on month": "Nombre total d'heures", "Counts of Hours on days": "Heures en jours", "OrderId": "Commande N°", "created time": "Date de création", "Intaleq Over": "Et c'est là qu'on l'aura.", "I will slow down": "Je vais ralentir.", "Map Passenger": "Carte du passager", "Be Slowly": "Soyez lent", "If you want to make Google Map App run directly when you apply order": "Si vous souhaitez lancer Google Maps directement lorsque vous appliquez la commande", "You can change the language of the app": "Vous pouvez modifier la langue de l'application", "Your Budget less than needed": "Votre budget est sous-estimé", "You can change the Country to get all features": "Vous pouvez modifier le pays pour obtenir toutes les fonctionnalités", "Change Country": "Non-pays" }, "de": { "Order": "Auftrag", "OrderVIP": "VIP-Auftrag", "Cancel Trip": "Fahrt stornieren", "Passenger Cancel Trip": "Fahrgast hat storniert", "VIP Order": "VIP-Auftrag", "Hi ,I Arrive your site": "Hallo, ich bin am Standort angekommen", "The driver accepted your trip": "Der Fahrer hat Ihre Fahrt angenommen", "message From passenger": "Nachricht vom Fahrgast", "Cancel": "Abbrechen", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Fahrt storniert. Die Kosten werden Ihrer Wallet gutgeschrieben.", "token change": "Token-Änderung", "face detect": "Gesichtserkennung", "Face Detection Result": "Ergebnis der Gesichtserkennung", "similar": "Ähnlich", "not similar": "Nicht ähnlich", "Hi ,I will go now": "Hallo, ich fahre jetzt los", "Passenger come to you": "Fahrgast kommt zu Ihnen", "Call Income": "Eingehender Anruf", "Call Income from Passenger": "Anruf vom Fahrgast", "Criminal Document Required": "Führungszeugnis erforderlich", "You should have upload it .": "Sie müssen es hochladen.", "Call End": "Anruf beendet", "The order has been accepted by another driver.": "Der Auftrag wurde von einem anderen Fahrer angenommen.", "The order Accepted by another Driver": "Auftrag von anderem Fahrer angenommen", "We regret to inform you that another driver has accepted this order.": "Es tut uns leid, ein anderer Fahrer hat diesen Auftrag bereits angenommen.", "Driver Applied the Ride for You": "Fahrer hat die Fahrt für Sie beantragt", "Applied": "Beantragt", "Pay by Sham Cash": "Mit Sham Cash bezahlen", "Pay with Debit Card": "Mit Debitkarte bezahlen", "Please go to Car Driver": "Bitte gehen Sie zum Fahrer", "Ok I will go now.": "Ok, ich gehe jetzt.", "Accepted Ride": "Akzeptierte Fahrt", "Driver Accepted the Ride for You": "Fahrer hat die Fahrt für Sie akzeptiert", "Promo": "Promo", "Show latest promo": "Neueste Promos anzeigen", "Trip Monitoring": "Fahrtüberwachung", "Driver Is Going To Passenger": "Fahrer ist auf dem Weg zum Fahrgast", "Please stay on the picked point.": "Bitte bleiben Sie am Abholort.", "message From Driver": "Nachricht vom Fahrer", "Trip is Begin": "Fahrt beginnt", "Cancel Trip from driver": "Fahrtstornierung durch Fahrer", "We will look for a new driver.\nPlease wait.": "Wir suchen einen neuen Fahrer.\nBitte warten.", "The driver canceled your ride.": "Der Fahrer hat Ihre Fahrt storniert.", "Driver Finish Trip": "Fahrer hat Fahrt beendet", "you will pay to Driver": "Sie zahlen an den Fahrer", "Don’t forget your personal belongings.": "Vergessen Sie Ihre persönlichen Gegenstände nicht.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Bitte stellen Sie sicher, dass Sie alle persönlichen Gegenstände haben und dass Restbeträge Ihrer Wallet gutgeschrieben wurden. Danke, dass Sie Intaleq nutzen.", "Finish Monitor": "Überwachung beenden", "Trip finished": "Fahrt beendet", "Call Income from Driver": "Anruf vom Fahrer", "Driver Cancelled Your Trip": "Fahrer hat Ihre Fahrt storniert", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Sie bezahlen die Zeit des Fahrers, siehe Ihre Intaleq Wallet", "Order Applied": "Auftrag angewendet", "welcome to intaleq": "Willkommen bei Intaleq", "login or register subtitle": "Geben Sie Ihre Handynummer ein, um sich anzumelden oder zu registrieren", "An application error occurred.": "Ein Anwendungsfehler ist aufgetreten.", "Submission Failed": "Senden fehlgeschlagen", "Your complaint has been submitted.": "Ihre Beschwerde wurde eingereicht.", "Failed to connect to the server. Please try again.": "Verbindung zum Server fehlgeschlagen. Bitte versuchen Sie es erneut.", "Ride information not found. Please refresh the page.": "Fahrtinformationen nicht gefunden. Bitte Seite aktualisieren.", "Please describe your issue before submitting.": "Bitte beschreiben Sie Ihr Problem vor dem Absenden.", "An application error occurred during upload.": "Fehler beim Hochladen aufgetreten.", "Failed to upload audio file.": "Hochladen der Audiodatei fehlgeschlagen.", "Audio uploaded successfully.": "Audio erfolgreich hochgeladen.", "Complaint cannot be filed for this ride. It may not have been completed or started.": "Beschwerde kann für diese Fahrt nicht eingereicht werden. Vielleicht nicht beendet oder gestartet.", "2. Attach Recorded Audio (Optional)": "2. Audioaufnahme anhängen (Optional)", "Please enter a description of the issue.": "Bitte geben Sie eine Beschreibung des Problems ein.", "phone number label": "Telefonnummer", "phone number required": "Telefonnummer erforderlich", "send otp button": "OTP senden", "verify your number title": "Nummer verifizieren", "otp sent subtitle": "Ein 5-stelliger Code wurde gesendet an\n@phoneNumber", "verify and continue button": "Verifizieren und weiter", "enter otp validation": "Bitte geben Sie den 5-stelligen OTP ein", "one last step title": "Ein letzter Schritt", "complete profile subtitle": "Vervollständigen Sie Ihr Profil", "first name label": "Vorname", "first name required": "Vorname erforderlich", "last name label": "Nachname", "Verify OTP": "OTP verifizieren", "Verification Code": "Verifizierungscode", "We have sent a verification code to your mobile number:": "Wir haben einen Code an Ihre Handynummer gesendet:", "Verify": "Verifizieren", "Resend Code": "Code erneut senden", "You can resend in": "Erneut senden in", "seconds": "Sekunden", "Error": "Fehler", "Please enter the complete 6-digit code.": "Bitte geben Sie den vollständigen 6-stelligen Code ein.", "last name required": "Nachname erforderlich", "email optional label": "E-Mail (Optional)", "complete registration button": "Registrierung abschließen", "User with this phone number or email already exists.": "Benutzer mit dieser Nummer oder E-Mail existiert bereits.", "otp sent success": "OTP erfolgreich an WhatsApp gesendet.", "failed to send otp": "Senden des OTP fehlgeschlagen.", "server error try again": "Serverfehler, bitte versuchen Sie es erneut.", "an error occurred": "Ein Fehler ist aufgetreten: @error", "otp verification failed": "OTP-Verifizierung fehlgeschlagen.", "registration failed": "Registrierung fehlgeschlagen.", "welcome user": "Willkommen, @firstName!", "Cancel Trip from driver": "Fahrtstornierung durch Fahrer", "We will look for a new driver.\nPlease wait.": "Wir suchen einen neuen Fahrer.\nBitte warten.", "The driver canceled your ride.": "Der Fahrer hat Ihre Fahrt storniert.", "Driver Finish Trip": "Fahrer beendet Fahrt", "you will pay to Driver": "Sie zahlen an den Fahrer", "Don't forget your personal belongings.": "Vergessen Sie Ihre persönlichen Gegenstände nicht.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Bitte prüfen Sie Ihre Gegenstände und ob Restbeträge Ihrer Wallet gutgeschrieben wurden. Danke für die Nutzung von Intaleq.", "Finish Monitor": "Überwachung beenden", "Trip finished": "Fahrt beendet", "Call Income from Driver": "Anruf vom Fahrer", "Driver Cancelled Your Trip": "Fahrer hat Ihre Fahrt storniert", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Sie zahlen die Zeit des Fahrers, siehe Ihre Intaleq Wallet", "Order Applied": "Auftrag aufgegeben", "Share App": "App teilen", "Wallet": "Wallet", "Balance": "Guthaben", "Don’t forget your personal belongings.": "Vergessen Sie Ihre persönlichen Sachen nicht.", "Profile": "Profil", "Contact Support": "Support kontaktieren", "Session expired. Please log in again.": "Sitzung abgelaufen. Bitte erneut anmelden.", "Security Warning": "⚠️ Sicherheitswarnung", "Potential security risks detected. The application may not function correctly.": "Potenzielle Sicherheitsrisiken erkannt. Die App funktioniert möglicherweise nicht korrekt.", "please order now": "Jetzt bestellen", "Where to": "Wohin?", "Where are you going?": "Wohin fahren Sie?", "Quick Actions": "Schnellaktionen", "My Balance": "Mein Guthaben", "Order History": "Bestellverlauf", "Contact Us": "Kontakt", "Driver": "Fahrer", "Complaint": "Beschwerde", "Promos": "Promos", "Recent Places": "Letzte Orte", "From": "Von", "WhatsApp Location Extractor": "WhatsApp Standort-Extraktor", "Location Link": "Standort-Link", "Paste location link here": "Standort-Link hier einfügen", "Go to this location": "Zu diesem Ort navigieren", "Paste WhatsApp location link": "WhatsApp Standort-Link einfügen", "Select Order Type": "Auftragstyp wählen", "Choose who this order is for": "Für wen ist diese Fahrt?", "I want to order for myself": "Ich bestelle für mich", "I want to order for someone else": "Ich bestelle für jemand anderen", "Order for someone else": "Für jemand anderen bestellen", "Order for myself": "Für mich bestellen", "Are you want to go this site": "Möchten Sie zu diesem Ort?", "No": "Nein", "Pay by Sham Cash": "Mit Sham Cash zahlen", "Intaleq Wallet": "Intaleq Wallet", "Have a promo code?": "Haben Sie einen Promo-Code?", "Your Wallet balance is ": "Ihr Wallet-Guthaben beträgt ", "Cash": "Bar", "Phone Number": "Telefonnummer", "Search country": "Land suchen", "Payment Successful!": "Zahlung erfolgreich!", "Your payment was successful.": "Ihre Zahlung war erfolgreich.", "Pay directly to the captain": "Direkt an den Fahrer zahlen", "Top up Wallet to continue": "Wallet aufladen zum Fortfahren", "Or pay with Cash instead": "Oder bar bezahlen", "Confirm & Find a Ride": "Bestätigen & Fahrt finden", "Balance:": "Guthaben:", "Alerts": "Benachrichtigungen", "Welcome Back!": "Willkommen zurück!", "Current Balance": "Aktuelles Guthaben", "Set Wallet Phone Number": "Wallet-Telefonnummer festlegen", "Link a phone number for transfers": "Telefonnummer für Überweisungen verknüpfen", "Payment History": "Zahlungsverlauf", "View your past transactions": "Vergangene Transaktionen ansehen", "Top up Wallet": "Wallet aufladen", "Add funds using our secure methods": "Guthaben sicher aufladen", "Driver is waiting": "Fahrer wartet", "Type your message...": "Nachricht eingeben...", "Driver Accepted Request": "Fahrer hat Anfrage akzeptiert", "Message": "Nachricht", "Call": "Anrufen", "Set Phone Number": "Telefonnummer festlegen", "Select This Ride": "Diese Fahrt wählen", "Call Driver": "Fahrer anrufen", "Increase Fare": "Preis erhöhen", "Stop": "Stopp", "Record": "Aufnehmen", "Share": "Teilen", "WhatsApp": "WhatsApp", "SOS": "SOS", "No drivers accepted your request yet": "Noch kein Fahrer hat Ihre Anfrage akzeptiert", "Increasing the fare might attract more drivers. Would you like to increase the price?": "Eine Preiserhöhung könnte mehr Fahrer anlocken. Möchten Sie den Preis erhöhen?", "Please make sure not to leave any personal belongings in the car.": "Bitte lassen Sie keine persönlichen Gegenstände im Auto zurück.", "Cancel Ride": "Fahrt stornieren", "Route Not Found": "Route nicht gefunden", "We couldn't find a valid route to this destination. Please try selecting a different point.": "Keine gültige Route gefunden. Bitte wählen Sie einen anderen Punkt.", "alert": "Alarm", "You can call or record audio during this trip.": "Sie können während der Fahrt anrufen oder Audio aufnehmen.", "Warning: Speeding detected!": "Warnung: Geschwindigkeitsüberschreitung!", "Fixed Price": "Festpreis", "Report": "Melden", "Comfort": "Komfort", "Intaleq Balance": "Intaleq Guthaben", "Search for a starting point": "Startpunkt suchen", "Top up Balance to continue": "Guthaben aufladen zum Fortfahren", "Electric": "Elektro", "Lady": "Damen", "Van": "Van", "Rayeh Gai": "Hin & Zurück", "Join Intaleq as a driver using my referral code!": "Werde Fahrer bei Intaleq mit meinem Code!", "Use code:": "Code verwenden:", "Download the Intaleq Driver app now and earn rewards!": "Lade die Intaleq Fahrer-App und verdiene Belohnungen!", "Get a discount on your first Intaleq ride!": "Rabatt auf deine erste Intaleq-Fahrt!", "Use my referral code:": "Mein Empfehlungscode:", "Download the Intaleq app now and enjoy your ride!": "Intaleq App laden und Fahrt genießen!", "Contacts Loaded": "Kontakte geladen", "Showing": "Zeige", "of": "von", "Pay by MTN Wallet": "Mit MTN Wallet zahlen", "Pay by Syriatel Wallet": "Mit Syriatel Wallet zahlen", "Customer not found": "Kunde nicht gefunden", "Wallet is blocked": "Wallet ist gesperrt", "Customer phone is not active": "Kundentelefon nicht aktiv", "Balance not enough": "Guthaben nicht ausreichend", "Balance limit exceeded": "Guthabenlimit überschritten", "Incorrect sms code": "⚠️ Falscher SMS-Code. Bitte erneut versuchen.", "contacts. Others were hidden because they don't have a phone number.": "Kontakte. Andere ausgeblendet wegen fehlender Nummer.", "No contacts found": "Keine Kontakte gefunden", "No contacts with phone numbers were found on your device.": "Keine Kontakte mit Telefonnummern auf dem Gerät gefunden.", "Permission denied": "Zugriff verweigert", "Contact permission is required to pick contacts": "Kontaktzugriff erforderlich.", "An error occurred while picking contacts:": "Fehler beim Auswählen der Kontakte:", "Please enter a correct phone": "Bitte korrekte Nummer eingeben", "Success": "Erfolg", "Invite sent successfully": "Einladung erfolgreich gesendet", "Hello! I'm inviting you to try Intaleq.": "Hallo! Ich lade dich ein, Intaleq zu testen.", "Use my invitation code to get a special gift on your first ride!": "Nutze meinen Code für ein Geschenk bei der ersten Fahrt!", "Your personal invitation code is:": "Dein persönlicher Einladungscode:", "Be sure to use it quickly! This code expires at": "Schnell nutzen! Code läuft ab am", "Download the app now:": "App jetzt laden:", "See you on the road!": "Wir sehen uns auf der Straße!", "This phone number has already been invited.": "Diese Nummer wurde bereits eingeladen.", "An unexpected error occurred. Please try again.": "Unerwarteter Fehler. Bitte erneut versuchen.", "You deserve the gift": "Sie haben das Geschenk verdient", "Claim your 20 LE gift for inviting": "Fordern Sie Ihr 20 € Geschenk an", "You have got a gift for invitation": "Sie haben ein Geschenk für die Einladung erhalten", "You have earned 20": "Sie haben 20 verdient", "LE": "€", "Vibration feedback for all buttons": "Vibrationsfeedback für alle Tasten", "Share with friends and earn rewards": "Mit Freunden teilen und Belohnungen verdienen", "Gift Already Claimed": "Geschenk bereits eingelöst", "You have already received your gift for inviting": "Sie haben Ihr Geschenk für diese Einladung bereits erhalten", "Keep it up!": "Weiter so!", "has completed": "hat abgeschlossen", "trips": "Fahrten", "Personal Information": "Persönliche Informationen", "Name": "Name", "Not set": "Nicht festgelegt", "Gender": "Geschlecht", "Education": "Bildung", "Work & Contact": "Arbeit & Kontakt", "Employment Type": "Beschäftigungsart", "Marital Status": "Familienstand", "SOS Phone": "SOS-Telefon", "Sign Out": "Abmelden", "Delete My Account": "Mein Konto löschen", "Update Gender": "Geschlecht aktualisieren", "Update": "Aktualisieren", "Update Education": "Bildung aktualisieren", "Are you sure? This action cannot be undone.": "Sind Sie sicher? Dies kann nicht rückgängig gemacht werden.", "Confirm your Email": "E-Mail bestätigen", "Type your Email": "E-Mail eingeben", "Delete Permanently": "Dauerhaft löschen", "Male": "Männlich", "Female": "Weiblich", "Other": "Divers", "High School Diploma": "Abitur / Mittlere Reife", "Associate Degree": "Berufsausbildung", "Bachelor's Degree": "Bachelor-Abschluss", "Master's Degree": "Master-Abschluss", "Doctoral Degree": "Doktortitel", "Select your preferred language for the app interface.": "Wählen Sie Ihre bevorzugte Sprache für die App.", "Language Options": "Sprachoptionen", "You can claim your gift once they complete 2 trips.": "Sie erhalten das Geschenk, sobald 2 Fahrten abgeschlossen sind.", "Closest & Cheapest": "Am Nächsten & Günstigsten", "Comfort choice": "Komfort-Wahl", "Travel in a modern, silent electric car. A premium, eco-friendly choice for a smooth ride.": "Reisen Sie im modernen, leisen Elektroauto. Premium und umweltfreundlich.", "Spacious van service ideal for families and groups. Comfortable, safe, and cost-effective travel together.": "Geräumiger Van-Service, ideal für Familien und Gruppen. Komfortabel, sicher und günstig.", "Quiet & Eco-Friendly": "Leise & Umweltfreundlich", "Lady Captain for girls": "Fahrerin für Frauen", "Van for familly": "Van für Familie", "Are you sure to delete this location?": "Diesen Ort wirklich löschen?", "Change Work location?": "Arbeitsort ändern?", "Change Home location?": "Wohnort ändern?", "Submit a Complaint": "Beschwerde einreichen", "Submit Complaint": "Beschwerde absenden", "No trip history found": "Kein Fahrtverlauf gefunden", "Your past trips will appear here.": "Ihre vergangenen Fahrten erscheinen hier.", "1. Describe Your Issue": "1. Problem beschreiben", "Enter your complaint here...": "Geben Sie Ihre Beschwerde hier ein...", "2. Attach Recorded Audio": "2. Audioaufnahme anhängen", "No audio files found.": "Keine Audiodateien gefunden.", "Confirm Attachment": "Anhang bestätigen", "Attach this audio file?": "Diese Audiodatei anhängen?", "Uploaded": "Hochgeladen", "3. Review Details & Response": "3. Details & Antwort überprüfen", "Date": "Datum", "Today's Promos": "Heutige Promos", "No promos available right now.": "Derzeit keine Promos verfügbar.", "Check back later for new offers!": "Schauen Sie später wieder vorbei!", "Valid Until:": "Gültig bis:", "CODE": "CODE", "Login": "Anmelden", "Sign in for a seamless experience": "Melden Sie sich für ein nahtloses Erlebnis an", "Sign In with Google": "Mit Google anmelden", "Sign in with Apple": "Mit Apple anmelden", "User not found": "Benutzer nicht gefunden", "Need assistance? Contact us": "Brauchen Sie Hilfe? Kontaktieren Sie uns", "Email": "E-Mail", "Your email address": "Ihre E-Mail-Adresse", "Enter a valid email": "Gültige E-Mail eingeben", "Password": "Passwort", "Your password": "Ihr Passwort", "Enter your password": "Passwort eingeben", "Submit": "Absenden", "Terms of Use & Privacy Notice": "Nutzungsbedingungen & Datenschutzerklärung", "By selecting \"I Agree\" below, I confirm that I have read and agree to the ": "Mit \"Ich stimme zu\" bestätige ich, dass ich die ", "Terms of Use": "Nutzungsbedingungen", " and acknowledge the ": " gelesen habe und die ", "Privacy Notice": "Datenschutzerklärung", " . I am at least 18 years old.": " akzeptiere. Ich bin mindestens 18 Jahre alt.", "I Agree": "Ich stimme zu", "Continue": "Weiter", "Enable Location": "Standort aktivieren", "To give you the best experience, we need to know where you are. Your location is used to find nearby captains and for pickups.": "Für das beste Erlebnis benötigen wir Ihren Standort, um Fahrer in der Nähe zu finden.", "Allow Location Access": "Standortzugriff erlauben", "Welcome to Intaleq!": "Willkommen bei Intaleq!", "Before we start, please review our terms.": "Bitte lesen Sie zuerst unsere Bedingungen.", "Your journey starts here": "Ihre Reise beginnt hier", "Cancel Search": "Suche abbrechen", "Set pickup location": "Abholort festlegen", "Move the map to adjust the pin": "Karte bewegen, um Pin anzupassen", "Searching for the nearest captain...": "Suche nach dem nächsten Fahrer...", "No one accepted? Try increasing the fare.": "Niemand akzeptiert? Versuchen Sie, den Preis zu erhöhen.", "Increase Your Trip Fee (Optional)": "Fahrtpreis erhöhen (Optional)", "We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers.": "Noch keine Fahrer gefunden. Erhöhen Sie den Preis, um das Angebot attraktiver zu machen.", "No, thanks": "Nein, danke", "Increase Fee": "Preis erhöhen", "Copy": "Kopieren", "Promo Copied!": "Promo kopiert!", "Code": "Code", "copied to clipboard": "in Zwischenablage kopiert", "Price": "Preis", "Intaleq's Response": "Antwort von Intaleq", "Awaiting response...": "Warte auf Antwort...", "Audio file not attached": "Audiodatei nicht angehängt", "The audio file is not uploaded yet.\\nDo you want to submit without it?": "Audiodatei noch nicht hochgeladen.\\nOhne sie absenden?", "deleted": "gelöscht", "To Work": "Zur Arbeit", "Work Saved": "Arbeit gespeichert", "To Home": "Nach Hause", "Home Saved": "Zuhause gespeichert", "Destination selected": "Ziel ausgewählt", "Now select start pick": "Jetzt Startpunkt wählen", "OK": "OK", "Confirm Pick-up Location": "Abholort bestätigen", "Set Location on Map": "Ort auf Karte festlegen", "Leave a detailed comment (Optional)": "Detaillierten Kommentar hinterlassen (Optional)", "Share your experience to help us improve...": "Teilen Sie Ihre Erfahrung, um uns zu verbessern...", "Your valuable feedback helps us improve our service quality.": "Ihr Feedback hilft uns, die Servicequalität zu verbessern.", "witout zero": "ohne Null", "Top up Balance": "Guthaben aufladen", "An error occurred": "Ein Fehler ist aufgetreten", "Send WhatsApp Message": "WhatsApp-Nachricht senden", "How was your trip with": "Wie war Ihre Fahrt mit", "Drawing route on map...": "Route wird auf Karte gezeichnet...", "Please wait while we prepare your trip.": "Bitte warten, Fahrt wird vorbereitet.", "Submit Rating": "Bewertung absenden", "Call Support": "Support anrufen", "You can contact us during working hours from 10:00 - 16:00.": "Sie können uns während der Geschäftszeiten von 10:00 - 16:00 Uhr kontaktieren.", "Intaleq is the safest and most reliable ride-sharing app designed especially for passengers in Syria. We provide a comfortable, respectful, and affordable riding experience with features that prioritize your safety and convenience. Our trusted captains are verified, insured, and supported by regular car maintenance carried out by top engineers. We also offer on-road support services to make sure every trip is smooth and worry-free. With Intaleq, you enjoy quality, safety, and peace of mind—every time you ride.": "Intaleq ist die sicherste Mitfahr-App für Deutschland. Wir bieten eine komfortable und erschwingliche Fahrt, bei der Ihre Sicherheit Vorrang hat. Unsere Fahrer sind verifiziert und versichert.", "Work time is from 10:00 AM to 16:00 PM.\nYou can send a WhatsApp message or email.": "Arbeitszeit ist 10:00 - 16:00 Uhr.\nSie können WhatsApp oder E-Mail senden.", "Sorry": "Entschuldigung", "Customer MSISDN doesn’t have customer wallet": "Kunden-MSISDN hat keine Wallet", "Please enter the number without the leading 0": "Bitte Nummer ohne führende 0 eingeben", "Please enter your phone number": "Bitte geben Sie Ihre Telefonnummer ein", "Phone number seems too short": "Telefonnummer scheint zu kurz zu sein", "No cars are available at the moment. Please try again later.": "Derzeit keine Autos verfügbar. Bitte später versuchen.", "Nearest Car: ~": "Nächstes Auto: ~", "Nearest Car": "Nächstes Auto", "No cars nearby": "Keine Autos in der Nähe", "Favorite Places": "Lieblingsorte", "No favorite places yet!": "Noch keine Lieblingsorte!", "from your favorites": "aus Favoriten", "Back": "Zurück", "Enter your code below to apply the discount.": "Code unten eingeben, um Rabatt zu erhalten.", "By selecting \"I Agree\" below, I confirm that I have read and agree to the": "Mit \"Ich stimme zu\" bestätige ich, dass ich die", "and acknowledge the": "gelesen habe und die", "Enable Location Access": "Standortzugriff aktivieren", "We need your location to find nearby drivers for pickups and drop-offs.": "Wir benötigen Ihren Standort, um Fahrer zu finden.", "You should restart app to change language": "App neu starten, um Sprache zu ändern", "Home Page": "Startseite", "To change Language the App": "Um die Sprache der App zu ändern", "Learn more about our app and mission": "Mehr über unsere App und Mission erfahren", "Promos For Today": "Heutige Promos", "Choose your ride": "Wählen Sie Ihre Fahrt", "Your Journey Begins Here": "Ihre Reise beginnt hier", "Bonus gift": "Bonusgeschenk", "Pay": "Bezahlen", "Get": "Erhalten", "Send to Driver Again": "Erneut an Fahrer senden", "Driver Name:": "Fahrername:", "No trip data available": "Keine Fahrtdaten verfügbar", "Car Plate:": "Kennzeichen:", "remaining": "verbleibend", "Order Cancelled": "Auftrag storniert", "You canceled VIP trip": "Sie haben die VIP-Fahrt storniert", "Passenger cancelled order": "Fahrgast hat Auftrag storniert", "Your trip is scheduled": "Ihre Fahrt ist geplant", "Don't forget your ride!": "Vergessen Sie Ihre Fahrt nicht!", "Trip updated successfully": "Fahrt erfolgreich aktualisiert", "Car Make:": "Marke:", "Car Model:": "Modell:", "Car Color:": "Farbe:", "Driver Phone:": "Fahrer-Telefon:", "Pre-booking": "Vorbuchung", "Waiting VIP": "Warten auf VIP", "Driver List": "Fahrerliste", "Confirm Trip": "Fahrt bestätigen", "Select date and time of trip": "Datum und Uhrzeit wählen", "Date and Time Picker": "Datum- und Zeitwähler", "Trip Status:": "Fahrtstatus:", "pending": "ausstehend", "accepted": "akzeptiert", "rejected": "abgelehnt", "Apply": "Anwenden", "Enter your promo code": "Promo-Code eingeben", "Apply Promo Code": "Promo-Code anwenden", "Scheduled Time:": "Geplante Zeit:", "No drivers available": "Keine Fahrer verfügbar", "No drivers available at the moment. Please try again later.": "Derzeit keine Fahrer verfügbar. Bitte später versuchen.", "you have a negative balance of": "Sie haben ein negatives Guthaben von", "Please try again in a few moments": "Bitte in wenigen Augenblicken erneut versuchen", "Unknown Driver": "Unbekannter Fahrer", "in your": "in Ihrer", "The driver accepted your order for": "Der Fahrer hat Ihren Auftrag angenommen für", "wallet due to a previous trip.": "Wallet aufgrund einer früheren Fahrt.", "rides": "Fahrten", "Add Work": "Arbeit hinzufügen", "The reason is": "Der Grund ist", "User does not have a wallet #1652": "Benutzer hat keine Wallet #1652", "Price of trip": "Fahrtpreis", "From:": "Von:", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Für Intaleq- und Lieferfahrten wird der Preis dynamisch berechnet. Für Komfortfahrten basiert er auf Zeit und Entfernung.", "Phone Wallet Saved Successfully": "Wallet-Telefonnummer gespeichert", "Add wallet phone you use": "Verwendete Wallet-Telefonnummer hinzufügen", "Update Available": "Update verfügbar", "Phone number must be exactly 11 digits long": "Telefonnummer muss genau 11 Ziffern lang sein", "Insert Wallet phone number": "Wallet-Telefonnummer eingeben", "Phone number isn't an Egyptian phone number": "Keine deutsche Telefonnummer", "A new version of the app is available. Please update to the latest version.": "Neue App-Version verfügbar. Bitte aktualisieren.", "We use location to get accurate and nearest passengers for you": "Wir nutzen den Standort, um die nächsten Fahrgäste zu finden", "This ride is already applied by another driver.": "Diese Fahrt wurde bereits von einem anderen Fahrer übernommen.", "We use your precise location to find the nearest available driver and provide accurate pickup and dropoff information. You can manage this in Settings.": "Wir nutzen Ihren genauen Standort für Fahrer und präzise Abholinfos. Dies können Sie in den Einstellungen verwalten.", "Where are you, sir?": "Wo sind Sie?", "I've been trying to reach you but your phone is off.": "Ich habe versucht Sie zu erreichen, aber Ihr Telefon ist aus.", "Please don't be late": "Bitte kommen Sie nicht zu spät", "Please don't be late, I'm waiting for you at the specified location.": "Bitte nicht zu spät kommen, ich warte am angegebenen Ort.", "My location is correct. You can search for me using the navigation app": "Mein Standort ist korrekt. Sie können mich über die Navi-App suchen.", "Hello, I'm at the agreed-upon location": "Hallo, ich bin am vereinbarten Ort", "How much longer will you be?": "Wie lange brauchen Sie noch?", "Phone number is verified before": "Telefonnummer wurde bereits verifiziert", "Change Ride": "Fahrt ändern", "You can change the destination by long-pressing any point on the map": "Sie können das Ziel durch langes Drücken auf der Karte ändern", "Pick from map destination": "Ziel von Karte wählen", "Pick or Tap to confirm": "Wählen oder Tippen zum Bestätigen", "Accepted your order": "Hat Ihren Auftrag angenommen", "Order Accepted": "Auftrag angenommen", "with type": "mit Typ", "accepted your order at price": "hat Auftrag angenommen zum Preis", "you canceled order": "Sie haben den Auftrag storniert", "If you want order to another person": "Wenn Sie für jemand anderen bestellen wollen", "upgrade price": "Preis erhöhen", "airport": "Flughafen", "Best choice for a comfortable car with a flexible route and stop points. This airport offers visa entry at this price.": "Beste Wahl für ein komfortables Auto mit flexibler Route.", "You can upgrade price to may driver accept your order": "Sie können den Preis erhöhen, damit ein Fahrer annimmt", "Change Route": "Route ändern", "No Captain Accepted Your Order": "Kein Fahrer hat Ihren Auftrag angenommen", "We are looking for a captain but the price may increase to let a captain accept": "Wir suchen einen Fahrer, aber der Preis könnte steigen", "No, I want to cancel this trip": "Nein, ich möchte diese Fahrt stornieren", "Attention": "Achtung", "Trip Cancelled. The cost of the trip will be deducted from your wallet.": "Fahrt storniert. Kosten werden von Ihrer Wallet abgezogen.", "You will be charged for the cost of the driver coming to your location.": "Die Anfahrtskosten des Fahrers werden berechnet.", "reject your order.": "lehnen Ihren Auftrag ab.", "Order Under Review": "Auftrag wird geprüft", "is reviewing your order. They may need more information or a higher price.": "prüft Ihren Auftrag. Eventuell werden mehr Infos oder ein höherer Preis benötigt.", "Vibration": "Vibration", "Resend code": "Code erneut senden", "change device": "Gerät wechseln", "Device Change Detected": "Gerätewechsel erkannt", "You can only use one device at a time. This device will now be set as your active device.": "Sie können nur ein Gerät gleichzeitig nutzen. Dieses Gerät ist nun aktiv.", "Click here point": "Hier klicken", "Are you want to change": "Möchten Sie ändern", "by": "von", "Enter your complaint here": "Beschwerde hier eingeben", "Please enter your complaint.": "Bitte geben Sie Ihre Beschwerde ein.", "Complaint data saved successfully": "Beschwerdedaten gespeichert", "Trip Monitor": "Fahrtmonitor", "Insert SOS Phone": "SOS-Nummer eingeben", "Add SOS Phone": "SOS-Nummer hinzufügen", "Dear ,\n\n 🚀 I have just started an exciting trip and I would like to share the details of my journey and my current location with you in real-time! Please download the Intaleq app. It will allow you to view my trip details and my latest location.\n\n 👉 Download link: \n Android [https://play.google.com/store/apps/details?id=com.mobileapp.store.ride]\n iOS [https://getapp.cc/app/6458734951]\n\n I look forward to keeping you close during my adventure!\n\n Intaleq ,": "Hallo,\n\n🚀 ich habe eine Fahrt begonnen und möchte meinen Standort teilen! Lade die Intaleq App, um meine Fahrt zu verfolgen.\n\n👉 Download:\nAndroid [https://play.google.com/store/apps/details?id=com.mobileapp.store.ride]\niOS [https://getapp.cc/app/6458734951]\n\nBis bald!\n\nIntaleq ,", "Send Intaleq app to him": "Intaleq App an ihn senden", "No passenger found for the given phone number": "Kein Fahrgast für diese Nummer gefunden", "No user found for the given phone number": "Kein Benutzer für diese Nummer gefunden", "This price is": "Dieser Preis ist", "Work": "Arbeit", "Add Home": "Zuhause hinzufügen", "Notifications": "Benachrichtigungen", "💳 Pay with Credit Card": "💳 Mit Kreditkarte zahlen", "⚠️ You need to choose an amount!": "⚠️ Sie müssen einen Betrag wählen!", "💰 Pay with Wallet": "💰 Mit Wallet zahlen", "You must restart the app to change the language.": "App neu starten, um Sprache zu ändern.", "joined": "beigetreten", "Driver joined the channel": "Fahrer ist dem Kanal beigetreten", "Driver left the channel": "Fahrer hat den Kanal verlassen", "Call Page": "Anrufseite", "Call Left": "Verbleibende Anrufe", " Next as Cash !": " Nächste als Barzahlung!", "To use Wallet charge it": "Wallet aufladen, um sie zu nutzen", "We are searching for the nearest driver to you": "Wir suchen den nächsten Fahrer", "Best choice for cities": "Beste Wahl für Städte", "Rayeh Gai: Round trip service for convenient travel between cities, easy and reliable.": "Rayeh Gai: Hin- und Rückfahrt-Service zwischen Städten.", "This trip is for women only": "Diese Fahrt ist nur für Frauen", "Total budgets on month": "Gesamtbudget im Monat", "You have call from driver": "Anruf vom Fahrer", "Intaleq": "Intaleq", "passenger agreement": "Fahrgastvereinbarung", "To become a passenger, you must review and agree to the ": "Um Fahrgast zu werden, müssen Sie zustimmen den ", "agreement subtitle": "Um fortzufahren, müssen Sie den Nutzungsbedingungen und der Datenschutzerklärung zustimmen.", "terms of use": "Nutzungsbedingungen", " and acknowledge our Privacy Policy.": " und unserer Datenschutzerklärung.", "and acknowledge our": "und anerkennen unsere", "privacy policy": "Datenschutzerklärung.", "i agree": "Ich stimme zu", "Driver already has 2 trips within the specified period.": "Fahrer hat bereits 2 Fahrten in diesem Zeitraum.", "The invitation was sent successfully": "Einladung erfolgreich gesendet", "You should select your country": "Sie sollten Ihr Land wählen", "Scooter": "E-Scooter", "A trip with a prior reservation, allowing you to choose the best captains and cars.": "Fahrt mit Vorreservierung, Auswahl der besten Fahrer und Autos.", "Mishwar Vip": "Mishwar VIP", "The driver waiting you in picked location .": "Fahrer wartet am Abholort.", "About Us": "Über uns", "You can change the vibration feedback for all buttons": "Vibrationsfeedback für Tasten ändern", "Most Secure Methods": "Sicherste Methoden", "In-App VOIP Calls": "In-App VOIP Anrufe", "Recorded Trips for Safety": "Aufgezeichnete Fahrten zur Sicherheit", "\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.": "\nWir bieten wettbewerbsfähige Preise.", "Intaleq is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:": "Intaleq ist eine Mitfahr-App für Ihre Sicherheit. Wir verbinden Sie mit zuverlässigen Fahrern.", "Sign In by Apple": "Mit Apple anmelden", "Sign In by Google": "Mit Google anmelden", "How do I request a ride?": "Wie bestelle ich eine Fahrt?", "Step-by-step instructions on how to request a ride through the Intaleq app.": "Schritt-für-Schritt-Anleitung zur Fahrtbestellung.", "What types of vehicles are available?": "Welche Fahrzeuge sind verfügbar?", "Intaleq offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.": "Intaleq bietet Economy, Komfort und Luxus.", "How can I pay for my ride?": "Wie kann ich bezahlen?", "Intaleq offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.": "Wählen Sie zwischen Barzahlung oder Karte.", "Can I cancel my ride?": "Kann ich stornieren?", "Yes, you can cancel your ride, but please note that cancellation fees may apply depending on how far in advance you cancel.": "Ja, Stornierung möglich, evtl. fallen Gebühren an.", "Driver Registration & Requirements": "Fahrer-Registrierung & Anforderungen", "How can I register as a driver?": "Wie registriere ich mich als Fahrer?", "What are the requirements to become a driver?": "Was sind die Anforderungen?", "Visit our website or contact Intaleq support for information on driver registration and requirements.": "Besuchen Sie unsere Website oder den Support.", "Intaleq provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.": "Intaleq bietet In-App-Chat.", "Intaleq prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.": "Sicherheit hat Priorität: Fahrerverifizierung, Tracking, Notruf.", "Frequently Questions": "Häufige Fragen", "User does not exist.": "Benutzer existiert nicht.", "We need your phone number to contact you and to help you.": "Wir benötigen Ihre Telefonnummer.", "You will recieve code in sms message": "Sie erhalten einen Code per SMS", "Please enter": "Bitte eingeben", "We need your phone number to contact you and to help you receive orders.": "Wir benötigen Ihre Nummer für Aufträge.", "The full name on your criminal record does not match the one on your driver's license. Please verify and provide the correct documents.": "Name im Führungszeugnis stimmt nicht mit Führerschein überein.", "The national number on your driver's license does not match the one on your ID document. Please verify and provide the correct documents.": "Ausweisnummer stimmt nicht überein.", "Capture an Image of Your Criminal Record": "Bild des Führungszeugnisses aufnehmen", "IssueDate": "Ausstellungsdatum", "Capture an Image of Your car license front": "Bild der Fahrzeugschein-Vorderseite", "Capture an Image of Your ID Document front": "Bild der Ausweis-Vorderseite", "NationalID": "Personalausweisnummer", "You can share the Intaleq App with your friends and earn rewards for rides they take using your code": "Teile die App und verdiene Belohnungen.", "FullName": "Vollständiger Name", "No invitation found yet!": "Keine Einladung gefunden!", "InspectionResult": "Prüfergebnis", "Criminal Record": "Führungszeugnis", "The email or phone number is already registered.": "E-Mail oder Nummer bereits registriert.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "Um Fahrer zu werden, laden Sie Führerschein, Ausweis und Fahrzeugschein hoch. KI prüft in 2-3 Min. Betrug führt zur Kündigung.", "Documents check": "Dokumentenprüfung", "Driver's License": "Führerschein", "for your first registration!": "für Ihre erste Registrierung!", "Get it Now!": "Jetzt holen!", "before": "vor", "Code not approved": "Code nicht genehmigt", "3000 LE": "30 €", "Do you have an invitation code from another driver?": "Haben Sie einen Einladungscode?", "Paste the code here": "Code hier einfügen", "No, I don't have a code": "Nein, kein Code", "Code approved": "Code genehmigt", "Install our app:": "App installieren:", "Invite another driver and both get a gift after he completes 100 trips!": "Lade einen Fahrer ein und erhalte ein Geschenk nach 100 Fahrten!", "Invite": "Einladen", "Are you sure?": "Sind Sie sicher?", "This will delete all recorded files from your device.": "Dies löscht alle Aufnahmen vom Gerät.", "Select a file": "Datei auswählen", "Select a File": "Datei auswählen", "Delete": "Löschen", "attach audio of complain": "Beschwerde-Audio anhängen", "Phone Number Check": "Telefonnummer-Prüfung", "Drivers received orders": "Fahrer haben Aufträge erhalten", "No audio files recorded.": "Keine Audioaufnahmen.", "This is for delivery or a motorcycle.": "Dies ist für Lieferung oder Motorrad.", "Intaleq Reminder": "Intaleq Erinnerung", "It's time to check the Intaleq app!": "Zeit, die Intaleq App zu prüfen!", "you must insert token code": "Token-Code eingeben", "Something went wrong. Please try again.": "Etwas ist schiefgelaufen. Bitte erneut versuchen.", "Trip Details": "Fahrtdetails", "The context does not provide any complaint details, so I cannot provide a solution to this issue. Please provide the necessary information, and I will be happy to assist you.": "Keine Beschwerdedetails. Bitte Infos bereitstellen.", "Submit Your Complaint": "Beschwerde einreichen", "Status": "Status", "Choose from contact": "Aus Kontakten wählen", "attach correct audio": "korrektes Audio anhängen", "be sure": "sicher sein", "Audio uploaded successfully.": "Audio erfolgreich hochgeladen.", "Perfect for passengers seeking the latest car models with the freedom to choose any route they desire": "Perfekt für Fahrgäste, die neue Autos und freie Routenwahl suchen", "Share this code with your friends and earn rewards when they use it!": "Code teilen und Belohnungen verdienen!", "Enter phone": "Telefon eingeben", "complete, you can claim your gift": "abgeschlossen, Geschenk abholen", "When": "Wenn", "Enter driver's phone": "Fahrer-Telefon eingeben", "Send Invite": "Einladung senden", "Show Invitations": "Einladungen anzeigen", "License Type": "Lizenztyp", "National Number": "Personalausweisnummer", "Name (Arabic)": "Name (Arabisch)", "Name (English)": "Name (Englisch)", "Address": "Adresse", "Issue Date": "Ausstellungsdatum", "Expiry Date": "Ablaufdatum", "License Categories": "Führerscheinklassen", "driver_license": "Führerschein", "Capture an Image of Your Driver License": "Bild des Führerscheins aufnehmen", "ID Documents Back": "Ausweis Rückseite", "National ID": "Personalausweis", "Occupation": "Beruf", "Religion": "Religion", "Full Name (Marital)": "Vollständiger Name", "Expiration Date": "Ablaufdatum", "Capture an Image of Your ID Document Back": "Bild der Ausweis-Rückseite", "ID Documents Front": "Ausweis Vorderseite", "First Name": "Vorname", "CardID": "Kartennummer", "Vehicle Details Front": "Fahrzeugdetails Vorne", "Plate Number": "Kennzeichen", "Owner Name": "Haltername", "Vehicle Details Back": "Fahrzeugdetails Hinten", "Make": "Marke", "Model": "Modell", "Year": "Jahr", "Chassis": "Fahrgestellnummer", "Color": "Farbe", "Displacement": "Hubraum", "Fuel": "Kraftstoff", "Tax Expiry Date": "Steuer-Ablaufdatum", "Inspection Date": "Inspektionsdatum", "Capture an Image of Your car license back": "Bild der Fahrzeugschein-Rückseite", "Capture an Image of Your Driver's License": "Bild des Führerscheins", "Sign in with Google for easier email and name entry": "Mit Google anmelden für einfachere Eingabe", "You will choose allow all the time to be ready receive orders": "Wählen Sie 'Immer erlauben', um Aufträge zu erhalten", "Get to your destination quickly and easily.": "Schnell und einfach ans Ziel.", "Enjoy a safe and comfortable ride.": "Sichere und komfortable Fahrt genießen.", "Choose Language": "Sprache wählen", "Pay with Wallet": "Mit Wallet zahlen", "Invalid MPIN": "Ungültige MPIN", "Invalid OTP": "Ungültiger OTP", "Enter your email address": "E-Mail eingeben", "Please enter Your Email.": "Bitte E-Mail eingeben.", "Enter your phone number": "Telefonnummer eingeben", "Please enter your phone number.": "Bitte Telefonnummer eingeben.", "Please enter Your Password.": "Bitte Passwort eingeben.", "if you dont have account": "wenn Sie kein Konto haben", "Register": "Registrieren", "Accept Ride's Terms & Review Privacy Notice": "Bedingungen & Datenschutz akzeptieren", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "Ich akzeptiere die Bedingungen und Datenschutzrichtlinien. Ich bin 18+.", "First name": "Vorname", "Enter your first name": "Vorname eingeben", "Please enter your first name.": "Bitte Vorname eingeben.", "Last name": "Nachname", "Enter your last name": "Nachname eingeben", "Please enter your last name.": "Bitte Nachname eingeben.", "City": "Stadt", "Please enter your City.": "Bitte Stadt eingeben.", "Verify Email": "E-Mail verifizieren", "We sent 5 digit to your Email provided": "Wir haben 5 Ziffern an Ihre E-Mail gesendet", "5 digit": "5 Ziffern", "Send Verification Code": "Verifizierungscode senden", "Your Ride Duration is ": "Ihre Fahrtdauer beträgt ", "You will be thier in": "Sie sind dort in", "You trip distance is": "Fahrtdistanz ist", "Fee is": "Gebühr ist", "From : ": "Von: ", "To : ": "Nach: ", "Add Promo": "Promo hinzufügen", "Confirm Selection": "Auswahl bestätigen", "distance is": "Distanz ist", "Privacy Policy": "Datenschutzerklärung", "Intaleq LLC": "Intaleq LLC", "Syria's pioneering ride-sharing service, proudly developed by Arabian and local owners. We prioritize being near you – both our valued passengers and our dedicated captains.": "Deutschlands wegweisender Mitfahrdienst.", "Intaleq is the first ride-sharing app in Syria, designed to connect you with the nearest drivers for a quick and convenient travel experience.": "Intaleq verbindet Sie mit den nächsten Fahrern.", "Why Choose Intaleq?": "Warum Intaleq?", "Closest to You": "Am nächsten zu Ihnen", "We connect you with the nearest drivers for faster pickups and quicker journeys.": "Wir verbinden Sie mit den nächsten Fahrern.", "Uncompromising Security": "Kompromisslose Sicherheit", "Lady Captains Available": "Fahrerinnen verfügbar", "Recorded Trips (Voice & AI Analysis)": "Aufgezeichnete Fahrten (Stimme & KI)", "Fastest Complaint Response": "Schnellste Beschwerdeantwort", "Our dedicated customer service team ensures swift resolution of any issues.": "Unser Kundenservice löst Probleme schnell.", "Affordable for Everyone": "Erschwinglich für alle", "Frequently Asked Questions": "Häufig gestellte Fragen", "Getting Started": "Erste Schritte", "Simply open the Intaleq app, enter your destination, and tap \"Request Ride\". The app will connect you with a nearby driver.": "Öffnen Sie Intaleq, geben Sie das Ziel ein und tippen Sie auf 'Fahrt anfordern'.", "Vehicle Options": "Fahrzeugoptionen", "Intaleq offers a variety of options including Economy, Comfort, and Luxury to suit your needs and budget.": "Intaleq bietet Economy, Komfort und Luxus.", "Payments": "Zahlungen", "You can pay for your ride using cash or credit/debit card. You can select your preferred payment method before confirming your ride.": "Zahlen Sie bar oder mit Karte.", "Ride Management": "Fahrtmanagement", "Yes, you can cancel your ride, but please note that cancellation fees may apply depending on how far in advance you cancel.": "Stornierung möglich, Gebühren können anfallen.", "For Drivers": "Für Fahrer", "Driver Registration": "Fahrer-Registrierung", "To register as a driver or learn about the requirements, please visit our website or contact Intaleq support directly.": "Besuchen Sie die Website oder kontaktieren Sie den Support.", "Visit Website/Contact Support": "Website besuchen / Support kontaktieren", "Close": "Schließen", "We are searching for the nearest driver": "Wir suchen den nächsten Fahrer", "Communication": "Kommunikation", "How do I communicate with the other party (passenger/driver)?": "Wie kommuniziere ich mit dem Fahrer/Fahrgast?", "You can communicate with your driver or passenger through the in-app chat feature once a ride is confirmed.": "Nutzen Sie den In-App-Chat nach Bestätigung.", "Safety & Security": "Sicherheit", "What safety measures does Intaleq offer?": "Welche Sicherheitsmaßnahmen bietet Intaleq?", "Intaleq offers various safety features including driver verification, in-app trip tracking, emergency contact options, and the ability to share your trip status with trusted contacts.": "Intaleq bietet Fahrerverifizierung, Tracking und Notrufe.", "Enjoy competitive prices across all trip options, making travel accessible.": "Genießen Sie wettbewerbsfähige Preise.", "Variety of Trip Choices": "Vielfalt an Fahrtoptionen", "Choose the trip option that perfectly suits your needs and preferences.": "Wählen Sie die passende Option.", "Your Choice, Our Priority": "Ihre Wahl, unsere Priorität", "Because we are near, you have the flexibility to choose the ride that works best for you.": "Flexibilität bei der Wahl der Fahrt.", "duration is": "Dauer ist", "Setting": "Einstellung", "Find answers to common questions": "Antworten auf häufige Fragen finden", "I don't need a ride anymore": "Ich brauche keine Fahrt mehr", "I was just trying the application": "Ich habe die App nur ausprobiert", "No driver accepted my request": "Kein Fahrer hat angenommen", "I added the wrong pick-up/drop-off location": "Falscher Ort eingegeben", "I don't have a reason": "Kein Grund", "Can we know why you want to cancel Ride ?": "Warum möchten Sie stornieren?", "Cancel Ride": "Fahrt stornieren", "Add Payment Method": "Zahlungsmethode hinzufügen", "Ride Wallet": "Fahrt-Wallet", "Payment Method": "Zahlungsmethode", "Type here Place": "Ort hier eingeben", "Are You sure to ride to": "Sind Sie sicher, nach ... zu fahren", "Confirm": "Bestätigen", "You are Delete": "Sie löschen", "Deleted": "Gelöscht", "You Dont Have Any places yet !": "Noch keine Orte gespeichert!", "From : Current Location": "Von: Aktueller Standort", "My Cared": "Meine Karten", "Add Card": "Karte hinzufügen", "Add Credit Card": "Kreditkarte hinzufügen", "Please enter the cardholder name": "Karteninhaber eingeben", "Please enter the expiry date": "Ablaufdatum eingeben", "Please enter the CVV code": "CVV-Code eingeben", "Go To Favorite Places": "Zu Lieblingsorten", "Go to this Target": "Zu diesem Ziel", "My Profile": "Mein Profil", "Are you want to go to this site": "Möchten Sie zu diesem Ort?", "MyLocation": "MeinStandort", "my location": "mein Standort", "Target": "Ziel", "You Should choose rate figure": "Sie sollten eine Bewertung wählen", "Login Captin": "Fahrer Login", "Register Captin": "Fahrer Registrierung", "Send Verfication Code": "Verifizierungscode senden", "KM": "KM", "End Ride": "Fahrt beenden", "Minute": "Minute", "Go to passenger Location now": "Zum Fahrgaststandort fahren", "Duration of the Ride is ": "Fahrtdauer ist ", "Distance of the Ride is ": "Fahrtdistanz ist ", "Name of the Passenger is ": "Name des Fahrgastes ist ", "Hello this is Captain": "Hallo, hier spricht der Fahrer", "Start the Ride": "Fahrt starten", "Please Wait If passenger want To Cancel!": "Bitte warten, falls Fahrgast stornieren will!", "Total Duration:": "Gesamtdauer:", "Active Duration:": "Aktive Dauer:", "Waiting for Captin ...": "Warten auf Fahrer...", "Age is ": "Alter ist ", "Rating is ": "Bewertung ist ", " to arrive you.": " um anzukommen.", "Tariff": "Tarif", "Settings": "Einstellungen", "Feed Back": "Feedback", "Please enter a valid 16-digit card number": "Bitte gültige 16-stellige Kartennummer eingeben", "Add Phone": "Telefon hinzufügen", "Please enter a phone number": "Bitte Telefonnummer eingeben", "You dont Add Emergency Phone Yet!": "Noch keine Notrufnummer hinzugefügt!", "You will arrive to your destination after ": "Sie kommen an in ", "You can cancel Ride now": "Sie können die Fahrt jetzt stornieren", "You Can cancel Ride After Captain did not come in the time": "Stornierung möglich, wenn Fahrer nicht rechtzeitig kommt", "If you in Car Now. Press Start The Ride": "Wenn Sie im Auto sind, drücken Sie Start", "You Dont Have Any amount in": "Sie haben kein Guthaben in", "Wallet!": "Wallet!", "You Have": "Sie haben", "Save Credit Card": "Kreditkarte speichern", "Show Promos": "Promos anzeigen", "10 and get 4% discount": "10 und erhalte 4% Rabatt", "20 and get 6% discount": "20 und erhalte 6% Rabatt", "40 and get 8% discount": "40 und erhalte 8% Rabatt", "100 and get 11% discount": "100 und erhalte 11% Rabatt", "Pay with Your PayPal": "Mit PayPal zahlen", "You will choose one of above !": "Bitte oben auswählen!", "Edit Profile": "Profil bearbeiten", "Copy this Promo to use it in your Ride!": "Promo kopieren und nutzen!", "To change some Settings": "Um Einstellungen zu ändern", "Order Request Page": "Auftragsanfrageseite", "Rouats of Trip": "Routen der Fahrt", "Passenger Name is ": "Fahrgastname ist ", "Total From Passenger is ": "Gesamt vom Fahrgast ist ", "Duration To Passenger is ": "Dauer zum Fahrgast ist ", "Distance To Passenger is ": "Distanz zum Fahrgast ist ", "Total For You is ": "Gesamt für Sie ist ", "Distance is ": "Distanz ist ", " KM": " KM", "Duration of Trip is ": "Fahrtdauer ist ", " Minutes": " Minuten", "Apply Order": "Auftrag annehmen", "Refuse Order": "Auftrag ablehnen", "Rate Captain": "Fahrer bewerten", "Enter your Note": "Notiz eingeben", "Type something...": "Etwas eingeben...", "Submit rating": "Bewertung absenden", "Rate Passenger": "Fahrgast bewerten", "Ride Summary": "Fahrtzusammenfassung", "welcome_message": "Willkommen bei Intaleq!", "app_description": "Intaleq ist eine sichere und zuverlässige Mitfahr-App.", "get_to_destination": "Kommen Sie schnell ans Ziel.", "get_a_ride": "Mit Intaleq in Minuten eine Fahrt bekommen.", "safe_and_comfortable": "Genießen Sie eine sichere Fahrt.", "committed_to_safety": "Intaleq engagiert sich für Sicherheit.", "your ride is Accepted": "Ihre Fahrt wurde angenommen", "Driver is waiting at pickup.": "Fahrer wartet am Abholort.", "Driver is on the way": "Fahrer ist auf dem Weg", "Contact Options": "Kontaktoptionen", "Send a custom message": "Benutzerdefinierte Nachricht senden", "Type your message": "Nachricht eingeben", "I will go now": "Ich gehe jetzt", "You Have Tips": "Sie haben Trinkgeld", " tips\nTotal is": " Trinkgeld\nGesamt ist", "Your fee is ": "Ihre Gebühr ist ", "Do you want to pay Tips for this Driver": "Möchten Sie Trinkgeld geben?", "Tip is ": "Trinkgeld ist ", "Are you want to wait drivers to accept your order": "Wollen Sie warten, bis Fahrer annehmen?", "This price is fixed even if the route changes for the driver.": "Festpreis, auch bei Routenänderung.", "The price may increase if the route changes.": "Preis kann bei Routenänderung steigen.", "The captain is responsible for the route.": "Der Fahrer ist für die Route verantwortlich.", "We are search for nearst driver": "Wir suchen den nächsten Fahrer", "Your order is being prepared": "Ihr Auftrag wird vorbereitet", "The drivers are reviewing your request": "Fahrer prüfen Ihre Anfrage", "Your order sent to drivers": "Auftrag an Fahrer gesendet", "You can call or record audio of this trip": "Sie können anrufen oder aufnehmen", "The trip has started! Feel free to contact emergency numbers, share your trip, or activate voice recording for the journey": "Fahrt gestartet! Notruf, Teilen oder Aufnahme möglich.", "Camera Access Denied.": "Kamerazugriff verweigert.", "Open Settings": "Einstellungen öffnen", "GPS Required Allow !.": "GPS erforderlich, bitte erlauben!", "Your Account is Deleted": "Ihr Konto wurde gelöscht", "Are you sure to delete your account?": "Konto wirklich löschen?", "Your data will be erased after 2 weeks\nAnd you will can't return to use app after 1 month ": "Daten werden nach 2 Wochen gelöscht\nApp-Nutzung nach 1 Monat nicht mehr möglich", "Enter Your First Name": "Vorname eingeben", "Are you Sure to LogOut?": "Wirklich abmelden?", "Email Wrong": "E-Mail falsch", "Email you inserted is Wrong.": "Eingegebene E-Mail ist falsch.", "You have finished all times ": "Alle Versuche aufgebraucht", "if you want help you can email us here": "Hilfe per E-Mail hier", "Thanks": "Danke", "Email Us": "E-Mail senden", "I cant register in your app in face detection ": "Registrierung bei Gesichtserkennung fehlgeschlagen", "Hi": "Hallo", "No face detected": "Kein Gesicht erkannt", "Image detecting result is ": "Ergebnis der Bilderkennung ist ", "from 3 times Take Attention": "von 3 Malen, Achtung", "Be sure for take accurate images please\nYou have": "Bitte genaue Bilder machen\nSie haben", "image verified": "Bild verifiziert", "Next": "Weiter", "There is no help Question here": "Keine Hilfe-Frage hier", "You dont have Points": "Sie haben keine Punkte", "You Are Stopped For this Day !": "Sie sind für heute gesperrt!", "You must be charge your Account": "Sie müssen Ihr Konto aufladen", "You Refused 3 Rides this Day that is the reason \nSee you Tomorrow!": "Sie haben 3 Fahrten abgelehnt \nBis morgen!", "Recharge my Account": "Mein Konto aufladen", "Ok , See you Tomorrow": "Ok, bis morgen", "You are Stopped": "Sie sind gesperrt", "Connected": "Verbunden", "Not Connected": "Nicht verbunden", "Your are far from passenger location": "Sie sind weit vom Fahrgast entfernt", "go to your passenger location before\nPassenger cancel trip": "Zum Fahrgast fahren bevor\ner storniert", "You will get cost of your work for this trip": "Sie erhalten die Kosten für diese Fahrt", " in your wallet": " in Ihrer Wallet", "you gain": "Sie gewinnen", "Order Cancelled by Passenger": "Auftrag vom Fahrgast storniert", "Feedback data saved successfully": "Feedback gespeichert", "No Promo for today .": "Keine Promo für heute.", "Select your destination": "Ziel auswählen", "Search for your Start point": "Startpunkt suchen", "Search for waypoint": "Wegpunkt suchen", "Current Location": "Aktueller Standort", "Add Location 1": "Ort 1 hinzufügen", "You must Verify email !.": "E-Mail verifizieren!", "Cropper": "Zuschneiden", "Saved Sucssefully": "Erfolgreich gespeichert", "Select Date": "Datum wählen", "Birth Date": "Geburtsdatum", "Ok": "Ok", "the 500 points equal 30 JOD": "500 Punkte entsprechen 30 €", "the 500 points equal 30 JOD for you \nSo go and gain your money": "500 Punkte sind 30 € für Sie \nVerdienen Sie Ihr Geld", "token updated": "Token aktualisiert", "Add Location 2": "Ort 2 hinzufügen", "Add Location 3": "Ort 3 hinzufügen", "Add Location 4": "Ort 4 hinzufügen", "Waiting for your location": "Warten auf Standort", "Search for your destination": "Ziel suchen", "Hi! This is": "Hallo! Hier ist", " I am using": " Ich nutze", " to ride with": " um zu fahren mit", " as the driver.": " als Fahrer.", "is driving a ": "fährt einen ", " with license plate ": " mit Kennzeichen ", " I am currently located at ": " Ich befinde mich bei ", "Please go to Car now ": "Bitte zum Auto gehen ", "You will receive a code in WhatsApp Messenger": "Sie erhalten einen Code per WhatsApp", "If you need assistance, contact us": "Bei Fragen kontaktieren Sie uns", "Promo Ended": "Promo beendet", "Enter the promo code and get": "Promo-Code eingeben und erhalten", "DISCOUNT": "RABATT", "No wallet record found": "Kein Wallet-Eintrag gefunden", "for": "für", "Intaleq is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.": "Intaleq ist sicherste Mitfahr-App mit vielen Features. Niedrigste Provision von 8%.", "You can contact us during working hours from 12:00 - 19:00.": "Kontaktieren Sie uns von 12:00 - 19:00 Uhr.", "Choose a contact option": "Kontaktoption wählen", "Work time is from 12:00 - 19:00.\nYou can send a WhatsApp message or email.": "Arbeitszeit 12:00 - 19:00 Uhr.\nWhatsApp oder E-Mail senden.", "Promo code copied to clipboard!": "Promo-Code kopiert!", "Copy Code": "Code kopieren", "Your invite code was successfully applied!": "Einladungscode erfolgreich angewendet!", "Payment Options": "Zahlungsoptionen", "wait 1 minute to receive message": "1 Minute auf Nachricht warten", "You have copied the promo code.": "Sie haben den Code kopiert.", "Select Payment Amount": "Zahlungsbetrag wählen", "The promotion period has ended.": "Promotionszeitraum beendet.", "Promo Code Accepted": "Promo-Code akzeptiert", "Tap on the promo code to copy it!": "Tippen zum Kopieren!", "Lowest Price Achieved": "Niedrigster Preis erreicht", "Cannot apply further discounts.": "Keine weiteren Rabatte möglich.", "Promo Already Used": "Promo bereits genutzt", "Invitation Used": "Einladung genutzt", "You have already used this promo code.": "Code bereits verwendet.", "Insert Your Promo Code": "Promo-Code eingeben", "Enter promo code here": "Promo-Code hier eingeben", "Please enter a valid promo code": "Bitte gültigen Code eingeben", "Awfar Car": "Spar-Auto", "Old and affordable, perfect for budget rides.": "Alt und günstig, perfekt für Budget-Fahrten.", " If you need to reach me, please contact the driver directly at": " Um mich zu erreichen, kontaktieren Sie den Fahrer unter", "No Car or Driver Found in your area.": "Kein Auto oder Fahrer in Ihrer Nähe.", "Please Try anther time ": "Bitte später versuchen ", "There no Driver Aplly your order sorry for that ": "Kein Fahrer hat angenommen, tut uns leid ", "Trip Cancelled": "Fahrt storniert", "The Driver Will be in your location soon .": "Fahrer ist bald da.", "The distance less than 500 meter.": "Distanz weniger als 500 Meter.", "Promo End !": "Promo Ende!", "There is no notification yet": "Noch keine Benachrichtigung", "Use Touch ID or Face ID to confirm payment": "Touch ID oder Face ID zur Bestätigung nutzen", "Contact us for any questions on your order.": "Kontaktieren Sie uns bei Fragen.", "Pyament Cancelled .": "Zahlung abgebrochen.", "type here": "hier tippen", "Scan Driver License": "Führerschein scannen", "Please put your licence in these border": "Führerschein in den Rahmen legen", "Camera not initialized yet": "Kamera noch nicht initialisiert", "Take Image": "Bild aufnehmen", "AI Page": "KI-Seite", "Take Picture Of ID Card": "Bild des Ausweises machen", "Take Picture Of Driver License Card": "Bild des Führerscheins machen", "We are process picture please wait ": "Bild wird verarbeitet, bitte warten ", "There is no data yet.": "Noch keine Daten.", "Name :": "Name:", "Drivers License Class: ": "Führerscheinklasse:", "Document Number: ": "Dokumentennummer:", "Address: ": "Adresse:", "Height: ": "Größe:", "Expiry Date: ": "Ablaufdatum:", "Date of Birth: ": "Geburtsdatum:", "You can't continue with us .\nYou should renew Driver license": "Sie können nicht fortfahren.\nFührerschein erneuern", "Detect Your Face ": "Gesicht erkennen ", "Go to next step\nscan Car License.": "Nächster Schritt\nFahrzeugschein scannen.", "Name in arabic": "Name auf Arabisch", "Drivers License Class": "Führerscheinklasse", "Selected Date": "Ausgewähltes Datum", "Select Time": "Zeit wählen", "Selected Time": "Ausgewählte Zeit", "Selected Date and Time": "Ausgewähltes Datum und Zeit", "Lets check Car license ": "Fahrzeugschein prüfen ", "Car": "Auto", "Plate": "Kennzeichen", "Rides": "Fahrten", "Selected driver": "Ausgewählter Fahrer", "Lets check License Back Face": "Rückseite prüfen", "Car License Card": "Fahrzeugschein", "No image selected yet": "Kein Bild ausgewählt", "Made :": "Marke:", "model :": "Modell:", "VIN :": "FIN:", "year :": "Jahr:", "ُExpire Date": "Ablaufdatum", "Login Driver": "Fahrer Login", "Password must br at least 6 character.": "Passwort muss mind. 6 Zeichen haben.", "if you don't have account": "wenn Sie kein Konto haben", "Here recorded trips audio": "Hier aufgezeichnete Fahrten-Audios", "Register as Driver": "Als Fahrer registrieren", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the ": "Durch Auswahl von \"Ich stimme zu\" akzeptiere ich die Nutzungsbedingungen und ", "Log Out Page": "Abmeldeseite", "Log Off": "Abmelden", "Register Driver": "Fahrer registrieren", "Verify Email For Driver": "E-Mail für Fahrer verifizieren", "Admin DashBoard": "Admin-Dashboard", "Your name": "Ihr Name", "your ride is applied": "Ihre Fahrt wurde beantragt", "H and": "S und", "JOD": "€", "m": "m", "We search nearst Driver to you": "Wir suchen den nächsten Fahrer", "please wait till driver accept your order": "bitte warten bis Fahrer annimmt", "No accepted orders? Try raising your trip fee to attract riders.": "Keine Annahme? Preis erhöhen.", "You should select one": "Sie sollten eins wählen", "The driver accept your order for": "Der Fahrer akzeptiert Ihren Auftrag für", "The driver on your way": "Fahrer ist auf dem Weg", "Total price from ": "Gesamtpreis von ", "Order Details Intaleq": "Auftragsdetails Intaleq", "Selected file:": "Ausgewählte Datei:", "Your trip cost is": "Ihre Fahrtkosten sind", "this will delete all files from your device": "dies löscht alle Dateien vom Gerät", "Exclusive offers and discounts always with the Intaleq app": "Exklusive Angebote mit Intaleq", "Submit Question": "Frage absenden", "Please enter your Question.": "Bitte Frage eingeben.", "Help Details": "Hilfe-Details", "No trip yet found": "Noch keine Fahrt gefunden", "No Response yet.": "Noch keine Antwort.", " You Earn today is ": " Ihr Verdienst heute ist ", " You Have in": " Sie haben in", "Total points is ": "Gesamtpunkte sind ", "Total Connection Duration:": "Gesamtverbindungsdauer:", "Passenger name : ": "Fahrgastname: ", "Cost Of Trip IS ": "Fahrtkosten sind ", "Arrival time": "Ankunftszeit", "arrival time to reach your point": "Ankunftszeit am Punkt", "For Intaleq and scooter trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Intaleq/Scooter: dynamisch. Komfort: Zeit/Distanz.", "Hello this is Driver": "Hallo, hier ist der Fahrer", "Is the Passenger in your Car ?": "Ist der Fahrgast im Auto?", "Please wait for the passenger to enter the car before starting the trip.": "Bitte warten bis Fahrgast einsteigt.", "No ,still Waiting.": "Nein, warte noch.", "I arrive you": "Ich bin da", "I Arrive your site": "Ich bin am Standort", "You are not in near to passenger location": "Nicht in der Nähe des Fahrgastes", "please go to picker location exactly": "bitte genau zum Abholort fahren", "You Can Cancel Trip And get Cost of Trip From": "Sie können stornieren und Kosten erhalten von", "Are you sure to cancel?": "Wirklich stornieren?", "Insert Emergincy Number": "Notrufnummer eingeben", "Best choice for comfort car and flexible route and stops point": "Beste Wahl für Komfort und Flexibilität", "Insert": "Einfügen", "This is for scooter or a motorcycle.": "Dies ist für Scooter oder Motorrad.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "Direktfahrt zum Festpreis. Fahrer muss Route folgen.", "You can decline a request without any cost": "Ablehnen ohne Kosten möglich", "Perfect for adventure seekers who want to experience something new and exciting": "Perfekt für Abenteurer", "My current location is:": "Mein Standort ist:", "and I have a trip on": "und ich habe eine Fahrt auf", "App with Passenger": "App mit Fahrgast", "You will be pay the cost to driver or we will get it from you on next trip": "Zahlen Sie den Fahrer oder wir ziehen es beim nächsten Mal ein", "Trip has Steps": "Fahrt hat Zwischenstopps", "Distance from Passenger to destination is ": "Entfernung Fahrgast zum Ziel ist ", "price is": "Preis ist", "This ride type does not allow changes to the destination or additional stops": "Keine Änderungen erlaubt", "This price may be changed": "Preis kann sich ändern", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "Keine SIM? Anruf über App möglich.", "This ride type allows changes, but the price may increase": "Änderungen erlaubt, Preis kann steigen", "Select one message": "Eine Nachricht wählen", "I'm waiting for you": "Ich warte auf Sie", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "Geschwindigkeit über 100 km/h. Bitte langsamer fahren.", "Warning: Intaleqing detected!": "Warnung: Zu schnell!", "Please help! Contact me as soon as possible.": "Hilfe! Kontaktieren Sie mich sofort.", "Share Trip Details": "Fahrtdetails teilen", "Car Plate is ": "Kennzeichen ist ", "the 300 points equal 300 L.E for you \nSo go and gain your money": "300 Punkte sind 300 € für Sie \nVerdienen Sie Ihr Geld", "the 300 points equal 300 L.E": "300 Punkte sind 300 €", "The payment was not approved. Please try again.": "Zahlung nicht genehmigt. Bitte erneut versuchen.", "Payment Failed": "Zahlung fehlgeschlagen", "This is a scheduled notification.": "Geplante Benachrichtigung.", "An error occurred during the payment process.": "Fehler beim Zahlungsprozess.", "The payment was approved.": "Zahlung genehmigt.", "Payment Successful": "Zahlung erfolgreich", "No ride found yet": "Noch keine Fahrt gefunden", "Accept Order": "Auftrag annehmen", "Bottom Bar Example": "Beispiel untere Leiste", "Driver phone": "Fahrer-Telefon", "Statistics": "Statistiken", "Origin": "Start", "Destination": "Ziel", "Driver Name": "Fahrername", "Driver Car Plate": "Fahrer-Kennzeichen", "Available for rides": "Verfügbar für Fahrten", "Scan Id": "Ausweis scannen", "Camera not initilaized yet": "Kamera nicht initialisiert", "Scan ID MklGoogle": "ID MklGoogle scannen", "Language": "Sprache", "Jordan": "Jordanien", "USA": "USA", "Egypt": "Ägypten", "Turkey": "Türkei", "Saudi Arabia": "Saudi-Arabien", "Qatar": "Katar", "Bahrain": "Bahrain", "Kuwait": "Kuwait", "But you have a negative salary of": "Aber Sie haben ein negatives Gehalt von", "Promo Code": "Promo-Code", "Your trip distance is": "Ihre Fahrtdistanz ist", "Enter promo code": "Promo-Code eingeben", "You have promo!": "Sie haben eine Promo!", "Cost Duration": "Kostendauer", "Duration is": "Dauer ist", "Leave": "Verlassen", "Join": "Beitreten", "Heading your way now. Please be ready.": "Ich komme. Bitte bereit sein.", "Approaching your area. Should be there in 3 minutes.": "In der Nähe. In 3 Minuten da.", "There's heavy traffic here. Can you suggest an alternate pickup point?": "Viel Verkehr. Anderen Abholort vorschlagen?", "This ride is already taken by another driver.": "Fahrt bereits vergeben.", "You Should be select reason.": "Grund auswählen.", "Waiting for Driver ...": "Warten auf Fahrer...", "Latest Recent Trip": "Letzte Fahrt", "from your list": "aus Ihrer Liste", "Do you want to change Work location": "Arbeitsort ändern", "Do you want to change Home location": "Wohnort ändern", "We Are Sorry That we dont have cars in your Location!": "Keine Autos in Ihrer Gegend!", "Choose from Map": "Von Karte wählen", "Pick your ride location on the map - Tap to confirm": "Ort auf Karte wählen - Tippen zum Bestätigen", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq ist sicher und zuverlässig.", "With Intaleq, you can get a ride to your destination in minutes.": "In Minuten ans Ziel mit Intaleq.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Sicherheit verpflichtet: Alle Fahrer geprüft.", "Pick from map": "Von Karte wählen", "No Car in your site. Sorry!": "Kein Auto an Ihrem Standort. Sorry!", "Nearest Car for you about ": "Nächstes Auto in ca. ", "From :": "Von:", "Get Details of Trip": "Fahrtdetails abrufen", "If you want add stop click here": "Für Zwischenstopp hier klicken", "Where you want go ": "Wohin wollen Sie ", "My Card": "Meine Karte", "Start Record": "Aufnahme starten", "History of Trip": "Fahrtverlauf", "Helping Center": "Hilfe-Center", "Record saved": "Aufnahme gespeichert", "Trips recorded": "Aufgezeichnete Fahrten", "Select Your Country": "Land wählen", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "Bitte wählen Sie Ihr Land für genaue Informationen.", "Are you sure to delete recorded files": "Aufnahmen wirklich löschen?", "Select recorded trip": "Aufgezeichnete Fahrt wählen", "Card Number": "Kartennummer", "Hi, Where to ": "Hallo, wohin ", "Pick your destination from Map": "Ziel auf Karte wählen", "Add Stops": "Stopps hinzufügen", "Get Direction": "Route abrufen", "Add Location": "Ort hinzufügen", "Switch Rider": "Fahrgast wechseln", "You will arrive to your destination after timer end.": "Ankunft nach Timer-Ende.", "You can cancel trip": "Sie können stornieren", "The driver waitting you in picked location .": "Fahrer wartet am Abholort.", "Pay with Your": "Zahlen mit", "Pay with Credit Card": "Mit Kreditkarte zahlen", "Show Promos to Charge": "Promos zum Aufladen zeigen", "Point": "Punkt", "How many hours would you like to wait?": "Wie viele Stunden warten?", "Driver Wallet": "Fahrer-Wallet", "Choose between those Type Cars": "Fahrzeugtyp wählen", "hour": "Stunde", "Select Waiting Hours": "Wartezeit wählen", "Total Points is": "Gesamtpunkte sind", "You will receive a code in SMS message": "Sie erhalten SMS-Code", "Done": "Fertig", "Total Budget from trips is ": "Gesamtbudget aus Fahrten ist ", "Total Amount:": "Gesamtbetrag:", "Total Budget from trips by\nCredit card is ": "Gesamtbudget per\nKreditkarte ist ", "This amount for all trip I get from Passengers": "Betrag von Fahrgästen", "Pay from my budget": "Vom Budget zahlen", "This amount for all trip I get from Passengers and Collected For me in": "Gesammelter Betrag in", "You can buy points from your budget": "Punkte vom Budget kaufen", "insert amount": "Betrag eingeben", "You can buy Points to let you online\nby this list below": "Punkte kaufen, um online zu bleiben\nüber Liste unten", "Create Wallet to receive your money": "Wallet erstellen für Geldempfang", "Enter your feedback here": "Feedback hier eingeben", "Please enter your feedback.": "Bitte Feedback eingeben.", "Feedback": "Feedback", "Submit ": "Absenden ", "Click here to Show it in Map": "Hier klicken für Karte", "Canceled": "Storniert", "No I want": "Nein ich will", "Email is": "E-Mail ist:", "Phone Number is": "Telefonnummer ist:", "Date of Birth is": "Geburtsdatum ist:", "Sex is ": "Geschlecht ist: ", "Car Details": "Fahrzeugdetails", "VIN is": "FIN ist:", "Color is ": "Farbe ist: ", "Make is ": "Marke ist: ", "Model is": "Modell ist:", "Year is": "Jahr ist:", "Expiration Date ": "Ablaufdatum: ", "Edit Your data": "Daten bearbeiten", "write vin for your car": "FIN eingeben", "VIN": "FIN", "Device Change Detected": "Gerätewechsel erkannt", "Please verify your identity": "Identität verifizieren", "write Color for your car": "Farbe eingeben", "write Make for your car": "Marke eingeben", "write Model for your car": "Modell eingeben", "write Year for your car": "Jahr eingeben", "write Expiration Date for your car": "Ablaufdatum eingeben", "Tariffs": "Tarife", "Minimum fare": "Mindestfahrpreis", "Maximum fare": "Höchstfahrpreis", "Flag-down fee": "Grundgebühr", "Including Tax": "Inkl. Steuer", "BookingFee": "Buchungsgebühr", "Morning": "Morgen", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "von 07:30 bis 10:30", "Evening": "Abend", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "von 12:00 bis 15:00", "Night": "Nacht", "You have in account": "Sie haben auf dem Konto", "Select Country": "Land wählen", "Ride Today : ": "Fahrt heute: ", "After this period\nYou can't cancel!": "Nach dieser Zeit\nkeine Stornierung möglich!", "from 23:59 till 05:30": "von 23:59 bis 05:30", "Rate Driver": "Fahrer bewerten", "Total Cost is ": "Gesamtkosten sind ", "Write note": "Notiz schreiben", "Time to arrive": "Ankunftszeit", "Ride Summaries": "Fahrtzusammenfassungen", "Total Cost": "Gesamtkosten", "Average of Hours of": "Durchschnittsstunden von", " is ON for this month": " ist ON diesen Monat", "Days": "Tage", "Total Hours on month": "Gesamtstunden im Monat", "Counts of Hours on days": "Stundenanzahl an Tagen", "OrderId": "Auftrags-ID", "created time": "Erstellzeit", "Intaleq Over": "Intaleq Ende", "I will slow down": "Ich werde langsamer fahren", "Map Passenger": "Karte Fahrgast", "Be Slowly": "Langsam", "If you want to make Google Map App run directly when you apply order": "Google Maps direkt starten bei Auftrag", "You can change the language of the app": "App-Sprache ändern", "Your Budget less than needed": "Budget niedriger als benötigt", "You can change the Country to get all features": "Land ändern für alle Funktionen", "Change Country": "Land ändern" }, "es": { "Order": "Pedido", "OrderVIP": "Pedido VIP", "Cancel Trip": "Cancelar Viaje", "Passenger Cancel Trip": "Pasajero Canceló Viaje", "VIP Order": "Pedido VIP", "The driver accepted your trip": "El conductor aceptó tu viaje", "message From passenger": "Mensaje del pasajero", "Cancel": "Cancelar", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Viaje Cancelado. El costo del viaje se agregará a tu billetera.", "token change": "cambio de token", "face detect": "detección facial", "Face Detection Result": "Resultado de Detección Facial", "similar": "similar", "not similar": "no similar", "Hi ,I will go now": "Hola, me voy ahora", "Passenger come to you": "El pasajero viene hacia ti", "Call Income": "Llamada Entrante", "Call Income from Passenger": "Llamada Entrante del Pasajero", "Criminal Document Required": "Documento Criminal Requerido", "You should have upload it .": "Deberías haberlo subido.", "Call End": "Fin de Llamada", "The order has been accepted by another driver.": "El pedido ha sido aceptado por otro conductor.", "The order Accepted by another Driver": "El pedido Aceptado por otro Conductor", "We regret to inform you that another driver has accepted this order.": "Lamentamos informarte que otro conductor ha aceptado este pedido.", "Driver Applied the Ride for You": "El Conductor Aplicó el Viaje para Ti", "Applied": "Aplicado", "Hi ,I Arrive your site": "Hola, llegué a tu ubicación", "Please go to Car Driver": "Por favor, ve con el Conductor del Coche", "Ok I will go now.": "Ok, me voy ahora.", "Accepted Ride": "Viaje Aceptado", "Driver Accepted the Ride for You": "El Conductor Aceptó el Viaje para Ti", "Promo": "Promo", "Show latest promo": "Mostrar la última promo", "Trip Monitoring": "Monitoreo de Viaje", "Driver Is Going To Passenger": "El Conductor Va Hacia el Pasajero", "Please stay on the picked point.": "Por favor, permanece en el punto de recogida seleccionado.", "message From Driver": "Mensaje del Conductor", "Trip is Begin": "El Viaje Comienza", "Cancel Trip from driver": "Cancelar Viaje desde el conductor", "We will look for a new driver.\nPlease wait.": "Buscaremos un nuevo conductor.\nPor favor, espera.", "The driver canceled your ride.": "El conductor canceló tu viaje.", "Driver Finish Trip": "El Conductor Finalizó el Viaje", "you will pay to Driver": "le pagarás al Conductor", "Don’t forget your personal belongings.": "No olvides tus pertenencias personales.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Por favor, asegúrate de tener todas tus pertenencias personales y de que cualquier tarifa restante, si corresponde, se haya agregado a tu billetera antes de irte. Gracias por elegir la aplicación Intaleq", "Finish Monitor": "Finalizar Monitoreo", "Trip finished": "Viaje finalizado", "Call Income from Driver": "Llamada Entrante del Conductor", "Driver Cancelled Your Trip": "El Conductor Canceló Tu Viaje", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "le pagarás al Conductor, pagarás el costo del tiempo del conductor, mira tu Billetera Intaleq", "Order Applied": "Pedido Aplicado", //firebase }, "el": { "Order": "Παραγγελία", "OrderVIP": "VIP Παραγγελία", "Cancel Trip": "Ακύρωση Διαδρομής", "Passenger Cancel Trip": "Ο Επιβάτης Ακύρωσε τη Διαδρομή", "VIP Order": "VIP Παραγγελία", "The driver accepted your trip": "Ο οδηγός αποδέχτηκε τη διαδρομή σας", "message From passenger": "Μήνυμα από επιβάτη", "Cancel": "Ακύρωση", "Trip Cancelled. The cost of the trip will be added to your wallet.": "Η διαδρομή ακυρώθηκε. Το κόστος της διαδρομής θα προστεθεί στο πορτοφόλι σας.", "token change": "αλλαγή κωδικού", "face detect": "ανίχνευση προσώπου", "Face Detection Result": "Αποτέλεσμα Ανίχνευσης Προσώπου", "similar": "παρόμοιος", "not similar": "μη παρόμοιος", "Hi ,I will go now": "Γεια, θα πάω τώρα", "Passenger come to you": "Ο επιβάτης έρχεται προς το μέρος σας", "Call Income": "Εισερχόμενη Κλήση", "Call Income from Passenger": "Εισερχόμενη Κλήση από Επιβάτη", "Criminal Document Required": "Απαιτείται Ποινικό Μητρώο", "You should have upload it .": "Έπρεπε να το ανεβάσετε.", "Call End": "Τέλος Κλήσης", "The order has been accepted by another driver.": "Η παραγγελία έχει γίνει αποδεκτή από άλλον οδηγό.", "The order Accepted by another Driver": "Η παραγγελία έγινε αποδεκτή από άλλον οδηγό", "We regret to inform you that another driver has accepted this order.": "Λυπούμαστε που σας ενημερώνουμε ότι άλλος οδηγός έχει αποδεχτεί αυτήν την παραγγελία.", "Driver Applied the Ride for You": "Ο Οδηγός Υπέβαλε Αίτηση για τη Διαδρομή για Εσάς", "Applied": "Εφαρμόστηκε", "Hi ,I Arrive your site": "Γεια, έφτασα στην τοποθεσία σας", "Please go to Car Driver": "Παρακαλώ πηγαίνετε στον Οδηγό Αυτοκινήτου", "Ok I will go now.": "Εντάξει, θα πάω τώρα.", "Accepted Ride": "Αποδεκτή Διαδρομή", "Driver Accepted the Ride for You": "Ο Οδηγός Αποδέχτηκε τη Διαδρομή για Εσάς", "Promo": "Προσφορά", "Show latest promo": "Εμφάνιση τελευταίας προσφοράς", "Trip Monitoring": "Παρακολούθηση Διαδρομής", "Driver Is Going To Passenger": "Ο Οδηγός Πηγαίνει προς τον Επιβάτη", "Please stay on the picked point.": "Παρακαλώ μείνετε στο σημείο παραλαβής που επιλέξατε.", "message From Driver": "Μήνυμα από τον Οδηγό", "Trip is Begin": "Η Διαδρομή Ξεκινά", "Cancel Trip from driver": "Ακύρωση Διαδρομής από τον οδηγό", "We will look for a new driver.\nPlease wait.": "Θα αναζητήσουμε νέο οδηγό.\nΠαρακαλώ περιμένετε.", "The driver canceled your ride.": "Ο οδηγός ακύρωσε τη διαδρομή σας.", "Driver Finish Trip": "Ο Οδηγός Τερμάτισε τη Διαδρομή", "you will pay to Driver": "θα πληρώσετε στον Οδηγό", "Don’t forget your personal belongings.": "Μην ξεχάσετε τα προσωπικά σας αντικείμενα.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "Βεβαιωθείτε ότι έχετε όλα τα προσωπικά σας αντικείμενα και ότι τυχόν υπόλοιπο ναύλο, εάν υπάρχει, έχει προστεθεί στο πορτοφόλι σας πριν φύγετε. Ευχαριστούμε που επιλέξατε την εφαρμογή Intaleq", "Finish Monitor": "Τερματισμός Παρακολούθησης", "Trip finished": "Η διαδρομή τελείωσε", "Call Income from Driver": "Εισερχόμενη Κλήση από τον Οδηγό", "Driver Cancelled Your Trip": "Ο Οδηγός Ακύρωσε τη Διαδρομή Σας", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "θα πληρώσετε στον Οδηγό, θα πληρώσετε το κόστος του χρόνου του οδηγού, κοιτάξτε το Πορτοφόλι Intaleq σας", "Order Applied": "Η Παραγγελία Εφαρμόστηκε", //firebase "registration_date": "Ημερομηνία εγγραφής", "expiration_date": "Ημερ. λήξης", "rating_count": "Για την ακροαματικότητα;", "rating_driver": "Βαθμολογία οδηγού", "age": "Ηλικία", "vin": "Γιατί εγώ είμαι στα λειτουργικά. Έχω απομνημονεύσει τον Αριθμό Αναγνώρισης Οχήματος.", "car_color": "Στο χρώμα.", "car_plate": "C-R-M-S-Κ ...", "car_model": "Μοντέλο Αυτοκινήτου:", "education": "Η Εκπαίδευση", "gender": "Φύλο:", "birthdate": "Γενέθλια", "Approve Driver Documents": "Έγκριση Εγγράφων Οδηγού", "Total Budget is": "Συνολικός προϋπολογισμός", "You will recieve code in sms message": "Θα λάβετε τον κωδικό σε ένα SMS", "Please enter": "Παρακαλώ εισάγετε ένα όνομα πόρου. @ info: whatsthis", "We need your phone number to contact you and to help you receive orders.": "Χρειαζόμαστε τον αριθμό τηλεφώνου σας για να επικοινωνήσουμε μαζί σας και να σας βοηθήσουμε να λαμβάνετε παραγγελίες.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "Το πλήρες ονοματεπώνυμο στο ποινικό μητρώο σας δεν αντιστοιχεί στο ονοματεπώνυμο στο δίπλωμα οδήγησής σας. Ελέγξτε και προσκομίστε τα σωστά έγγραφα.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "Ο εθνικός αριθμός στην άδεια οδήγησής σας δεν αντιστοιχεί στον αριθμό που αναγράφεται στο έγγραφο ταυτότητάς σας. Ελέγξτε και προσκομίστε τα σωστά έγγραφα.", "Capture an Image of Your Criminal Record": "Τραβήξτε μια φωτογραφία του ποινικού σας μητρώου", "IssueDate": "Ημερομηνία έκδοσης", "Capture an Image of Your car license front": "Τραβήξτε μια φωτογραφία του διπλώματος οδήγησής σας από μπροστά", "Capture an Image of Your ID Document front": "Τραβήξτε μια φωτογραφία της ταυτότητάς σας από μπροστά", "NationalID": "Εθνικός αριθμός:", "FullName": "Πλήρες όνομα", "InspectionResult": "Έφερα τις εξετάσεις.", "Criminal Record": "Ποινικό μητρώο", "The email or phone number is already registered.": "Το email ή ο αριθμός τηλεφώνου είναι ήδη καταχωρημένα.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "Για να γίνετε οδηγός επιμερισμού διαδρομής στην εφαρμογή Ταξίδια, πρέπει να ανεβάσετε την άδεια οδήγησης, το έγγραφο ταυτοποίησης και το έγγραφο ταξινόμησης οχήματος. Το σύστημα τεχνητής νοημοσύνης μας θα ελέγξει και θα επαληθεύσει αμέσως την αυθεντικότητά του σε μόλις 2-3 λεπτά. Εάν τα έγγραφά σας εγκριθούν, μπορείτε να αρχίσετε να εργάζεστε ως οδηγός στην εφαρμογή Ταξίδια. Λάβετε υπόψη ότι η παροχή πλαστών εγγράφων αποτελεί σοβαρό αδίκημα και μπορεί να οδηγήσει σε άμεση καταγγελία και νομικές συνέπειες.", "Documents check": "Επαλήθευση εγγράφου", "Driver's License": "'δεια.", "License Type": "- Πάσο.", "National Number": "Την ταυτότητα μου, την ασφάλεια μου.", "Name (Arabic)": "Όνομα (Αραβικά)", "Name (English)": "- Αγγλοσύνη.", "Address": "Διεύθυνση", "Issue Date": "Ημερομηνία έκδοσης", "Expiry Date": "Ημερομηνία λήξης", "License Categories": "- Πάσο.", "driver_license": "'δεια.", "Capture an Image of Your Driver License": "Τραβήξτε μια φωτογραφία της άδειας οδήγησής σας", "ID Documents Back": "- Ταυτότητα.", "National ID": "Δελτίο Εθνικής ταυτότητας", "Occupation": "Επάγγελμα", "Gender": "Φύλο:", "Religion": "Η θρησκεία.", "Marital Status": "Οικογενειακή κατάσταση...", "Full Name (Marital)": "Πλήρες όνομα", "Expiration Date": "Ημερ. λήξης", "Capture an Image of Your ID Document Back": "Τραβήξτε μια φωτογραφία της πίσω όψης του εγγράφου ταυτότητάς σας", "ID Documents Front": "Μπροστινή όψη εγγράφων ταυτοποίησης", "First Name": "Μικρό όνομα...", "CardID": "Τραβήξτε μια φωτογραφία της πίσω όψης του εγγράφου ταυτότητάς σας", "Full Name": "Πλήρες όνομα", "Vehicle Details Front": "Στοιχεία εμπρόσθιου οχήματος", "Plate Number": "Αριθμός πίνακα", "Owner Name": "Ιδιοκτήτης, μάλιστα.", "Vehicle Details Back": "Τα στοιχεία του οχήματος ξανά", "Make": "Grep:% 1", "Model": "Μοντέλο Αυτοκινήτου:", "Year": "- Είναι οι ετήσιες.", "Chassis": "Πλαίσιο", "Color": "Στο χρώμα.", "Displacement": "Υποκατάσταση", "Fuel": "- ΑΜΟΛΥΒΔΗ ΜΟΝΟ - Βενζίνη!", "Tax Expiry Date": "Ημερομηνία λήξης", "Inspection Date": "Ημερομηνία εξέτασης", "Capture an Image of Your car license back": "Τραβήξτε ξανά μια φωτογραφία της άδειας οδήγησής σας", "Capture an Image of Your Driver’s License": "Τραβήξτε μια φωτογραφία της άδειας οδήγησής σας", "Sign in with Google for easier email and name entry": "Συνδεθείτε μέσω Google για να καταχωρίσετε εύκολα το email και το όνομά σας", "You will choose allow all the time to be ready receive orders": "Θα επιλέξετε να επιτρέπετε τις έτοιμες παραγγελίες όλη την ώρα", "Welcome to Intaleq!": "Καλώς ήρθατε στο Safar!", "Get to your destination quickly and easily.": "Φτάστε στον προορισμό σας γρήγορα και εύκολα.", "Enjoy a safe and comfortable ride.": "Απολαύστε μια ασφαλή και άνετη διαδρομή.", "Choose Language": "Επιλέξτε τη γλώσσα", "Login": "Αναφέρω.", "Pay with Wallet": "Πληρωμή με Wallet", "Invalid MPIN": "Μη έγκυρος κωδικός MPIN", "Invalid OTP": "Μη έγκυρος κωδικός επαλήθευσης", "Enter your email address": "Εισάγετε το email σας", "Please enter Your Email.": "Παρακαλώ εισάγετε...", "Enter your phone number": "Τηλέφωνο;", "Please enter your phone number.": "Εισαγάγετε τον αριθμό τηλεφώνου σας.", "Please enter Your Password.": "Εισαγωγή κωδικού", "Submit": "Aπoστoλή...", "if you dont have account": "- Αν δεν σε πειράζει.", "Register": "Ξεκίνα.", "Accept Ride's Terms & Review Privacy Notice": "Αποδεχτείτε τους όρους της διαδρομής και διαβάστε τη δήλωση απορρήτου", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "Επιλέγοντας «Συμφωνώ» παρακάτω, διάβασα και συμφωνώ με τους Όρους Χρήσης και αποδέχομαι τη Δήλωση Απορρήτου.Είμαι τουλάχιστον 18 ετών.", "I Agree": "- Αμήν. - Αμήν. Αξιέπαινες ψήφοι!", "First name": "Μικρό όνομα...", "Enter your first name": "- Το μικρό σας. - Τζέιμς.", "Please enter your first name.": "Εισαγάγετε το όνομά σας.", "Last name": "Επίθετο.", "Enter your last name": "Επίθετο.", "Please enter your last name.": "Εισαγάγετε το όνομά σας.", "City": "Μεντίνα", "Please enter your City.": "Παρακαλώ εισάγετε...", "Male": "Άρρεν", "Female": "θήλυ", "Verify Email": "Επικύρωση email", "We sent 5 digit to your Email provided": "Στείλαμε 5 ψηφία στο παρεχόμενο email σας", "5 digit": "PIN(5 ψηφία)", "Send Verification Code": "Διερεύνηση...", "Your Ride Duration is": "Η διάρκεια της διαδρομής σας είναι", "You will be thier in": "Θα τα έχετε σε", "You trip distance is": "Η απόσταση της διαδρομής σας είναι", "Fee is": "Η αμοιβή είναι", "To :": "προς:", "Add Promo": "Προσθήκη προσφοράς", "Confirm Selection": "Επιβεβαίωση επιλογής", "distance is": "Η απόσταση είναι", "duration is": "Η διάρκεια είναι", "I don't need a ride anymore": "Δεν χρειάζομαι πλέον διαδρομή", "I was just trying the application": "Απλώς δοκίμαζα την εφαρμογή", "No driver accepted my request": "Κανένας οδηγός δεν αποδέχτηκε την παραγγελία μου", "I added the wrong pick-up/drop-off location": "Προσθέσατε λάθος τοποθεσία παραλαβής/αποβίβασης", "I don't have a reason": "- Δεν ξέρω το γιατί.", "Other": "Άλλα", "Can we know why you want to cancel Ride ?": "Μπορούμε να μάθουμε γιατί θέλετε να ακυρώσετε τη διαδρομή;", "Cancel Ride": "Ματαίωση!", "Add Payment Method": "Έναν τρόπο πληρωμής;", "Your Wallet balance is": "Το υπόλοιπο του πορτοφολιού σας είναι", "Ride Wallet": "Wallet διαδρομής", "Payment Method": "Τρόπος πληρωμής;", "Type here Place": "Ασε με εδώ.", "Are You sure to ride to": "Είστε βέβαιοι ότι θέλετε να μετακινηθείτε προς", "Confirm": "Έγινε.", "Back": "Μάζεμα! Επάνω!", "You are Delete": "Διαγράφετε", "Deleted": "Διαγραμμένοmessage status", "You Dont Have Any places yet !": "Δεν έχετε ακόμα κηλίδες!", "Favorite Places": "Το αγαπημένο σου στέκι;", "From : Current Location": "Τρέχουσα τοποθεσία:", "Where to": "- Ίσως μέσα στην επόμενη ώρα.", "Notifications": "Ρύθμιση ειδοποιήσεων...", "Profile": "& Προφίλ acls", "Home": "Αρχική σελίδα", "My Cared": "MyCurt", "Add Card": "Προσθήκη κάρτας", "Add Credit Card": "Πιστωτική.", "Please enter the cardholder name": "Εισαγάγετε το όνομα του κατόχου της κάρτας", "Please enter the expiry date": "Ανάλωση έως", "Please enter the CVV code": "Εισαγάγετε τον κωδικό επαλήθευσης κάρτας", "Go To Favorite Places": "Μετάβαση στα Αγαπημένα Μέρη", "Go to this Target": "Μετάβαση σε αυτόν τον στόχο", "My Profile": "Προφίλ", "Sign Out": "Αποσυνδέομαι.", "Home Page": "Αρχική σελίδα", "Are you want to go to this site": "Θέλετε να μεταβείτε σε αυτήν την τοποθεσία", "MyLocation": "Στην ιστοσελίδα μου;", "my location": "Στην ιστοσελίδα μου;", "Target": "Ένας στόχος.", "Update": "Ανανέωση!", "You Should choose rate figure": "Πρέπει να επιλέξετε τον σωστό αριθμό", "Login Captin": "Αναφέρω.", "Register Captin": "Εγγραφή καπετάνι", "Send Verfication Code": "Αποστολή κωδικού επαλήθευσης", "End Ride": "Επιβιβαστείτε!", "Minute": "Σχολαστικές;", "Go to passenger Location now": "Μεταβείτε στην τοποθεσία επιβάτη τώρα", "Duration of the Ride is": "Η διάρκεια της διαδρομής είναι", "Distance of the Ride is": "Η απόσταση διαδρομής είναι", "Name of the Passenger is": "Το όνομα του επιβάτη είναι", "Hello this is Captain": "Γεια σας, είμαι ο καπετάνιος", "Start the Ride": "Έναρξη διαδρομής", "Please Wait If passenger want To Cancel!": "Περιμένετε εάν ο επιβάτης θέλει να ακυρώσει!", "Total Duration:": "Συνολική Διάρκεια:", "Active Duration:": "Ενεργή διάρκεια βήματος", "Waiting for Captin ...": "Αναμένω τον καπετάνιο.", "Age is": "Η ηλικία είναι απλά ένας αριθμός.", "Rating is": "- Η αξιολόγηση είναι...", "to arrive you.": "Είναι πολύ εύκολο να σε βρουν.", "Order History": "Καταγραφή ιστορικού παραγγελιών", "My Wallet": "Αχ, η τσάντα μου.", "Tariff": "Τιμολόγιο", "Settings": "Ρυθμίσεις.", "Feed Back": "Aντανακλαστικά;", "Promos": "Προσφορές", "Please enter a valid 16-digit card number": "Εισαγάγετε έναν έγκυρο αριθμό εντολής αγοράς.", "Add Phone": "Συγχωρήστε με, κύριοι.", "Please enter a phone number": "Εισαγάγετε τον αριθμό τηλεφώνου", "You dont Add Emergency Phone Yet!": "Δεν έχετε προσθέσει ακόμα τηλέφωνο έκτακτης ανάγκης!", "You will arrive to your destination after": "Θα φτάσετε στον προορισμό σας μετά από", "You can cancel Ride now": "Μπορείτε να ακυρώσετε τη διαδρομή τώρα", "You Can cancel Ride After Captain did not come in the time": "Μπορείτε να ακυρώσετε τη διαδρομή αφού ο καπετάνιος δεν έφτασε εγκαίρως", "If you in Car Now. Press Start The Ride": "Αν είστε στο αυτοκίνητο αυτή τη στιγμή. Πατήστε Έναρξη διαδρομής", "You Dont Have Any amount in": "Δεν έχετε κανένα ποσό σε", "Wallet!": "- Τίποτα. Πορτοφόλι.", "You Have": "- Έχεις λίγη...", "Save Credit Card": "Διατήρηση πιστωτικής κάρτας", "Show Promos": "Αναπαραστάσεις;", "10 and get 4% discount": "10 και κερδίστε έκπτωση 4%", "20 and get 6% discount": "20 και κερδίστε έκπτωση 6%", "40 and get 8% discount": "40 και κερδίστε έκπτωση 8%", "100 and get 11% discount": "100% και έκπτωση 11%", "Pay with Your PayPal": "Πληρωμή με PayPal", "You will choose one of above !": "Θα επιλέξετε μία από τις παραπάνω επιλογές!", "Cancel": "Ακύρωση.", "Delete My Account": "Διαγραφή του λογαριασμού μου", "Edit Profile": "Modifier le profil", "Name": "Nom", "Update Gender": "Mettre à jour le sexe", "Education": "Les études", "Update Education": ":: Moderniser l'enseignement;", "Employment Type": "Catégorie de personnel", "SOS Phone": "Mobile", "High School Diploma": "BACCALAUREAT DE L'ENSEIGNEMENT", "Associate Degree": "Diplôme conjoint", "Bachelor's Degree": "Grade de bachelier", "Master's Degree": "Master", "Doctoral Degree": "Docteur en philosophie.", "Promos For today": "Promotions", "Copy this Promo to use it in your Ride!": "Copiez cette promotion pour l'utiliser lors de votre voyage !", "To change some Settings": "Pour modifier certains paramètres", "To change Language the App": "Pour modifier la langue de l'application", "Order Request Page": "Page de demande de commande", "Rouats of Trip": "Tripp.", "Passenger Name is": "Voyageur.", "Total From Passenger is": "Le total du passager est", "Duration To Passenger is": "Durée jusqu'au passager", "Distance To Passenger is": "distance par rapport au passager est", "Total For You is": "Le total pour vous est de", "Distance is": "Distance", "KM": "Km", "Duration of Trip is": "La durée de la course est de", "Minutes": "Minutes", "Apply Order": "Appliquer la commande", "Refuse Order": "- Demande rejetée.", "Rate Captain": "Cote de capitaine", "Enter your Note": "J'ai eu votre mot.", "Type something...": "Écrire quelque chose...", "Submit rating": "Fournir une évaluation", "Rate Passenger": "Note du passager", "Ride Summary": "Résumé de la course", "welcome_message": "Insérer « & #160; Bonjour monde & #160; »", "app_description": "ApplicationDescription", "get_to_destination": "Destination atteinte. Déblocage des contrôles manuels.", "get_a_ride": "Commandez une course", "safe_and_comfortable": "Sûr et confortable", "committed_to_safety": "Engagé pour la sécurité", "Driver Applied the Ride for You": "Un chauffeur qui a effectué la course pour vous", "Show latest promo": "Afficher la dernière promotion", "Cancel Trip": "Le vol est annulé.", "Passenger Cancel Trip": "Le passager annule la course", "Please stay on the picked point.": "Veuillez rester au point sélectionné.", "Trip is Begin": "Votre initiation a commencé.", "Hi ,I will go now": "Bonjour, j'y vais maintenant", "Passenger come to you": "Votre passager vient vous voir", "Hi ,I Arrive your site": "Bonjour, vous avez atteint votre position.", "Driver Finish Trip": "Fin de la course du chauffeur", "you will pay to Driver": "Sérieux ? Probablement avec mon argent.", "Driver Cancel Your Trip": "Annulez votre course, chauffeur.", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "Vous paierez le chauffeur Vous paierez le coût du temps du chauffeur Regardez votre portefeuille Intaleq", "I will go now": "- J'y vais.", "You Have Tips": "Astuces", "tips": "Des paroles sages ?", "Total is": "Chiffre total est de 15", "No,I want": "- Je n'en ai pas envie.", "Your fee is": "Vos frais sont de", "Do you want to pay Tips for this Driver": "Souhaitez-vous laisser un pourboire à ce chauffeur ?", "Tip is": "Monconseil", "Camera Access Denied.": "Accès à la caméra refusé.", "Open Settings": "|||UNTRANSLATED_CONTENT_START|||افتح الإعدادات|||UNTRANSLATED_CONTENT_END|||", "GPS Required Allow !.": "Le GPS doit être activé !", "Your Account is Deleted": "Votre compte a été supprimé", "Are you sure to delete your account?": "Voulez-vous vraiment supprimer votre compte ?", "Your data will be erased after 2 weeks": "Vos données seront effacées après 2 semaines", "And you will can't return to use app after 1 month": "Vous pourrez revenir à l'application après un mois", "Enter Your First Name": "Saisissez votre nom", "Are you Sure to LogOut?": "Voulez-vous vraiment vous déconnecter?", "Email Wrong": "Email ", "Email you inserted is Wrong.": "L'adresse e-mail que vous avez saisie est incorrecte.", "You have finished all times": "J'en ai assez !", "if you want help you can email us here": "Si vous souhaitez de l'aide, vous pouvez nous envoyer un e-mail ici", "Thanks": "Merci.", "Email Us": "Envoyez-nous un e-mail", "I cant register in your app in face detection": "Je ne peux pas m'inscrire à votre application avec la détection de visage", "Hi": "-C'est un plaisir. -Hello.", "No face detected": "Aucun scanner n'a été détécté", "Image detecting result is": "Le résultat de la détection d'image est", "from 3 times Take Attention": "que 3 fois attirent votre attention", "Be sure for take accurate images please": "Assurez-vous de prendre des photos précises s'il vous plaît", "You have": "- Euh...", "image verified": "La photo est notariée", "Next": "Suivant", "There is no help Question here": "Ouais, pas d'aide ici.", "Call End": "Terminer l'appel", "You dont have Points": "- Vous n'avez pas...", "You Are Stopped For this Day !": "Vous avez été mis en pause pour la journée !", "You must be charge your Account": "Vous devez recharger votre compte", "You Refused 3 Rides this Day that is the reason": "Vous avez refusé 3 courses aujourd'hui et c'est pourquoi", "See you Tomorrow!": "Je te verrais demain.", "Recharge my Account": "Recharger mon compte", "Ok , See you Tomorrow": "D'accord, on se voit demain.", "You are Stopped": "Vous êtes arrêté", "Connected": "Online", "Not Connected": "Offiline", "Your are far from passenger location": "Vous êtes loin de l'emplacement des passagers", "go to your passenger location before": "Accédez à l'emplacement de votre passager avant le", "Passenger cancel trip": "Le passager a annulé la course", "You will get cost of your work for this trip": "Vous obtiendrez le coût de votre entreprise pour cette course", "in your wallet": "Elle est dans ton portefeuille.", "you gain": "Vous gagnerez", "Order Cancelled": "Commande annulée", "Order Cancelled by Passenger": "Demande annulée par le passager", "Success": "Je l'ai.", "Feedback data saved successfully": "Données d'évaluation enregistrées avec succès", "No Promo for today .": "Pas de promotion pour aujourd'hui.", "Select your destination": "Sélectionnez la destination;", "Search for your Start point": "Trouvez votre point de départ", "Search for waypoint": "Rechercher un point WIPOINT", "Current Location": "Utiliser la position actuelle", "Add Location 1": "Emplacement & #160;: %1", "You must Verify email !.": "Relever le courriel", "Cropper": "Récolte", "Saved Sucssefully": "Bien reçu.", "Select Date": "Choisir une nouvelle date", "Birth Date": "Date de naissance", "Ok": "D'accord.", "the 500 points equal 30 JOD": "500 points équivaut à 30 JOD", "the 500 points equal 30 JOD for you": "500 points équivaut à 30 JOD pour vous", "token updated": "Code mis à jour", "Add Location 2": "Ajouter un emplacement 2", "Add Location 3": "Ajouter un emplacement 3", "Add Location 4": "Ajouter un emplacement 4", "Waiting for your location": "En attente de votre localisation", "Search for your destination": "Trouvez votre destination", "Hi! This is": "Bienvenue \"moi\": c' est ça.", "I am using": "Du matériel que j'utilisais.", "to ride with": "pour rouler avec", "as the driver.": "On dirait un chauffeur.", "is driving a": "- Je vais le tenter comme ça. - Conduire.", "with license plate": "Avec une plaque d'immatriculation", "I am currently located at": "Je suis actuellement en", "Please go to Car now": "S'il te plaît, va-t-en maintenant.", "If you need to reach me, please contact the driver directly at": "Si vous avez besoin de me joindre, veuillez contacter directement le chauffeur au", "No Car or Driver Found in your area.": "Aucune voiture ou chauffeur trouvé dans votre région.", "Please Try anther time": "Réessayer", "There no Driver Aplly your order sorry for that": "Aucun chauffeur ne peut répondre à votre demande, nous sommes désolés.", "Trip Cancelled": "Course annulée", "The Driver Will be in your location soon .": "Votre chauffeur arrivera bientôt chez vous.", "The distance less than 500 meter.": "La distance est inférieure à 500 mètres.", "Promo End !": "- C'est seulement jusqu'au spectacle.", "There is no notification yet": "Aucune notification pour le moment", "Use Touch ID or Face ID to confirm payment": "Utilisez Touch ID ou Face ID pour confirmer le paiement", "Contact us for any questions on your order.": "Contactez-nous pour toute question concernant votre commande.", "Pyament Cancelled .": "Le paiement a été annulé.", "type here": "Tapez ici", "Scan Driver License": "Permis de conduire", "Please put your licence in these border": "Veuillez placer votre licence dans ces limites", "Camera not initialized yet": "Caméra pas encore configurée", "Take Image": "Prends une photo, parce que demain matin, ces lettres partiront.", "AI Page": "Tu dis que ton système \"IA\"", "Take Picture Of ID Card": "Prenez une photo de votre pièce d'identité", "Take Picture Of Driver License Card": "Prenez une photo de votre permis de conduire.", "We are process picture please wait": "Nous traitons les images, veuillez patienter.", "There is no data yet.": "Aucune donnée trouvée", "Name :": "Nom :", "Drivers License Class:": "Catégorie de permis de conduire :", "Document Number:": "Numéro du document", "Address:": "Adresse:", "Height:": "& Hauteur & #160;:", "Expiry Date:": "Expiration & #160;:", "Date of Birth:": "Anniversaire & #160;: @title: group", "You can't continue with us .": "Ça ne peut pas durer.", "You should renew Driver license": "Vous devez renouveler votre permis de conduire", "Detect Your Face": "Découvrez votre visage", "Go to next step": "\"", "scan Car License.": "Vérification de l'immatriculation du véhicule.", "Name in arabic": "Full Name AR", "Drivers License Class": "Permis de conduire", "Date of Birth": "Date de naissance", "Age": "l’âge", "Lets check Car license": "Vérifions le permis de conduire", "Car Kind": "Type de véhicule", "Car Plate": "Le numéro d'immatriculation ?", "Lets check License Back Face": "Vérifions la licence de face arrière", "Car License Card": "Carte d'immatriculation du véhicule", "No image selected yet": "Aucune photo sélectionnée pour le moment", "Made :": "Make", "model :": "Mod.", "VIN :": "Structure :", "year :": "Année", "ُExpire Date": "Date d'expiration", "Login Driver": "Se connecter", "Password must br at least 6 character.": "Le mot de passe doit comporter au moins 6 caractères.", "if you don't have account": "Que voulez-vous dire ?", "Here recorded trips audio": "Voici les enregistrements audio du voyage", "Register as Driver": "Inscrivez-vous en tant que chauffeur", "Privacy Notice": "Avis de confidentialité", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "En sélectionnant « J'accepte » ci-dessous, j'ai lu, j'accepte et j'accepte les conditions générales", ". I am at least 18 years of age.": ". J'ai au moins 18 ans.", "Log Out Page": "Se Déconnecter", "Log Off": "Signe.", "Register Driver": "Le chauffeur...", "Verify Email For Driver": "Consultez l'e-mail du chauffeur", "Admin DashBoard": "Tableau de bord d'administration", "Your name": "Ton... nom.", "your ride is applied": "Votre course a été appliquée", "Your password": "Renouveler votre mot de passe", "LE": "Livre égyptienne", "JOD": "Monnaie: Dinar jordanien", "m": "%1 km", "We search nearst Driver to you": "Nous recherchons le chauffeur le plus proche", "please wait till driver accept your order": "Veuillez attendre que le chauffeur accepte votre demande", "No accepted orders? Try raising your trip fee to attract riders.": "Aucune Essayez d'augmenter les frais de course pour attirer des passagers.", "You should select one": "Vous devez en choisir un", "The driver accept your order for": "Votre chauffeur a accepté votre demande de", "Increase Fee": "Augmenter les frais", "No, thanks": "Non merci", "The driver on your way": "Votre chauffeur est en route", "Total price from": "P.T", "Order Details Intaleq": "Détails du commande", "Order Applied": "Commande appliquée", "accepted your order": "- Retenue.", "We regret to inform you that another driver has accepted this order.": "Nous sommes désolés de vous informer qu'un autre chauffeur a accepté cette demande.", "Selected file:": "Ouvre un fichier existant", "Your trip cost is": "Les frais de votre course", "this will delete all files from your device": "Cela supprimera tous les fichiers de votre appareil", "you have a negative balance of": "Vous avez un solde négatif de", "in your": "En toi.", "Exclusive offers and discounts always with the Intaleq app": "Offres exclusives et réductions toujours avec l'application de voyage", "Please go to Car Driver": "Veuillez vous rendre chez le conducteur de la voiture", "wallet due to a previous trip.": "Portefeuille en raison d'une course précédente.", "Submit Question": "Envoyer la question", "Please enter your Question.": "Veuillez saisir votre question.", "Help Details": "Détails de l'aide", "No trip yet found": "Aucune campagne trouvée", "No Response yet.": "Il n'y a pas de réponses.", "You Earn today is": "- On est euh...", "You Have in": "Vous avez à", "Total points is": "Le score total est de", "Total Connection Duration:": "Durée totale de connexion :", "H and": "H et", "Passenger name :": "Le voyageur.", "Cost Of Trip IS": "Coûts des vols par avion spécial", "Arrival time": "On arrive dans 7 minutes.", "arrival time to reach your point": "Heure d'arrivée pour atteindre votre destination", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "Pour les courses et livraisons rapides, le prix est calculé de manière dynamique. Pour des courses confortables, le prix est basé sur la durée et la distance.", "Hello this is Driver": "Bonjour, je suis le chauffeur", "Is the Passenger in your Car ?": "Le passager est-il dans votre véhicule ?", "Please wait for the passenger to enter the car before starting the trip.": "Veuillez attendre que le passager entre dans le véhicule avant de commencer la course.", "No ,still Waiting.": "Non , je t'attends toujours.", "I arrive you": "Elle t'a eue.", "I Arrive your site": "Elle t'a eue.", "You are not in near to passenger location": "Vous n'êtes pas près de l'emplacement du passager", "please go to picker location exactly": "Veuillez vous rendre à l'emplacement exact de la sélection", "You Can Cancel Trip And get Cost of Trip From": "Vous pouvez annuler la course et obtenir le coût de la course auprès de", "Are you sure to cancel?": "Voulez-vous vraiment annuler ?", "Yes": "Oui", "Insert Emergincy Number": "Saisir le numéro d'urgence", "Best choice for comfort car and flexible route and stops point": "Le meilleur choix pour une voiture confortable, un itinéraire flexible et un point d'arrêt", "Insert": "En cours d' utilisation", "This is for delivery or a motorcycle.": "C'est pour la livraison ou une moto.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "Cette course va directement de votre point de départ à votre destination pour un tarif forfaitaire. Le chauffeur doit suivre l'itinéraire prévu", "You can decline a request without any cost": "Vous pouvez refuser la demande sans frais", "Perfect for adventure seekers who want to experience something new and exciting": "Idéal pour les chercheurs d'aventure qui veulent essayer quelque chose de nouveau et d'excitant", "My current location is:": "Mon emplacement actuel est :", "and I have a trip on": "et j'ai un voyage à", "App with Passenger": "Postuler avec le passager", "You will be pay the cost to driver or we will get it from you on next trip": "Le coût sera payé au chauffeur ou nous l'obtiendrons de votre part lors de la prochaine course", "Trip has Steps": "La course comporte des étapes", "Distance from Passenger to destination is": "La distance entre le passager et la destination est", "price is": "C'est cent dollars.", "This ride type does not allow changes to the destination or additional stops": "Ce type de course ne permet pas de modifier la destination ou d'effectuer des arrêts supplémentaires", "This price may be changed": "Ce prix peut changer", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "Pas de carte SIM, pas de problème ! Contactez directement votre chauffeur via notre application. Nous utilisons une technologie de pointe pour garantir votre confidentialité.", "This ride type allows changes, but the price may increase": "Ce type de course peut être modifié, mais le prix peut augmenter", "message From passenger": "Estafette.", "Select one message": "Message un.", "My location is correct. You can search for me using the navigation app": "Ma position est correcte. Vous pouvez me rechercher à l'aide de l'application de navigation", "I'm waiting for you": "- Quand vous voulez.", "Hello, I'm at the agreed-upon location": "Bonjour, je suis à l'endroit convenu", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "Nous avons remarqué que la vitesse dépasse 100 km/h. Veuillez ralentir pour votre propre sécurité. Si vous ne vous sentez pas en sécurité, vous pouvez communiquer les détails de votre course à un contact ou appeler la police à l'aide du bouton de détresse rouge.", "Warning: Intaleqing detected!": "Avertissement : survitesse détectée !", "Please help! Contact me as soon as possible.": "Aide-moi s'il te plaît. Contactez-moi dès que possible.", "Share Trip Details": "Partagez les détails de la", "Car Plate is": "Le numéro d'immatriculation ?", "the 3000 points equal 3000 L.E for you": "3000 points équivaut à 3000 EGP pour vous", "So go and gain your money": "Gagnez de l'argent", "the 3000 points equal 3000 L.E": "3000 points équivaut à 3000 EGP", "The payment was not approved. Please try again.": "Paiement non approuvé. Réessayer", "Payment Failed": "Échec du paiement", "Error": "ⵜⴰⵣⴳⵍⵜ", "An error occurred during the payment process.": "Une erreur s'est produite lors de votre paiement.", "The payment was approved.": "Paiement approuvé.", "Payment Successful": "Paiement réussi", "No ride found yet": "Aucune campagne trouvée", "Accept Order": "Commande acceptée", "reject your order.": "Votre Ordre.", "Bottom Bar Example": "Exemple de barre inférieure", "Driver phone": "Téléphone du chauffeur", "Statistics": "& Statistiques", "Origin": "ORIGINE", "Destination": "- Destination ?", "Driver Name": "Nom de pilote & #160;:", "Driver Car Plate": "Plaque d'immatriculation du conducteur", "Available for rides": "Disponible pour les courses", "Scan Id": "Contrôle d'identité", "Camera not initilaized yet": "Caméra pas encore configurée", "Scan ID MklGoogle": "Vérification d'identité MklGoogle", "Language": "Langue ", "Jordan": "Jordanie", "USA": "Etats Unis d'Amérique", "Egypt": "Egypte", "Turkey": "Turquie", "Saudi Arabia": "Arabie Saoudite", "Qatar": "Qatar", "Bahrain": "Bahreïn", "Kuwait": "Koweït", "But you have a negative salary of": "Mais vous avez un salaire négatif de", "Promo Code": "Code promo", "Your trip distance is": "La distance de votre course est de", "Enter promo code": "Code promo", "You have promo!": "Vous avez une promotion !", "Cost Duration": "Durée du coût", "Duration is": "La durée est", "Leave": "Quitter", "Join": "Joindre", "You Should be select reason.": "Vous devez choisir une raison.", "\$": "\$", "Waiting for Driver ...": "En attente du chauffeur ...", "Latest Recent Trip": "J'ai des choses à faire!", "from your list": "À partir de votre liste", "Do you want to change Work location": "Souhaitez-vous changer de lieu de travail ?", "Do you want to change Home location": "Souhaitez-vous changer l'emplacement de la maison", "We Are Sorry That we dont have cars in your Location!": "Nous sommes désolés que les voitures ne soient pas disponibles chez vous !", "Choose from Map": "Sélectionner sur la carte", "Pick your ride location on the map - Tap to confirm": "Sélectionnez votre lieu de prise en charge sur la carte - appuyez pour confirmer", "To Work": "Pour le boulot", "Are you want to go this site": "Voulez-vous aller à cet endroit", "Closest & Cheapest": "Le plus proche et le moins cher", "Work Saved": "Enregistré :", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq est une application de covoiturage sûre, fiable et accessible.", "With Intaleq, you can get a ride to your destination in minutes.": "En voyageant, vous pouvez vous rendre à destination en quelques minutes.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Safar s'engage pour la sécurité, et tous nos commandants sont soigneusement contrôlés et leurs antécédents vérifiés.", "To Home": "RETOUR À LA PAGE D'ACCUEIL", "Home Saved": "Enregistré :", "Destination selected": "Destination sélectionnée", "Now select start pick": "Maintenant, choisissez Démarrer la sélection", "Pick from map": "Sélectionner sur la carte", "Click here point": "Cliquez ici", "No Car in your site. Sorry!": "Il n'y a pas de voiture dans votre région. Ex... Excusez moi.", "Nearest Car for you about": "La voiture la plus proche de chez vous est d'environ", "N/A": "Aucune information", "From :": "Du :", "Get Details of Trip": "Obtenir les détails de la course", "If you want add stop click here": "Si vous souhaitez ajouter un arrêt, cliquez ici", "Driver": "ⴰⵎⵏⴷⴰⵀ", "Where you want go": "D'où viens-tu ?", "My Card": "Ma carte.", "Start Record": "Début de la campagne d'enregistrement", "Wallet": "Un portefeuille.", "History of Trip": "2.1 Histoire du vol", "Helping Center": "Centre d'aide", "Record saved": "Sauvegarde de l'historique effectuée !", "Trips recorded": "Voyages enregistrés", "Select Your Country": "Selectionnez votre pays", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "Pour vous assurer d'avoir les informations les plus précises pour votre emplacement, veuillez sélectionner votre pays ci-dessous. Cela vous aidera à personnaliser l'expérience et le contenu de l'application pour votre pays.", "Are you sure to delete recorded files": "Êtes-vous sûr de vouloir supprimer les fichiers enregistrés", "Select recorded trip": "Choisissez une course enregistrée", "Card Number": "N  de pièce d'identité:", "Hi, Where to": "Bonjour, oùallez-vous ?", "Pick your destination from Map": "Sélectionner sur la carte", "Add Stops": "Ajouter des arrêts", "Get Direction": "Obtenir une direction", "Add Location": "Ajouter l'emplacement correctement", "Switch Rider": "Changer de passager", "You will arrive to your destination after timer end.": "Vous arriverez à destination après l'expiration de la minuterie.", "You can cancel trip": "Vous pouvez annuler la course", "The driver waitting you in picked location .": "Votre chauffeur vous attend à l'endroit désigné .", "Pay with Your": "Payer avec", "Pay with Credit Card": "- La carte.", "Payment History": "Historique des paiements", "Show Promos to Charge": "Afficher les promotions d'expédition", "Point": "Points", "Driver Balance": "Portefeuille chauffeur", "Total Points is": "Le score total est de", "Total Budget from trips is": "Le budget total des voyages est de", "Total Amount:": "Montant total", "Total Budget from trips by": "Budget total des voyages par", "Credit card is": "Votre carte de crédit.", "This amount for all trip I get from Passengers": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers.", "Pay from my budget": "Payer sur mon budget", "This amount for all trip I get from Passengers and Collected For me in": "Ce montant s'applique à toutes les courses que je reçois de la part de passagers collectés pour moi à", "You can buy points from your budget": "Vous pouvez acheter des points à partir de votre budget", "insert amount": "Entrez le montant", "You can buy Points to let you online": "Vous pouvez acheter des points pour vous permettre d'accéder en ligne", "by this list below": "Grâce à cette liste ci-dessous", "Create Wallet to receive your money": "Créez un portefeuille pour recevoir votre argent", "Enter your feedback here": "Saisissez vos commentaires ici", "Please enter your feedback.": "Veuillez saisir le texte de vos notes", "Feedback": "Feedback:", "Click here to Show it in Map": "Cliquez ici pour le voir sur la carte", "Canceled": "Annulé", "Type your Email": "Votre e-mail", "No I want": "- Je n'en ai pas envie.", "Email is": "Email ", "Phone Number is": "C'est le 92.38.09.06.", "Date of Birth is": "Année de naissance", "Sex is": "Le sexe est cardio.", "Car Details": "Détails du véhicule", "VIN is": "Structure", "Color is": "- Sa couleur?", "Make is": "Make is", "Model is": "Formulaire de :", "Year is": "Année", "Edit Your data": "Modifiez vos informations", "write vin for your car": "Notez le numéro de châssis de votre véhicule", "VIN": "|||UNTRANSLATED_CONTENT_START|||رقم هيكل السيارة|||UNTRANSLATED_CONTENT_END|||", "write Color for your car": "Tapez la couleur de votre voiture", "write Make for your car": "Écrivez une marque pour votre voiture", "write Model for your car": "Tapez votre modèle de voiture", "write Year for your car": "Saisissez une année pour votre voiture", "write Expiration Date for your car": "la date de péremption", "Tariffs": "Définitions ", "Minimum fare": "Prix minimum", "Maximum fare": "Prix maximum", "Flag-down fee": "Frais d'escale", "Including Tax": "Incluant...", "BookingFee": "Frais de réservation", "Morning": "- Bonjour.", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07h30 - 10h30 (jeudi, vendredi, samedi, lundi)", "Evening": "- Bonsoir.", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12h00 - 15h00 (jeudi, vendredi, samedi, lundi)", "Night": "la nuit", "You have in account": "Vous avez dans le compte", "Select Country": "Sélectionner un pays.", "Ride Today :": "Commandez une course aujourd'hui :", "After this period": "Après cette période", "You can't cancel!": "- Vous pouvez plus...", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "Le chauffeur...", "Total Cost is": "Coût total", "Write note": "J'écris une lettre de menace.", "Time to arrive": "Bobby, Qu'elle est notre e. t. a.?", "Ride Summaries": "Résumés des courses", "Total Cost": "Coût total", "Average of Hours of": "Nombre moyen d'heures de travail", "is ON for this month": "En cours ce mois-ci", "Days": "Quelques mois, semaines... quelques jours.", "Total Hours on month": "Nombre total d'heures", "Counts of Hours on days": "Heures en jours", "OrderId": "Commande N°", "created time": "Date de création", "Intaleq Over": "Et c'est là qu'on l'aura.", "I will slow down": "Je vais ralentir.", "Map Passenger": "Carte du passager", "Be Slowly": "Soyez lent", "If you want to make Google Map App run directly when you apply order": "Si vous souhaitez lancer Google Maps directement lorsque vous appliquez la commande", "You can change the language of the app": "Vous pouvez modifier la langue de l'application", "Your Budget less than needed": "Votre budget est sous-estimé", "You can change the Country to get all features": "Vous pouvez modifier le pays pour obtenir toutes les fonctionnalités", "Change Country": "Non-pays" }, "hi": { "Order": "ऑर्डर", "OrderVIP": "वीआईपी ऑर्डर", "Cancel Trip": "यात्रा रद्द करें", "Passenger Cancel Trip": "यात्री ने यात्रा रद्द कर दी", "VIP Order": "वीआईपी ऑर्डर", "The driver accepted your trip": "ड्राइवर ने आपकी यात्रा स्वीकार कर ली है", "message From passenger": "यात्री से संदेश", "Cancel": "रद्द करें", "Trip Cancelled. The cost of the trip will be added to your wallet.": "यात्रा रद्द कर दी गई। यात्रा की लागत आपके वॉलेट में जोड़ दी जाएगी।", "token change": "टोकन परिवर्तन", "face detect": "चेहरा पहचानना", "Face Detection Result": "चेहरा पहचान परिणाम", "similar": "समान", "not similar": "असमान", "Hi ,I will go now": "नमस्ते, मैं अब जाऊंगा", "Passenger come to you": "यात्री आपके पास आ रहा है", "Call Income": "आवक कॉल", "Call Income from Passenger": "यात्री से आवक कॉल", "Criminal Document Required": "आपराधिक दस्तावेज़ आवश्यक", "You should have upload it .": "आपको इसे अपलोड करना चाहिए था।", "Call End": "कॉल समाप्त", "The order has been accepted by another driver.": "ऑर्डर किसी अन्य ड्राइवर द्वारा स्वीकार कर लिया गया है।", "The order Accepted by another Driver": "ऑर्डर किसी अन्य ड्राइवर द्वारा स्वीकार किया गया", "We regret to inform you that another driver has accepted this order.": "हमें आपको यह सूचित करते हुए दुख हो रहा है कि किसी अन्य ड्राइवर ने यह ऑर्डर स्वीकार कर लिया है।", "Driver Applied the Ride for You": "ड्राइवर ने आपके लिए सवारी के लिए आवेदन किया", "Applied": "लागू", "Hi ,I Arrive your site": "नमस्ते, मैं आपके साइट पर पहुँच गया हूँ", "Please go to Car Driver": "कृपया कार ड्राइवर के पास जाएं", "Ok I will go now.": "ठीक है मैं अब जाऊंगा।", "Accepted Ride": "सवारी स्वीकार की गई", "Driver Accepted the Ride for You": "ड्राइवर ने आपके लिए सवारी स्वीकार कर ली", "Promo": "प्रोमो", "Show latest promo": "नवीनतम प्रोमो दिखाएं", "Trip Monitoring": "यात्रा निगरानी", "Driver Is Going To Passenger": "ड्राइवर यात्री के पास जा रहा है", "Please stay on the picked point.": "कृपया चुने हुए बिंदु पर रहें।", "message From Driver": "ड्राइवर से संदेश", "Trip is Begin": "यात्रा शुरू हो गई है", "Cancel Trip from driver": "ड्राइवर से यात्रा रद्द", "We will look for a new driver.\nPlease wait.": "हम एक नए ड्राइवर की तलाश करेंगे।\nकृपया प्रतीक्षा करें।", "The driver canceled your ride.": "ड्राइवर ने आपकी सवारी रद्द कर दी।", "Driver Finish Trip": "ड्राइवर ने यात्रा समाप्त की", "you will pay to Driver": "आप ड्राइवर को भुगतान करेंगे", "Don’t forget your personal belongings.": "अपनी निजी वस्तुएं न भूलें।", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "कृपया सुनिश्चित करें कि आपके पास अपनी सभी निजी वस्तुएं हैं और यदि लागू हो तो कोई भी शेष किराया जाने से पहले आपके वॉलेट में जोड़ दिया गया है। Intaleq ऐप चुनने के लिए धन्यवाद", "Finish Monitor": "निगरानी समाप्त करें", "Trip finished": "यात्रा समाप्त हो गई", "Call Income from Driver": "ड्राइवर से आवक कॉल", "Driver Cancelled Your Trip": "ड्राइवर ने आपकी यात्रा रद्द कर दी", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "आप ड्राइवर को भुगतान करेंगे आप ड्राइवर के समय की लागत का भुगतान करेंगे अपने Intaleq वॉलेट को देखें", "Order Applied": "ऑर्डर लागू किया गया", //firebase "registration_date": "दिनांक पंजीकृत", "expiration_date": "खत्म होने की तारीख", "rating_count": "रेटिंग्स", "rating_driver": "ड्राइवर पार्टनर की रेटिंग", "age": "दाँत", "vin": "VIN", "car_color": "फ़ॉन्ट रंग", "car_plate": "कार के चारों ओर ले आओ।", "car_model": "कार का मॉडल:", "education": "शिक्षा", "gender": "घराना", "birthdate": "जन्मदिन", "Approve Driver Documents": "ड्राइवर पार्टनर के डॉक्यूमेंट मंज़ूर करें", "Total Budget is": "कुल बजट", "You will recieve code in sms message": "आपको कोड एसएमएस (SMS) में मिलेगा", "Please enter": "कृपया संसाधन नाम भरें. @ info: whatsthis", "We need your phone number to contact you and to help you receive orders.": "हमें आपसे संपर्क करने और ऑर्डर पाने में आपकी मदद करने के लिए आपका फ़ोन नंबर चाहिए।", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "आपके आपराधिक रिकॉर्ड पर मौजूद पूरा नाम आपके ड्राइविंग लाइसेंस पर मौजूद नाम से मेल नहीं खाता। कृपया जाँच करें और सही डॉक्यूमेंट दें।", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "आपके ड्राइविंग लाइसेंस पर दिया गया राष्ट्रीय नंबर आपके आईडी डॉक्यूमेंट पर मौजूद नंबर से मेल नहीं खाता। कृपया जाँच करें और सही डॉक्यूमेंट दें।", "Capture an Image of Your Criminal Record": "अपने आपराधिक रिकॉर्ड की फ़ोटो लें", "IssueDate": "जारी तिथि", "Capture an Image of Your car license front": "सामने से अपने कार लाइसेंस की फ़ोटो लें", "Capture an Image of Your ID Document front": "सामने से अपनी आईडी की फ़ोटो लें", "NationalID": "राष्ट्रीय नंबर", "FullName": "पूरा नाम", "InspectionResult": "परीक्षा परिणाम", "Criminal Record": "आपराधिक रिकॉर्ड", "The email or phone number is already registered.": "ईमेल या फ़ोन नंबर पहले से रजिस्टर है।", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "यात्रा ऐप में राइडशेयर ड्राइवर पार्टनर बनने के लिए, आपको अपना ड्राइविंग लाइसेंस, पहचान का डॉक्यूमेंट और गाड़ी के रजिस्ट्रेशन का डॉक्यूमेंट अपलोड करना होगा। हमारा AI सिस्टम केवल 2 -3 मिनट में इसकी प्रामाणिकता की तुरंत समीक्षा और सत्यापन करेगा। अगर आपके डॉक्यूमेंट मंज़ूर हो जाते हैं, तो आप ट्रैवल ऐप में ड्राइवर पार्टनर के तौर पर काम करना शुरू कर सकते हैं। कृपया ध्यान दें कि जाली डॉक्यूमेंट देना एक गंभीर अपराध है और इसके परिणामस्वरूप तत्काल समाप्ति और कानूनी परिणाम हो सकते हैं।", "Documents check": "डॉक्यूमेंट वेरिफ़िकेशन", "Driver's License": "ड्राइविंग लाइसेंस", "License Type": "लाइसेंस:", "National Number": "राष्ट्रीय आईडी संख्या:", "Name (Arabic)": "नाम (अरबी)", "Name (English)": "channa", "Address": "पता", "Issue Date": "जारी तिथि", "Expiry Date": "समय - सीमा खत्म होने की तारीख", "License Categories": "लाइसेंस:", "driver_license": "ड्राइविंग लाइसेंस", "Capture an Image of Your Driver License": "अपने ड्राइविंग लाइसेंस की फ़ोटो लें", "ID Documents Back": "पहचान के डॉक्यूमेंट दिखना", "National ID": "राष्ट्रीय आईडी", "Occupation": "व्यवसाय", "Gender": "घराना", "Religion": "nizamuddin", "Marital Status": "वैवाहिक स्थिति", "Full Name (Marital)": "पूरा नाम", "Expiration Date": "खत्म होने की तारीख", "Capture an Image of Your ID Document Back": "अपने आईडी डॉक्यूमेंट के पिछले हिस्से की फ़ोटो लें", "ID Documents Front": "पहचान के डॉक्यूमेंट के सामने", "First Name": "पहला नाम", "CardID": "अपने आईडी डॉक्यूमेंट के पिछले हिस्से की फ़ोटो लें", "Full Name": "पूरा नाम", "Vehicle Details Front": "सामने वाली गाड़ी का ब्यौरा", "Plate Number": "बिसात की संख्या चुनें:", "Owner Name": "मालिक का नाम", "Vehicle Details Back": "गाड़ी का ब्यौरा फिर से", "Make": "मेक:% 1", "Model": "कार का मॉडल:", "Year": "वर्ष", "Chassis": "चेसिस", "Color": "फ़ॉन्ट रंग", "Displacement": "प्रतिस्थापन", "Fuel": "ईंधन शुद्ध!", "Tax Expiry Date": "समय - सीमा खत्म होने की तारीख", "Inspection Date": "परीक्षा की तिथि", "Capture an Image of Your car license back": "अपने कार लाइसेंस की फ़ोटो फिर से लें", "Capture an Image of Your Driver’s License": "अपने ड्राइविंग लाइसेंस की फ़ोटो लें", "Sign in with Google for easier email and name entry": "ईमेल और नाम डालना आसान बनाने के लिए Google के साथ साइन इन करें", "You will choose allow all the time to be ready receive orders": "आप हर समय तैयार ऑर्डर की अनुमति देने का विकल्प चुनेंगे", "Welcome to Intaleq!": "Safar में आपका स्वागत है!", "Get to your destination quickly and easily.": "अपने डेस्टिनेशन तक जल्दी और आसानी से पहुँचें।", "Enjoy a safe and comfortable ride.": "सुरक्षित और आरामदायक राइड का आनंद लें।", "Choose Language": "भाषा चुनें", "Login": "लॉगइन...", "Pay with Wallet": "Wallet से भुगतान करें", "Invalid MPIN": "अमान्य एमपीआईएन कोड", "Invalid OTP": "अमान्य वेरिफ़िकेशन कोड", "Enter your email address": "अपना ईमेल पता डालें", "Please enter Your Email.": "कृपया दर्ज करें...", "Enter your phone number": "अपना फ़ोन नंबर डालें", "Please enter your phone number.": "कृपया अपना फ़ोन नंबर डालें।", "Please enter Your Password.": "अपना पासवर्ड डालें", "Submit": "भेजा जा रहा है", "if you dont have account": "अगर आपके पास अकाउंट नहीं है", "Register": "रेकॉर्ड", "Accept Ride's Terms & Review Privacy Notice": "ट्रिप की शर्तें एक्सेप्ट करें और निजता सूचना पर गौर करें", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "नीचे \"मैं सहमत हूँ\" चुनकर, मैंने इस्तेमाल की शर्तों की समीक्षा की है और उनसे सहमत हूँ और निजता सूचना को स्वीकार करता हूँ।मेरी उम्र कम - से - कम 18 साल है।", "I Agree": "सहमत", "First name": "पहला नाम", "Enter your first name": "अपना नाम डालें", "Please enter your first name.": "कृपया अपना नाम डालें।", "Last name": "परिवार नाम", "Enter your last name": "परिवार नाम", "Please enter your last name.": "कृपया अपना नाम डालें।", "City": "शहर", "Please enter your City.": "कृपया दर्ज करें...", "Male": "पुरुष आवाज \"% 1\"", "Female": "स्त्री", "Verify Email": "ईमेल असत्यापित", "We sent 5 digit to your Email provided": "हमने आपके दिए गए ईमेल पर 5 अंक भेजे हैं", "5 digit": "पिन(5-अंकोंवाला)", "Send Verification Code": "Proofed और संचारण.", "Your Ride Duration is": "आपकी यात्रा की अवधि है", "You will be thier in": "आप उन्हें अंदर रखेंगे", "You trip distance is": "आपकी ट्रिप की दूरी है", "Fee is": "शुल्क है", "To :": "को:", "Add Promo": "प्रोमो जोड़ें", "Confirm Selection": "चयन की पुष्टि करें", "distance is": "दूरी है", "duration is": "अवधि है", "I don't need a ride anymore": "मुझे अब राइड की ज़रूरत नहीं है", "I was just trying the application": "मैं अभी - अभी ऐप आज़मा रहा था", "No driver accepted my request": "किसी भी ड्राइवर पार्टनर ने मेरा ऑर्डर मंज़ूर नहीं किया", "I added the wrong pick-up/drop-off location": "आपने गलत पिकअप/ड्रॉप ऑफ़ लोकेशन जोड़ी है", "I don't have a reason": "मेरे पास कोई कारण नहीं है", "Other": "अन्य", "Can we know why you want to cancel Ride ?": "क्या हम जान सकते हैं कि आप ट्रिप क्यों कैंसिल करना चाहते हैं?", "Cancel Ride": "चलाना बन्द करें", "Add Payment Method": "भुगतान विधि जोड़ें", "Your Wallet balance is": "आपका वॉलेट बैलेंस है", "Ride Wallet": "ट्रिप वॉलेट", "Payment Method": "भुगतान की विध", "Type here Place": "यहाँ जगह टाइप करें", "Are You sure to ride to": "क्या आप वाकई राइड करना चाहते हैं", "Confirm": "पक्का करें", "Back": "पीछे जाएँ", "You are Delete": "आप मिटा रहे हैं", "Deleted": "मिटाया", "You Dont Have Any places yet !": "आपके पास अभी तक कोई स्पॉट नहीं है !", "Favorite Places": "पसंदीदा जगहें", "From : Current Location": "मौज़ूदा स्थान बनाए रखें (_K)", "Where to": "...कहाँ?", "Notifications": "सूचनाएं", "Profile": "प्रोफ़ाइल एसीएलएस (P)", "Home": "घर", "My Cared": "माई कर्ट", "Add Card": "A6 कार्ड", "Add Credit Card": "क्रेडिट कार्ड जोड़ें", "Please enter the cardholder name": "कृपया कार्डधारक का नाम डालें", "Please enter the expiry date": "कृपया समय - सीमा खत्म होने की तारीख डालें", "Please enter the CVV code": "कृपया कार्ड वेरिफ़िकेशन कोड डालें", "Go To Favorite Places": "पसंदीदा जगहों पर जाएँ", "Go to this Target": "इस लक्ष्य पर जाएँ", "My Profile": "प्रोफ़ाइल नाम", "Sign Out": "लॉगआउट", "Home Page": "घर", "Are you want to go to this site": "क्या आप इस लोकेशन पर जाना चाहते हैं", "MyLocation": "मेरी लोकेशन", "my location": "मेरी लोकेशन", "Target": "गंतव्य", "Update": "अद्यतन", "You Should choose rate figure": "आपको सही संख्या चुननी होगी", "Login Captin": "लॉगइन...", "Register Captin": "कप्तान का रजिस्ट्रेशन", "Send Verfication Code": "वेरिफ़िकेशन कोड भेजें", "End Ride": "राइड", "Minute": "मिनट", "Go to passenger Location now": "अभी राइडर की लोकेशन पर जाएँ", "Duration of the Ride is": "ट्रिप की अवधि है", "Distance of the Ride is": "ट्रिप की दूरी है", "Name of the Passenger is": "राइडर का नाम है", "Hello this is Captain": "नमस्ते, मैं कप्तान हूँ", "Start the Ride": "ट्रिप शुरू करें", "Please Wait If passenger want To Cancel!": "अगर राइडर कैंसिल करना चाहते हैं, तो कृपया इंतज़ार करें!", "Total Duration:": "कुल अवधि:", "Active Duration:": "चरण की सक्रिय अवधि", "Waiting for Captin ...": "कप्तान का इंतज़ार किया जा रहा है...", "Age is": "उम्र है", "Rating is": "रेटिंग है", "to arrive you.": "आप तक पहुँचने के लिए।", "Order History": "ऑर्डर का इतिहास रिकॉर्ड करें", "My Wallet": "मेरा वॉलेट", "Tariff": "टैरिफ", "Settings": "विन्यास", "Feed Back": "क्रिया:", "Promos": "प्रमोशन", "Please enter a valid 16-digit card number": "कृपया एक मान्य PO नंबर डालें।", "Add Phone": "टेलिफोन", "Please enter a phone number": "कृपया फ़ोन नंबर डालें", "You dont Add Emergency Phone Yet!": "आपने अभी तक कोई आपातकालीन फ़ोन नहीं जोड़ा है!", "You will arrive to your destination after": "आप के बाद अपने डेस्टिनेशन पर पहुँचेंगे", "You can cancel Ride now": "आप अभी ट्रिप कैंसिल कर सकते हैं", "You Can cancel Ride After Captain did not come in the time": "कैप्टन के समय पर न आने के बाद आप ट्रिप कैंसिल कर सकते हैं", "If you in Car Now. Press Start The Ride": "अगर तुम अभी कार में हो. ट्रिप शुरू करें पर टैप करें", "You Dont Have Any amount in": "आपके पास में कोई राशि नहीं है", "Wallet!": "एक बटुआ नाम", "You Have": "तुम्हारे पास बकवास है.", "Save Credit Card": "क्रेडिट कार्ड रखें", "Show Promos": "ऑफ़र देखें", "10 and get 4% discount": "10 और 4% की छूट पाएँ", "20 and get 6% discount": "20 और 6% की छूट पाएँ", "40 and get 8% discount": "40 और 8% की छूट पाएँ", "100 and get 11% discount": "100% और 11% की छूट पाएँ", "Pay with Your PayPal": "PayPal से भुगतान करें", "You will choose one of above !": "आप ऊपर दिए गए विकल्पों में से एक चुनेंगे!", "Cancel": "चलाना बन्द करें", "Delete My Account": "मेरा अकाउंट हटाएँ", "Edit Profile": "प्रोफ़ाइल एसीएलएस (P)", "Name": "नाम", "Update Gender": "लिंग अपडेट करें", "Education": "शिक्षा", "Update Education": "शिक्षा अपडेट करें", "Employment Type": "कार्य रद्द करें", "SOS Phone": "फ़ोन नंबर", "High School Diploma": "हाई स्कूल डिप्लोमा", "Associate Degree": "जॉइंट डिप्लोमा डिग्री", "Bachelor's Degree": "स्नातक की डिग्री", "Master's Degree": "मैं एक मास्टर की डिग्री है.", "Doctoral Degree": "पीएचडी", "Promos For today": "आज के प्रमोशन", "Copy this Promo to use it in your Ride!": "अपनी ट्रिप में इस्तेमाल करने के लिए इस प्रोमो को कॉपी करें!", "To change some Settings": "कुछ सेटिंग बदलने के लिए", "To change Language the App": "ऐप की भाषा बदलने के लिए", "Order Request Page": "ऑर्डर अनुरोध पेज", "Rouats of Trip": "रावत ट्रिप", "Passenger Name is": "यात्री का नाम", "Total From Passenger is": "राइडर का कुल योग है", "Duration To Passenger is": "राइडर की अवधि", "Distance To Passenger is": "राइडर की दूरी है", "Total For You is": "आपके लिए कुल राशि है", "Distance is": "खाली जगह", "KM": "किलोमीटर", "Duration of Trip is": "ट्रिप की अवधि है", "Minutes": "1 मिनट@ item: inlistbox", "Apply Order": "ऑर्डर लागू करें", "Refuse Order": "अनुरोध नामंज़ूर करें", "Rate Captain": "कप्तान रेटिंग", "Enter your Note": "अपना नोट डालें", "Type something...": "कुछ लिखें...", "Submit rating": "मूल्यांकन प्रदान करें", "Rate Passenger": "राइडर की रेटिंग", "Ride Summary": "ट्रिप का सारांश", "welcome_message": "भरें - सबको नमस्कार", "app_description": "आवेदनDescription", "get_to_destination": "डेस्टिनेशन पर पहुँचना", "get_a_ride": "राइड लें", "safe_and_comfortable": "सुरक्षित और आरामदायक", "committed_to_safety": "सुरक्षा के लिए प्रतिबद्ध", "Driver Applied the Ride for You": "एक ड्राइवर पार्टनर, जिन्होंने आपके लिए ट्रिप पूरी की है", "Show latest promo": "नवीनतम प्रोमो दिखाएँ", "Cancel Trip": "इस यात्रा को रद्द करें", "Passenger Cancel Trip": "राइडर ने ट्रिप कैंसिल की", "Please stay on the picked point.": "कृपया चुने गए पॉइंट पर बने रहें।", "Trip is Begin": "यात्रा शुरू होती है", "Hi ,I will go now": "नमस्ते जी, अब मैं जा रहा हूँ", "Passenger come to you": "आपके राइडर आपके पास आ रहे हैं", "Hi ,I Arrive your site": "नमस्ते जी, आप अपनी लोकेशन पर पहुँच गए हैं।", "Driver Finish Trip": "ड्राइवर पार्टनर की ट्रिप खत्म होने की तारीख", "you will pay to Driver": "आप ड्राइवर पार्टनर को भुगतान करेंगे", "Driver Cancel Your Trip": "अपनी ट्रिप कैंसिल करें, ड्राइवर पार्टनर।", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "आप ड्राइवर पार्टनर को भुगतान करेंगे आप ड्राइवर पार्टनर के समय की लागत का भुगतान करेंगे अपना सेफ़र वॉलेट देखें", "I will go now": "अब मैं जा रही हूँ.", "You Have Tips": "आपके पास बख्शीश है", "tips": "सुझाव", "Total is": "कुल है", "No,I want": "मैं ठीक हूँ।", "Your fee is": "आपका शुल्क है", "Do you want to pay Tips for this Driver": "क्या आप इस ड्राइवर पार्टनर को बख्शीश देना चाहेंगे?", "Tip is": "मेरीबख्शीश", "Camera Access Denied.": "कैमरे का ऐक्सेस नामंज़ूर कर दिया गया।", "Open Settings": "सेटिंग खोलें", "GPS Required Allow !.": "जीपीएस (GPS) चालू करना ज़रूरी है!", "Your Account is Deleted": "आपका अकाउंट हटा दिया गया है", "Are you sure to delete your account?": "क्या आप वाकई अपना अकाउंट हटाना चाहते हैं?", "Your data will be erased after 2 weeks": "आपका डेटा 2 हफ़्तों के बाद मिटा दिया जाएगा", "And you will can't return to use app after 1 month": "आप एक महीने बाद ऐप पर वापस आ सकेंगे", "Enter Your First Name": "अपना नाम डालें", "Are you Sure to LogOut?": "क्या आप वाकई लॉग आउट करना चाहते हैं?", "Email Wrong": "ईमेल", "Email you inserted is Wrong.": "आपने जो ईमेल डाला है, वह गलत है।", "You have finished all times": "आपने हर समय काम किया है", "if you want help you can email us here": "अगर आप मदद चाहते हैं, तो आप हमें यहाँ ईमेल कर सकते हैं", "Thanks": "धन्यवाद", "Email Us": "हमें एक ईमेल भेजें", "I cant register in your app in face detection": "मैं फ़ेस डिटेक्शन के साथ आपके ऐप के लिए साइन अप नहीं कर सकता", "Hi": "सुस्वागतम", "No face detected": "कोई चेहरा नहीं मिला", "Image detecting result is": "इमेज डिटेक्शन का नतीजा है", "from 3 times Take Attention": "3 से अधिक बार आपका ध्यान आकर्षित करते हैं", "Be sure for take accurate images please": "कृपया सटीक फ़ोटो लेना न भूलें", "You have": "तुम्हारे पास बकवास है.", "image verified": "फ़ोटो नोटरीकृत है", "Next": "अगला", "There is no help Question here": "यहाँ कोई मदद का सवाल नहीं है", "Call End": "कॉल खत्म करें", "You dont have Points": "आप कोई आत्मा है.", "You Are Stopped For this Day !": "आपको पूरे दिन के लिए रोक दिया गया है!", "You must be charge your Account": "आपको अपना अकाउंट रिचार्ज करना होगा", "You Refused 3 Rides this Day that is the reason": "आपने आज 3 ट्रिप मना कर दी हैं और इसीलिए", "See you Tomorrow!": "कल मिलते हैं!", "Recharge my Account": "मेरा अकाउंट रीचार्ज करें", "Ok , See you Tomorrow": "ठीक है, मैं तुमसे कल मिलूँगी.", "You are Stopped": "आपको रोक दिया गया है", "Connected": "ऑनलाइन", "Not Connected": "मिटाया नहीं", "Your are far from passenger location": "आप राइडर की लोकेशन से बहुत दूर हैं", "go to your passenger location before": "तक अपने राइडर की लोकेशन पर जाएँ", "Passenger cancel trip": "राइडर ने ट्रिप कैंसिल कर दी", "You will get cost of your work for this trip": "आपको इस यात्रा के लिए अपने काम के लिए भुगतान मिलेगा", "in your wallet": "आपके वॉलेट में", "you gain": "आप कमाते हैं", "Order Cancelled": "निवेदन रोका गया", "Order Cancelled by Passenger": "राइडर ने अनुरोध कैंसिल कर दिया", "Success": "सफल", "Feedback data saved successfully": "मूल्यांकन डेटा सफलतापूर्वक सहेजा गया", "No Promo for today .": "आज के लिए कोई प्रमोशन नहीं।", "Select your destination": "अपना डेस्टिनेशन चुनें", "Search for your Start point": "अपना शुरुआती बिंदु ढूँढें", "Search for waypoint": "WIPOINT पॉइंट खोजें", "Current Location": "मौज़ूदा स्थान बनाए रखें (_K)", "Add Location 1": "स्थान:% 1", "You must Verify email !.": "ईमेल असत्यापित", "Cropper": "फ़सल", "Saved Sucssefully": "सफलतापूर्वक सहेजा गया", "Select Date": "दिनांक", "Birth Date": "जन्मदिन: @ title: group", "Ok": "ठीक", "the 500 points equal 30 JOD": "500 points बराबर है: 30 JOD", "the 500 points equal 30 JOD for you": "500 पॉइंट्स आपके लिए 30 JOD के बराबर होते हैं", "token updated": "कोड अपडेट किया गया", "Add Location 2": "स्थान 2 जोड़ें", "Add Location 3": "लोकेशन जोड़ें 3", "Add Location 4": "लोकेशन जोड़ें 4", "Waiting for your location": "आपकी लोकेशन का इंतज़ार है", "Search for your destination": "अपना डेस्टिनेशन ढूँढ़ें", "Hi! This is": "अरे, अब. इस तरफ वाला खेलेगा", "I am using": "छवि इस्तेमाल करें", "to ride with": "के साथ राइड करने के लिए", "as the driver.": "एक ड्राइवर के रूप में", "is driving a": "गाड़ी चलाएँ", "with license plate": "लाइसेंस प्लेट के साथ", "I am currently located at": "फ़िलहाल मैं में हूँ", "Please go to Car now": "कृपया अभी कार में जाएँ", "If you need to reach me, please contact the driver directly at": "अगर आपको मुझसे संपर्क करना है, तो कृपया सीधे ड्राइवर पार्टनर से पर संपर्क करें", "No Car or Driver Found in your area.": "आपके इलाके में कोई कार या ड्राइवर पार्टनर नहीं मिला।", "Please Try anther time": "फिर से कोशिश करें", "There no Driver Aplly your order sorry for that": "कोई भी ड्राइवर पार्टनर आपका अनुरोध पूरा नहीं कर सकता, हमें अफ़सोस है।", "Trip Cancelled": "ट्रिप कैंसिल की गई", "The Driver Will be in your location soon .": "आपके ड्राइवर पार्टनर जल्द ही आपकी लोकेशन पर पहुँच जाएँगे।", "The distance less than 500 meter.": "दूरी 500 मीटर से कम है।", "Promo End !": "शो खत्म हो गया है!", "There is no notification yet": "अभी तक कोई नोटिफ़िकेशन नहीं है", "Use Touch ID or Face ID to confirm payment": "भुगतान कन्फ़र्म करने के लिए टच आईडी या फ़ेस आईडी का इस्तेमाल करें", "Contact us for any questions on your order.": "अपने ऑर्डर के बारे में किसी भी सवाल के लिए हमसे संपर्क करें।", "Pyament Cancelled .": "भुगतान कैंसिल कर दिया गया।", "type here": "यहाँ लिखें", "Scan Driver License": "ड्राइविंग लाइसेंस की जाँच", "Please put your licence in these border": "कृपया अपना लाइसेंस इन सीमाओं के भीतर रखें", "Camera not initialized yet": "कैमरा अभी कॉन्फ़िगर नहीं किया गया है", "Take Image": "(आह)", "AI Page": "AI पेज", "Take Picture Of ID Card": "अपनी आईडी की फ़ोटो लें", "Take Picture Of Driver License Card": "अपने ड्राइविंग लाइसेंस कार्ड की फ़ोटो लें।", "We are process picture please wait": "हम फ़ोटो प्रोसेस कर रहे हैं, कृपया इंतज़ार करें।", "There is no data yet.": "अभी तक कोई डेटा नहीं है।", "Name :": "नाम:", "Drivers License Class:": "ड्राइविंग लाइसेंस श्रेणी:", "Document Number:": "दस्तावेज़ संख्या:", "Address:": "आईपी पता:", "Height:": "ऊँचाईः", "Expiry Date:": "समाप्ति तिथि:", "Date of Birth:": "जन्मदिन: @ title: group", "You can't continue with us .": "आप हमारे साथ जारी नहीं रख सकते।", "You should renew Driver license": "आपको अपने ड्राइविंग लाइसेंस का नवीनीकरण करना होगा", "Detect Your Face": "अपने आप पता लगाएँ", "Go to next step": "अगले चरण पर जाएँ", "scan Car License.": "गाड़ी के लाइसेंस की जाँच।", "Name in arabic": "अरबी में नाम", "Drivers License Class": "ड्राइविंग लाइसेंस श्रेणी", "Date of Birth": "जन्मदिन: @ title: group", "Age": "जीवन", "Lets check Car license": "आइए गाड़ी का लाइसेंस देखें", "Car Kind": "कार के चारों ओर ले आओ।", "Car Plate": "कार के चारों ओर ले आओ।", "Lets check License Back Face": "आइए बैक फ़ेस लाइसेंस की जाँच करें", "Car License Card": "गाड़ी का लाइसेंस कार्ड", "No image selected yet": "अभी तक कोई फ़ोटो नहीं चुनी गई है", "Made :": "मेक:", "model :": "मॉडल:", "VIN :": "चेसिस नंबर:", "year :": "साल", "ُExpire Date": "खत्म होने की तारीख", "Login Driver": "लॉगइन...", "Password must br at least 6 character.": "पासवर्ड कम - से - कम 6 कैरेक्टर का होना चाहिए।", "if you don't have account": "अगर आपके पास अकाउंट नहीं है", "Here recorded trips audio": "यहाँ ऑडियो ट्रिप रिकॉर्डिंग दी गई हैं", "Register as Driver": "ड्राइवर पार्टनर के रूप में साइन अप करें", "Privacy Notice": "निजता सूचना", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "नीचे \"मैं सहमत हूँ\" चुनकर, मैंने नियम और शर्तों की समीक्षा की है, सहमति दी है और उन्हें स्वीकार किया है", ". I am at least 18 years of age.": ". मेरी उम्र कम - से - कम 18 साल है।", "Log Out Page": "लॉगआउट", "Log Off": "बाहर आ रहा है.", "Register Driver": "ड्राइवर चुनें", "Verify Email For Driver": "ड्राइवर पार्टनर का ईमेल देखें", "Admin DashBoard": "एडमिन डैशबोर्ड", "Your name": "तुम्हारा नाम", "your ride is applied": "आपकी ट्रिप लागू कर दी गई है", "Your password": "आपका पासवर्ड बदला गया.", "LE": "मिस्र पाउण्ड", "JOD": "जॉर्डन दिनार", "m": "% 1 मी", "We search nearst Driver to you": "हम आपके सबसे नज़दीकी ड्राइवर पार्टनर की तलाश कर रहे हैं", "please wait till driver accept your order": "कृपया ड्राइवर पार्टनर के आपका अनुरोध एक्सेप्ट करने तक इंतज़ार करें", "No accepted orders? Try raising your trip fee to attract riders.": "कोई एक्सेप्ट किए गए ऑर्डर नहीं हैं? राइडर को आकर्षित करने के लिए अपना ट्रिप शुल्क बढ़ाएँ।", "You should select one": "आपको एक चुनना होगा", "The driver accept your order for": "आपके ड्राइवर पार्टनर ने के लिए आपका अनुरोध मंज़ूर कर लिया है", "Increase Fee": "शुल्क बढ़ाएँ", "No, thanks": "मैं देख रहा हूँ.", "The driver on your way": "आपके ड्राइवर पार्टनर रास्ते में हैं", "Total price from": "से कुल किराया", "Order Details Intaleq": "ऑर्डर विवरण", "Order Applied": "ऑर्डर लागू किया गया", "accepted your order": "आपका अनुरोध मंज़ूर कर लिया गया है", "We regret to inform you that another driver has accepted this order.": "हमें यह बताते हुए अफ़सोस हो रहा है कि किसी दूसरे ड्राइवर पार्टनर ने यह अनुरोध एक्सेप्ट कर लिया है।", "Selected file:": "मौज़ूदा फ़ाइल को खोलें", "Your trip cost is": "आपकी ट्रिप का खर्च", "this will delete all files from your device": "यह आपके डिवाइस से सभी फ़ाइलों को हटा देगा", "you have a negative balance of": "आपका बैलेंस नेगेटिव है", "in your": "डार्सी विक?", "Exclusive offers and discounts always with the Intaleq app": "यात्रा ऐप के साथ हमेशा खास ऑफ़र और छूट", "Please go to Car Driver": "कृपया कार के ड्राइवर पार्टनर के पास जाएँ", "wallet due to a previous trip.": "पिछली ट्रिप की वजह से वॉलेट।", "Submit Question": "प्रश्न सबमिट करें", "Please enter your Question.": "कृपया अपना प्रश्न दर्ज करें।", "Help Details": "मदद का ब्यौरा", "No trip yet found": "अभी तक कोई ट्रिप नहीं मिली है", "No Response yet.": "अभी तक कोई जवाब नहीं मिला।", "You Earn today is": "आज आपकी कमाई है", "You Have in": "आपके पास पर है", "Total points is": "कुल स्कोर है", "Total Connection Duration:": "कुल कनेक्शन अवधि:", "H and": "H और", "Passenger name :": "यात्री का नाम:", "Cost Of Trip IS": "ट्रिप का खर्च है", "Arrival time": "पहुँच अनुमतियाँ", "arrival time to reach your point": "अपने डेस्टिनेशन तक पहुँचने का समय", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "झटपट राइड और डिलीवरी के लिए, किराए का हिसाब गतिशील तरीके से लगाया जाता है। आरामदायक राइड के लिए, किराया समय और दूरी पर आधारित होता है।", "Hello this is Driver": "नमस्ते जी, मैं ड्राइवर पार्टनर हूँ", "Is the Passenger in your Car ?": "क्या राइडर आपकी गाड़ी में हैं?", "Please wait for the passenger to enter the car before starting the trip.": "कृपया ट्रिप शुरू करने से पहले राइडर के गाड़ी में बैठने का इंतज़ार करें।", "No ,still Waiting.": "नहीं , मैं अभी भी तुम्हारा इंतज़ार कर रही हूँ।", "I arrive you": "मैं पहुँच गया!", "I Arrive your site": "मैं पहुँच गया!", "You are not in near to passenger location": "आप राइडर की लोकेशन के पास नहीं हैं", "please go to picker location exactly": "कृपया चयन की सटीक लोकेशन पर जाएँ", "You Can Cancel Trip And get Cost of Trip From": "आप ट्रिप कैंसिल कर सकते हैं और से ट्रिप का खर्च उठा सकते हैं", "Are you sure to cancel?": "क्या आप वाक़ई रद्द करना चाहते हैं?", "Yes": "نعم", "Insert Emergincy Number": "आपातकालीन नंबर डालें", "Best choice for comfort car and flexible route and stops point": "आरामदायक कार, सुविधाजनक मार्ग और ठहरने की जगह के लिए सबसे अच्छा विकल्प", "Insert": "प्रविष्ट", "This is for delivery or a motorcycle.": "यह डिलीवरी या मोटरसाइकिल के लिए है।", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "यह ट्रिप आपके शुरुआती स्थान से सीधे आपके डेस्टिनेशन तक जाती है। ड्राइवर पार्टनर को तय किए गए रास्ते पर चलना होगा", "You can decline a request without any cost": "आप बिना किसी शुल्क के अनुरोध नामंज़ूर कर सकते हैं", "Perfect for adventure seekers who want to experience something new and exciting": "एडवेंचर चाहने वालों के लिए आदर्श जो कुछ नया और रोमांचक आज़माना चाहते हैं", "My current location is:": "मेरी मौजूदा लोकेशन है:", "and I have a trip on": "और मेरी में एक यात्रा है", "App with Passenger": "राइडर के साथ आवेदन करें", "You will be pay the cost to driver or we will get it from you on next trip": "लागत का भुगतान ड्राइवर पार्टनर को किया जाएगा या हम इसे अगली ट्रिप पर आपसे ले लेंगे", "Trip has Steps": "ट्रिप में स्टेप हैं", "Distance from Passenger to destination is": "डेस्टिनेशन तक राइडर की दूरी है", "price is": "किराया है", "This ride type does not allow changes to the destination or additional stops": "ट्रिप का यह प्रकार डेस्टिनेशन में बदलाव या अतिरिक्त स्टॉप की इजाज़त नहीं देता है", "This price may be changed": "यह किराया बदल सकता है", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "कोई सिम कार्ड नहीं, कोई समस्या नहीं! हमारे ऐप के ज़रिए सीधे अपने ड्राइवर पार्टनर से संपर्क करें। हम आपकी निजता सुनिश्चित करने के लिए उन्नत तकनीक का उपयोग करते हैं।", "This ride type allows changes, but the price may increase": "इस तरह की ट्रिप में बदलाव हो सकते हैं, लेकिन किराया बढ़ सकता है", "message From passenger": "राइडर का मैसेज", "Select one message": "स्वचालितआवाज:", "My location is correct. You can search for me using the navigation app": "मेरी लोकेशन सही है। आप नेविगेशन ऐप का इस्तेमाल करके मुझे खोज सकते हैं", "I'm waiting for you": "मैं आपका इंतज़ार कर रहा हूँ", "Hello, I'm at the agreed-upon location": "नमस्ते जी, मैं सहमत लोकेशन पर हूँ", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "हमने देखा कि गति 100 किमी/घंटा से अधिक है। कृपया अपनी सुरक्षा के लिए इसे धीमा करें। अगर आप असुरक्षित महसूस करते हैं, तो आप किसी संपर्क के साथ अपनी ट्रिप का ब्यौरा शेयर कर सकते हैं या रेड डिस्ट्रेस बटन का इस्तेमाल करके पुलिस को कॉल कर सकते हैं।", "Warning: Intaleqing detected!": "चेतावनी: ओवरस्पीड का पता चला!", "Please help! Contact me as soon as possible.": "कृपया मेरी मदद करें! जितनी जल्दी हो सके मुझसे संपर्क करें।", "Share Trip Details": "ट्रिप का ब्यौरा दें", "Car Plate is": "कार के चारों ओर ले आओ।", "the 3000 points equal 3000 L.E for you": "3000 अंक आपके लिए 3000 EGP के बराबर है", "So go and gain your money": "अपने पैसे कमाने के लिए आगे बढ़ें", "the 3000 points equal 3000 L.E": "3000 points बराबर है: 3000 EGP", "The payment was not approved. Please try again.": "भुगतान मंज़ूर नहीं किया गया। फिर से कोशिश करें", "Payment Failed": "भुगतान नहीं हो सका", "Error": "% 1 त्रुटि", "An error occurred during the payment process.": "आपके भुगतान में कोई गड़बड़ी हुई।", "The payment was approved.": "भुगतान मंज़ूर हो गया।", "Payment Successful": "भुगतान सफल रहा", "No ride found yet": "अभी तक कोई ट्रिप नहीं मिली है", "Accept Order": "निवेदन रोका गया", "reject your order.": "इनकार करें", "Bottom Bar Example": "निचला पटल", "Driver phone": "ड्राइवर पार्टनर का फ़ोन नंबर", "Statistics": "आंकड़े", "Origin": "संपत्ति", "Destination": "पहुँच अनुमतियाँ", "Driver Name": "ड्राइवर नामः", "Driver Car Plate": "ड्राइविंग लाइसेंस प्लेट", "Available for rides": "राइड के लिए उपलब्ध", "Scan Id": "पहचान की जाँच", "Camera not initilaized yet": "कैमरा अभी कॉन्फ़िगर नहीं किया गया है", "Scan ID MklGoogle": "MklGoogle पहचान जाँच", "Language": "भाषा", "Jordan": "जॉर्डन", "USA": "संयुक्त राज्य अमेरिका", "Egypt": "मिश्र", "Turkey": "तुर्की", "Saudi Arabia": "सऊदी अरब", "Qatar": "क़तर", "Bahrain": "बहारीन", "Kuwait": "कुवैत", "But you have a negative salary of": "लेकिन आपके पास नकारात्मक वेतन है", "Promo Code": "प्रोमो कोड", "Your trip distance is": "आपकी ट्रिप की दूरी है", "Enter promo code": "प्रोमो कोड डालें", "You have promo!": "आपके पास एक प्रमोशन है!", "Cost Duration": "कास्ट 2", "Duration is": "अवधि है", "Leave": "छोड़ें", "Join": "दर्शक के रूप में शामिल हों (J)", "You Should be select reason.": "आपको एक कारण चुनना होगा।", "\$": "\$", "Waiting for Driver ...": "ड्राइवर पार्टनर का इंतज़ार किया जा रहा है...", "Latest Recent Trip": "ताज़ा ट्रिप", "from your list": "आपकी लिस्ट से", "Do you want to change Work location": "क्या आप कार्य स्थान बदलना चाहेंगे?", "Do you want to change Home location": "क्या आप घर की लोकेशन बदलना चाहेंगे", "We Are Sorry That we dont have cars in your Location!": "हमें अफ़सोस है कि आपकी लोकेशन पर कारें उपलब्ध नहीं हैं!", "Choose from Map": "मैप से चुनें", "Pick your ride location on the map - Tap to confirm": "मैप पर अपनी पिकअप लोकेशन चुनें - कन्फ़र्म करने के लिए टैप करें", "To Work": "काम के लिए", "Are you want to go this site": "क्या आप इस लोकेशन पर जाना चाहते हैं", "Closest & Cheapest": "सबसे नज़दीकी और सबसे सस्ती", "Work Saved": "सेव", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq एक सुरक्षित, भरोसेमंद और सुलभ राइड - हेलिंग ऐप है।", "With Intaleq, you can get a ride to your destination in minutes.": "यात्रा के साथ, आप मिनटों में अपने डेस्टिनेशन तक राइड ले सकते हैं।", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "SAFAR सुरक्षा के लिए प्रतिबद्ध है, और हमारे सभी कमांडरों की सावधानीपूर्वक जांच की जाती है और पृष्ठभूमि की जाँच की जाती है।", "To Home": "घर", "Home Saved": "सेव", "Destination selected": "डेस्टिनेशन चुना गया", "Now select start pick": "अब चयन शुरू करें चुनें", "Pick from map": "मैप से चुनें", "Click here point": "यहाँ क्लिक करें", "No Car in your site. Sorry!": "आपकी लोकेशन में कोई कार नहीं है। क्षमा करें!", "Nearest Car for you about": "आपकी सबसे नज़दीकी कार लगभग", "N/A": "जानकारियाँ नहीं", "From :": "द्वारा:", "Get Details of Trip": "ट्रिप का ब्यौरा पाएँ", "If you want add stop click here": "अगर आप कोई स्टॉप जोड़ना चाहते हैं, तो यहाँ क्लिक करें", "Driver": "ड्राइवर", "Where you want go": "आप कहाँ जाना चाहते हैं?", "My Card": "mera card kho gaya hai", "Start Record": "रिकार्ड करने के लिए आरंभ कर रहा है", "Wallet": "हमअपनेहाथोंपरकाफी लड़ाई है तो एलेन का बटुआ. .", "History of Trip": "ट्रिप की तारीख", "Helping Center": "मदद!", "Record saved": "रिकॉर्ड सेव किया गया", "Trips recorded": "रिकॉर्ड की गई ट्रिप", "Select Your Country": "अपना देश चुनें", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "यह पक्का करने के लिए कि आपके पास अपनी लोकेशन के लिए सबसे सटीक जानकारी है, कृपया नीचे अपना देश चुनें। इससे आपके देश के लिए ऐप के अनुभव और कॉन्टेंट को कस्टमाइज़ करने में मदद मिलेगी।", "Are you sure to delete recorded files": "क्या आप वाकई लॉग की गई फ़ाइलों को हटाना चाहते हैं", "Select recorded trip": "रिकॉर्ड की गई ट्रिप चुनें", "Card Number": "कार्ड संख्य", "Hi, Where to": "नमस्ते, कहाँ जाना है?", "Pick your destination from Map": "मैप से अपना डेस्टिनेशन चुनें", "Add Stops": "स्टॉप जोड़ें", "Get Direction": "रास्ता जानें", "Add Location": "लोकेशन जोड़ें", "Switch Rider": "राइडर बदलें", "You will arrive to your destination after timer end.": "टाइमर की समय - सीमा खत्म होने के बाद आप अपने डेस्टिनेशन पर पहुँच जाएँगे।", "You can cancel trip": "आप ट्रिप कैंसिल कर सकते हैं", "The driver waitting you in picked location .": "आपके ड्राइवर पार्टनर तय लोकेशन पर आपका इंतज़ार कर रहे हैं।", "Pay with Your": "के द्वारा खोलें (i)", "Pay with Credit Card": "क्रेडिट कार्ड से भुगतान करें", "Payment History": "भुगतान इतिहास", "Show Promos to Charge": "शिपिंग प्रमोशन दिखाएँ", "Point": "pt", "Driver Balance": "ड्राइवर पार्टनर का वॉलेट", "Total Points is": "कुल स्कोर है", "Total Budget from trips is": "ट्रिप का कुल बजट है", "Total Amount:": "कुल राश", "Total Budget from trips by": "तक ट्रिप का कुल बजट", "Credit card is": "क्रेडिट कार्ड", "This amount for all trip I get from Passengers": "यह राशि उन सभी ट्रिप के लिए है, जो मुझे राइडर से मिलती हैं", "Pay from my budget": "मेरे बजट से भुगतान करें", "This amount for all trip I get from Passengers and Collected For me in": "यह राशि उन सभी ट्रिप के लिए है, जो मुझे में मेरे लिए इकट्ठा किए गए राइडर से मिलती हैं", "You can buy points from your budget": "आप अपने बजट से पॉइंट खरीद सकते हैं", "insert amount": "राशि डालें", "You can buy Points to let you online": "आप ऑनलाइन ऐक्सेस करने के लिए पॉइंट खरीद सकते हैं", "by this list below": "नीचे इस सूची के माध्यम से", "Create Wallet to receive your money": "अपना पैसा पाने के लिए एक वॉलेट बनाएँ", "Enter your feedback here": "अपना फ़ीडबैक यहाँ डालें", "Please enter your feedback.": "कृपया अपने नोट्स का टेक्स्ट डालें", "Feedback": "लांच फ़ीडबैक सक्षम करें (l)", "Click here to Show it in Map": "मैप पर इसे देखने के लिए यहाँ क्लिक करें", "Canceled": "कैंसिल किया गया", "Type your Email": "अपना ईमेल टाइप करें", "No I want": "मैं ठीक हूँ।", "Email is": "ईमेल", "Phone Number is": "फ़ोन नंबर", "Date of Birth is": "जन्मदिन: @ title: group", "Sex is": "लिंग है", "Car Details": "गाड़ी का ब्यौरा", "VIN is": "स्केलेटान नक़ल करें", "Color is": "रंग है", "Make is": "मेक है", "Model is": "फ़ॉर्म यहाँ से:", "Year is": "वर्ष", "Edit Your data": "अपने ब्यौरे में बदलाव करें", "write vin for your car": "अपनी गाड़ी का चेसिस नंबर लिखें", "VIN": "चेसिस नंबर", "write Color for your car": "अपनी कार का रंग टाइप करें", "write Make for your car": "अपनी कार के लिए मेक लिखें", "write Model for your car": "अपनी कार का मॉडल टाइप करें", "write Year for your car": "अपनी कार के लिए साल टाइप करें", "write Expiration Date for your car": "अपनी गाड़ी की समय - सीमा खत्म होने की तारीख लिखें", "Tariffs": "परिभाषाएँ", "Minimum fare": "30 मि.", "Maximum fare": "अधि.", "Flag-down fee": "स्टॉपओवर शुल्क", "Including Tax": "टैक्स सहित", "BookingFee": "बुकिंग शुल्क", "Morning": "Apki ek photo dekh skta hu", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07:30 - 10:30 (गुरुवार, शुक्रवार, शनिवार, सोमवार)", "Evening": "और फिर एक शाम...", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12:00 - 15:00 (गुरुवार, शुक्रवार, शनिवार, सोमवार)", "Night": "रात", "You have in account": "आपके अकाउंट में है", "Select Country": "देश चुनें", "Ride Today :": "आज ही राइड का अनुरोध करें :-", "After this period": "इस अवधि के बाद", "You can't cancel!": "आप कैंसिल नहीं कर सकते!", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "ड्राइवर चुनें", "Total Cost is": "कुल लागत है", "Write note": "टिप्पणीः", "Time to arrive": "पहुँचने का अनुमानित समय", "Ride Summaries": "ट्रिप के सारांश", "Total Cost": "कुल लागत", "Average of Hours of": "कार्य घंटे@ info: whatsthis", "is ON for this month": "इस महीने चल रहा है", "Days": "2 दिन", "Total Hours on month": "हर महीने घंटों की कुल संख्या", "Counts of Hours on days": "दिनों में घंटे", "OrderId": "निवेदन रोका गया", "created time": "निर्माण समय", "Intaleq Over": "एनिमेशन गति", "I will slow down": "मैं धीमा हो जाऊँगी.", "Map Passenger": "राइडर मैप", "Be Slowly": "धीमा रहें", "If you want to make Google Map App run directly when you apply order": "यदि आप कमांड लागू करते समय सीधे Google मानचित्र लॉन्च करना चाहते हैं", "You can change the language of the app": "आप ऐप की भाषा बदल सकते हैं", "Your Budget less than needed": "आपका बजट कम बजट वाला है", "You can change the Country to get all features": "आप सभी सुविधाएँ पाने के लिए देश बदल सकते हैं", "Change Country": "गैर - देश" }, "fa": { "Order": "سفارش", "OrderVIP": "سفارش VIP", "Cancel Trip": "لغو سفر", "Passenger Cancel Trip": "مسافر سفر را لغو کرد", "VIP Order": "سفارش VIP", "The driver accepted your trip": "راننده سفر شما را پذیرفت", "message From passenger": "پیام از طرف مسافر", "Cancel": "لغو", "Trip Cancelled. The cost of the trip will be added to your wallet.": "سفر لغو شد. هزینه سفر به کیف پول شما اضافه خواهد شد.", "token change": "تغییر رمز", "face detect": "تشخیص چهره", "Face Detection Result": "نتیجه تشخیص چهره", "similar": "مشابه", "not similar": "غیر مشابه", "Hi ,I will go now": "سلام، من الان میروم", "Passenger come to you": "مسافر به سمت شما می آید", "Call Income": "تماس ورودی", "Call Income from Passenger": "تماس ورودی از مسافر", "Criminal Document Required": "مدرک جنایی مورد نیاز است", "You should have upload it .": "شما باید آن را بارگذاری می کردید.", "Call End": "پایان تماس", "The order has been accepted by another driver.": "سفارش توسط راننده دیگری پذیرفته شده است.", "The order Accepted by another Driver": "سفارش توسط راننده دیگر پذیرفته شد", "We regret to inform you that another driver has accepted this order.": "متاسفیم به اطلاع شما برسانیم که راننده دیگری این سفارش را پذیرفته است.", "Driver Applied the Ride for You": "راننده برای شما درخواست سفر داده است", "Applied": "اعمال شد", "Hi ,I Arrive your site": "سلام، من به موقعیت شما رسیدم", "Please go to Car Driver": "لطفا به سمت راننده خودرو بروید", "Ok I will go now.": "باشه، من الان میروم.", "Accepted Ride": "سفر پذیرفته شد", "Driver Accepted the Ride for You": "راننده سفر را برای شما پذیرفت", "Promo": "تبلیغ", "Show latest promo": "نمایش آخرین تبلیغ", "Trip Monitoring": "نظارت بر سفر", "Driver Is Going To Passenger": "راننده به سمت مسافر می رود", "Please stay on the picked point.": "لطفا در نقطه انتخاب شده بمانید.", "message From Driver": "پیام از طرف راننده", "Trip is Begin": "سفر شروع شد", "Cancel Trip from driver": "لغو سفر از طرف راننده", "We will look for a new driver.\nPlease wait.": "ما به دنبال راننده جدیدی خواهیم بود.\nلطفا صبر کنید.", "The driver canceled your ride.": "راننده سفر شما را لغو کرد.", "Driver Finish Trip": "راننده سفر را تمام کرد", "you will pay to Driver": "شما به راننده پرداخت خواهید کرد", "Don’t forget your personal belongings.": "وسایل شخصی خود را فراموش نکنید.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "لطفا مطمئن شوید که تمام وسایل شخصی خود را برداشته‌اید و اگر مبلغ باقیمانده‌ای وجود دارد، قبل از رفتن به کیف پول شما اضافه شده است. از اینکه برنامه Intaleq را انتخاب کردید متشکریم", "Finish Monitor": "پایان نظارت", "Trip finished": "سفر به پایان رسید", "Call Income from Driver": "تماس ورودی از راننده", "Driver Cancelled Your Trip": "راننده سفر شما را لغو کرد", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "شما به راننده پرداخت خواهید کرد، هزینه زمان راننده را پرداخت خواهید کرد، به کیف پول Intaleq خود نگاه کنید", "Order Applied": "سفارش اعمال شد", //firebase "registration_date": "تاریخ ثبت نام", "expiration_date": "انقضا:", "rating_count": "تعداد بررسی ها", "rating_driver": "ارزیابی راننده", "age": "سن/سن", "vin": "شماره شناسایی خودرو رو توی ترابری", "car_color": "& رنگ‌", "car_plate": "پلاک اتومبیل", "car_model": "مدل ماشین:", "education": "-آموزش و پرورش .", "gender": "-چي؟ -اون سکس", "birthdate": "تولد", "Approve Driver Documents": "تایید مدارک شریک راننده", "Total Budget is": "کل بودجه", "You will recieve code in sms message": "کد را در پیامک دریافت خواهید کرد", "Please enter": "لطفاً ، نام منبعی را وارد کنید.", "We need your phone number to contact you and to help you receive orders.": "برای تماس با شما و کمک به شما در گرفتن سفارشات به شماره تلفن شما نیاز داریم.", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "نام کامل در سوابق کیفری شما با نام گواهینامه رانندگی شما مطابقت ندارد. لطفا بررسی کنید و مدارک صحیح را ارسال کنید.", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "شماره ملی گواهینامه رانندگی شما با شماره مندرج در مدرک هویت شما مطابقت ندارد. لطفا بررسی کنید و مدارک صحیح را ارسال کنید.", "Capture an Image of Your Criminal Record": "از سابقه کیفری خود عکس بگیرید", "IssueDate": "اولین کلید", "Capture an Image of Your car license front": "از جلوی گواهینامه ماشین خود عکس بگیرید", "Capture an Image of Your ID Document front": "یک عکس از مدرک شناسایی خود از جلو بگیرید", "NationalID": "شمار ملى ", "FullName": "نام", "InspectionResult": "نتیجه آزمایش", "Criminal Record": "سابقه کیفری", "The email or phone number is already registered.": "ایمیل یا شماره تلفن قبلا ثبت شده است.", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "برای تبدیل شدن به یک راننده اشتراکی در یک برنامه انطلق، باید گواهینامه رانندگی، سند هویت و سند ثبت وسیله نقلیه خود را آپلود کنید. سیستم هوش مصنوعی ما در عرض 2 تا 3 دقیقه فوراً صحت آن را بررسی و تأیید می کند. اگر مدارک شما تأیید شد، می توانید به عنوان شریک راننده در یک برنامه انطلق شروع به کار کنید. لطفا توجه داشته باشید که ارائه مدارک جعلی یک تخلف جدی است و ممکن است منجر به فسخ فوری و عواقب قانونی شود.", "Documents check": "تأیید سند", "Driver's License": "گواهينامه؟", "License Type": "مجوز:", "National Number": "کد ملی:", "Name (Arabic)": "نام (عربی)", "Name (English)": "بهانگليسي!", "Address": "آدرس چیه؟", "Issue Date": "اولین کلید", "Expiry Date": "تاریخ انقضا", "License Categories": "مجوز:", "driver_license": "گواهينامه؟", "Capture an Image of Your Driver License": "از گواهینامه رانندگی خود عکس بگیرید", "ID Documents Back": "پشت مدارک شناسایی", "National ID": "هویت ملی", "Occupation": "حرفه", "Gender": "-چي؟ -اون سکس", "Religion": "مذهب؟", "Marital Status": "وضعيت تاهل وعائله مندى: متاهل ", "Full Name (Marital)": "نام", "Expiration Date": "انقضا:", "Capture an Image of Your ID Document Back": "از پشت مدرک شناسایی خود عکس بگیرید", "ID Documents Front": "قسمت جلوی اسناد هویتی", "First Name": "نام کوچک", "CardID": "از پشت مدرک شناسایی خود عکس بگیرید", "Full Name": "نام", "Vehicle Details Front": "جزئیات خودروی جلو", "Plate Number": "پلاک اتومبيل رو برداشتي ؟", "Owner Name": "صاحب", "Vehicle Details Back": "جزئیات خودرو دوباره", "Make": "مقدار Û±", "Model": "مدل ماشین:", "Year": "دنار", "Chassis": "شاسی بلند", "Color": "& رنگ‌", "Displacement": "تعویض", "Fuel": "بنزين...", "Tax Expiry Date": "تاریخ انقضا", "Inspection Date": "تاریخ امتحان", "Capture an Image of Your car license back": "دوباره از گواهینامه ماشین خود عکس بگیرید", "Capture an Image of Your Driver’s License": "از گواهینامه رانندگی خود عکس بگیرید", "Sign in with Google for easier email and name entry": "با Google وارد شوید تا وارد کردن ایمیل و نام خود را آسان کنید", "You will choose allow all the time to be ready receive orders": "شما انتخاب می کنید که تمام وقت برای دریافت سفارشات آماده اجازه دهید", "Welcome to Intaleq!": "به خونه خوش اومدی", "Get to your destination quickly and easily.": "سریع و آسان به مقصد برسید.", "Enjoy a safe and comfortable ride.": "از یک سواری امن و راحت لذت ببرید.", "Choose Language": "انتخاب ظاهر و احساس", "Login": "ورود به سیستم", "Pay with Wallet": "با استفاده از کیف پول پرداخت کنید", "Invalid MPIN": "کد MPIN نامعتبر است", "Invalid OTP": "کد تأیید نامعتبر است", "Enter your email address": "آدرس ایمیل خود را وارد کنید", "Please enter Your Email.": "لطفا وارد کنید...", "Enter your phone number": "شماره تلفن خود را وارد کنید", "Please enter your phone number.": "لطفا شماره تلفن خود را وارد کنید.", "Please enter Your Password.": "اسم رمز ورودی", "Submit": ".فرستاده شود", "if you dont have account": "اگه اشکالي نداره", "Register": "نامنويسي کردن , ثبت نام کردن , عضويت دادن , درفهرست واردکردن , در صورت نوشتن , نام نويسي کردن (در هيلت منصفه)", "Accept Ride's Terms & Review Privacy Notice": "شرایط انطلق را بپذیرید و اعلامیه حریم خصوصی را مرور کنید", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "با انتخاب «موافقم» در زیر، شرایط استفاده را بررسی کرده و با آن موافقم و اعلامیه حریم خصوصی را تأیید می‌کنم.من حداقل 18 سال دارم.", "I Agree": "بله!", "First name": "نام کوچک", "Enter your first name": "لطفاً نام و نام خانوادگی‌تان را وارد کنید:", "Please enter your first name.": "لطفا نام خود را وارد کنید.", "Last name": "فاميليت", "Enter your last name": "فاميليت", "Please enter your last name.": "لطفا نام خود را وارد کنید.", "City": "داخل شهره", "Please enter your City.": "لطفا وارد کنید...", "Male": "ياداوري کردن , ياداور شدن , بياد اوردن", "Female": "زن", "Verify Email": "اعتبار سنجی ایمیل", "We sent 5 digit to your Email provided": "ما 5 شماره به ایمیل شما ارسال کردیم", "5 digit": "پین (5 رقمی)", "Send Verification Code": "کد تایید", "Your Ride Duration is": "مدت انطلق شما است", "You will be thier in": "شما در آنها خواهید بود", "You trip distance is": "مسافت پیاده روی شما است", "Fee is": "هزینه ها هستند", "To :": "بيماريِ آسپرگرِش؟", "Add Promo": "افزودن نما", "Confirm Selection": "انتخاب را تایید کنید", "distance is": "فاصله است", "duration is": "مدت زمان است", "I don't need a ride anymore": "من دیگر نیازی به سواری ندارم", "I was just trying the application": "من فقط برنامه را امتحان کردم", "No driver accepted my request": "هیچ شریک راننده ای درخواست من را نپذیرفت", "I added the wrong pick-up/drop-off location": "اضافه شدن مکان نادرست تحویل / تحویل", "I don't have a reason": "يه دليلي دارم.", "Other": "يكي ديگه", "Can we know why you want to cancel Ride ?": "آیا می‌توانیم بدانیم چرا می‌خواهید انطلق را لغو کنید؟", "Cancel Ride": "متوقفش کنيد!", "Add Payment Method": "یک روش پرداخت اضافه کنید", "Your Wallet balance is": "موجودی کیف پول شما است", "Ride Wallet": "کیف پول انطلق", "Payment Method": "و چه جوري هزينه اش رو پرداخت ميکنيد؟", "Type here Place": "مکان را اینجا بنویسید", "Are You sure to ride to": "آیا مطمئن هستید که قصد انطلق به ...", "Confirm": "تاييد شد", "Back": "بازگشت , مراجعت", "You are Delete": "شما حذف کنید", "Deleted": "حذف‌شده", "You Dont Have Any places yet !": "شما هنوز جایی ندارید!", "Favorite Places": "مکان های مورد علاقه", "From : Current Location": "موقعيت فعلي: اسکدارسکا32", "Where to": "-البته. کجا؟", "Notifications": "& پیکربندی آگاه‌سازی‌ها", "Profile": "‏پروفایل؟", "Home": "آغازه", "My Cared": "ممکن است کاهش یابد", "Add Card": "کارت اضافه کنید", "Add Credit Card": "درخواست كارت المثني ", "Please enter the cardholder name": "لطفا نام دارنده کارت را وارد کنید", "Please enter the expiry date": "لطفا تاریخ انقضا را وارد کنید", "Please enter the CVV code": "لطفا کد تایید کارت را وارد کنید", "Go To Favorite Places": "به مکان های مورد علاقه بروید", "Go to this Target": "برو به اون هدف", "My Profile": "نام Profile", "Sign Out": "همه ي ارتباط ها قطع شد", "Home Page": "آغازه", "Are you want to go to this site": "آیا می خواهید به این سایت بروید؟", "MyLocation": "محل من", "my location": "محل من", "Target": "يه هدف.", "Update": "نوسازي , نوپردازي , نوين گري", "You Should choose rate figure": "باید عدد صحیح را انتخاب کنید", "Login Captin": "ورود به سیستم", "Register Captin": "ثبت نام کاپیتان", "Send Verfication Code": "ارسال کد تایید", "End Ride": "سواری", "Minute": "حساسيت", "Go to passenger Location now": "اکنون به وب سایت سوارکار بروید", "Duration of the Ride is": "مدت انطلق است", "Distance of the Ride is": "مسافت پیاده روی است", "Name of the Passenger is": "نام مسافر است", "Hello this is Captain": "سلام من کاپیتان هستم", "Start the Ride": "انطلق را آغاز کنید", "Please Wait If passenger want To Cancel!": "لطفا صبر کنید اگر مسافر می خواهد لغو کند!", "Total Duration:": "کل مدت زمان:", "Active Duration:": "مدت زمان گام فعال", "Waiting for Captin ...": "منتظر کاپیتان...", "Age is": ". بزرگ شده", "Rating is": "ارزیابی است", "to arrive you.": "برای رسیدن به تو", "Order History": "سابقه سفارش را ثبت کنید", "My Wallet": "کيفم", "Tariff": "تعرفه", "Settings": "GnomeMeeting", "Feed Back": "واکنش ها", "Promos": "تبلیغات", "Please enter a valid 16-digit card number": "لطفاً یک شماره سفارش خرید معتبر وارد کنید.", "Add Phone": "تلفن", "Please enter a phone number": "لطفا شماره تلفن را وارد کنید", "You dont Add Emergency Phone Yet!": "هنوز تلفن اضطراری اضافه نکرده‌اید!", "You will arrive to your destination after": "هنوز به مقصد خواهی رسید", "You can cancel Ride now": "اکنون می توانید انطلق را لغو کنید", "You Can cancel Ride After Captain did not come in the time": "بعد از اینکه کاپیتان به موقع نرسید می توانید انطلق را لغو کنید", "If you in Car Now. Press Start The Ride": "اگر الان در ماشین هستید. روی شروع انطلق کلیک کنید", "You Dont Have Any amount in": "شما هیچ مبلغی ندارید", "Wallet!": "کيسه , جيب , کيسه پول , کيف پول , پول , دارايي , وجوهات خزانه , غنچه کردن , جمع کردن , پول دزديدن , جيب بري کردن , کيف جيبي", "You Have": "تو داري مياي ؟", "Save Credit Card": "کارت اعتباری را نگه دارید", "Show Promos": "مشاهده پیشنهادات", "10 and get 4% discount": "10 و 4 درصد تخفیف بگیرید", "20 and get 6% discount": "20 و 6 درصد تخفیف بگیرید", "40 and get 8% discount": "40 و 8 درصد تخفیف بگیرید", "100 and get 11% discount": "100 و 11 درصد تخفیف بگیرید", "Pay with Your PayPal": "با پی پال پرداخت کنید", "You will choose one of above !": "شما یکی از گزینه های بالا را انتخاب خواهید کرد!", "Cancel": "& لغو‌", "Delete My Account": "Delete My Account", "Edit Profile": "‏پروفایل؟", "Name": "اسم...", "Update Gender": "به روز رسانی جنسیت", "Education": "-آموزش و پرورش .", "Update Education": "نوسازی آموزش و پرورش", "Employment Type": "کارم ؟", "SOS Phone": "تلفنچي", "High School Diploma": "مدرک دبیرستان", "Associate Degree": "مدرک دیپلم مشترک", "Bachelor's Degree": "-اون دکتراست .", "Master's Degree": ". استاد", "Doctoral Degree": "و دکترات", "Promos For today": "تبلیغات امروز", "Copy this Promo to use it in your Ride!": "این تبلیغ را برای استفاده در انطلق خود کپی کنید!", "To change some Settings": "برای تغییر برخی تنظیمات", "To change Language the App": "برای تغییر زبان برنامه", "Order Request Page": "صفحه درخواست سفارش", "Rouats of Trip": "! \" تريپ \"", "Passenger Name is": "يک مسافر", "Total From Passenger is": "مجموع مسافر است", "Duration To Passenger is": "مدت زمان به مسافر", "Distance To Passenger is": "فاصله تا مسافر", "Total For You is": "مجموع برای شما است", "Distance is": "فاصله هستيم", "KM": "کيلومتر , هزارمتر", "Duration of Trip is": "مدت پرواز است", "Minutes": "صورت جلسه , خلا صه مذاکرات", "Apply Order": "درخواست درخواست", "Refuse Order": "که درخواست رد شد", "Rate Captain": "امتیاز کاپیتان", "Enter your Note": "یادداشت خود را وارد کنید", "Type something...": "چیزی بنویسید...", "Submit rating": "ارزیابی ارائه کنید", "Rate Passenger": "رتبه سوار", "Ride Summary": "خلاصه انطلق", "welcome_message": "درج Hello World", "app_description": "& پیاده‌سازی‌", "get_to_destination": "مقصد کار انجامی", "get_a_ride": "گمشو...", "safe_and_comfortable": "و خيلي هم راحته", "committed_to_safety": "متعهد به ایمنی", "Driver Applied the Ride for You": "یک راننده انطلق را برای شما انجام داد", "Show latest promo": "نمایش آخرین تبلیغات", "Cancel Trip": "لغو انطلق", "Passenger Cancel Trip": "مسافر پرواز را لغو کرد", "Please stay on the picked point.": "لطفا روی نقطه بمانید", "Trip is Begin": "برنامه انطلق , خط سير , انطلقنامه", "Hi ,I will go now": "هی الان میرم", "Passenger come to you": "مسافر به سمت شما می آید", "Hi ,I Arrive your site": "سلام من به سایت شما رسیدم", "Driver Finish Trip": "انطلق برای راننده به پایان می رسد", "you will pay to Driver": "شما به راننده پول می دهید", "Driver Cancel Your Trip": "انطلقت را کنسل کن راننده", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "شما به راننده پرداخت می کنید هزینه وقت راننده را می پردازید به کیف پول خود Intaleq نگاه کنید", "I will go now": "دود باید برم باید برم", "You Have Tips": "نکته؟", "tips": "مدد", "Total is": "پانزده نفر شدن", "No,I want": "من از اونا نيستم", "Your fee is": "هزینه های شما هستند", "Do you want to pay Tips for this Driver": "آیا می خواهید به این راننده انعام بدهید؟", "Tip is": "نکته من", "Camera Access Denied.": "دسترسی به دوربین ممنوع است.", "Open Settings": "تنظیمات...", "GPS Required Allow !.": "GPS باید فعال باشد!", "Your Account is Deleted": "حساب شما حذف شده است", "Are you sure to delete your account?": "آیا مطمئن هستید که می خواهید اکانت خود را حذف کنید؟", "Your data will be erased after 2 weeks": "اطلاعات شما پس از دو هفته پاک می شود", "And you will can't return to use app after 1 month": "بعد از یک ماه می توانید به استفاده از برنامه بازگردید", "Enter Your First Name": "لطفاً نام و نام خانوادگی‌تان را وارد کنید:", "Are you Sure to LogOut?": "آیا مطمئن هستید که از سیستم خارج می شوید؟", "Email Wrong": "پست الکترونیکی", "Email you inserted is Wrong.": "ایمیلی که وارد کردید نادرست است.", "You have finished all times": "نميخوام که تو ...", "if you want help you can email us here": "اگر مایل به کمک هستید می توانید از اینجا به ما ایمیل بزنید", "Thanks": "ممنون.", "Email Us": "یک ایمیل برای ما بفرستید", "I cant register in your app in face detection": "من نمی توانم با استفاده از تشخیص چهره در برنامه شما ثبت نام کنم", "Hi": "هالو (کلمه اي که در گفتگوي تلفني براي صدا کردن طرف بکار ميرود) , سلا م کردن , خوشامد , خوشامد گفتن , پذيرايي کردن , خوشايند", "No face detected": "هیچ چهره ای آشکار نشد", "Image detecting result is": "نتیجه تشخیص تصویر:", "from 3 times Take Attention": "بیش از 3 بار توجه خود را جلب کنید", "Be sure for take accurate images please": "حتما عکس های دقیق بگیرید لطفا", "You have": "تو داري مياي ؟", "image verified": "عکس محضری است", "Next": "بعد", "There is no help Question here": "در اینجا هیچ سوال کمکی وجود ندارد", "Call End": "تماس تمام می شود", "You dont have Points": "-شليک نکنيد ! - شما اجازه‌ي ورود ...", "You Are Stopped For this Day !": "شما برای یک روز تعلیق هستید!", "You must be charge your Account": "شما باید حساب خود را شارژ کنید", "You Refused 3 Rides this Day that is the reason": "من امروز 3 پرواز را رد کردم و دلیلش این است", "See you Tomorrow!": "فردا می بینمت!", "Recharge my Account": "حسابم را شارژ کن", "Ok , See you Tomorrow": "باشه فردا میبینمت", "You are Stopped": "شما خاموش هستید", "Connected": "پيوسته , روان , خط شکسته", "Not Connected": "برون خطي", "Your are far from passenger location": "شما از سایت مسافر دور هستید", "go to your passenger location before": "قبلاً به وب سایت مسافر خود بروید", "Passenger cancel trip": "مسافر پرواز را کنسل کرد", "You will get cost of your work for this trip": "هزینه کار خود را برای این انطلق دریافت خواهید کرد", "in your wallet": "تو کيف پولته.", "you gain": "تو بردي", "Order Cancelled": "بسه ديگه.", "Order Cancelled by Passenger": "سفارش توسط مسافر لغو شد", "Success": "بدست آوردن بيشترش", "Feedback data saved successfully": "داده های ارزیابی با موفقیت ذخیره شد", "No Promo for today .": "امروز تبلیغاتی وجود ندارد", "Select your destination": "مقصد خود را انتخاب کنید", "Search for your Start point": "نقطه شروع خود را پیدا کنید", "Search for waypoint": "نقطه راه را پیدا کنید", "Current Location": "موقعيت فعلي: اسکدارسکا32", "Add Location 1": "محل:% 1", "You must Verify email !.": "بررسی & نامه‌", "Cropper": "دروگر", "Saved Sucssefully": "با موفقیت ذخیره شد", "Select Date": "انتخاب یک تاریخ جدید", "Birth Date": "- تاريخ تولد", "Ok": "صحيح است , خوب , بسيار خوب , تصويب کردن , موافقت کردن , اجازه , تصويب , چشمه , جوهردان , دوات , ببالا فوران کردن , روامدن اب ومايع , درسطح امدن وجاري شدن , تندرست , سالم , راحت , بسيارخوب , به چشم , تماما , تمام وکمال , بدون اشکال , اوه , خيلي خوب", "the 500 points equal 30 JOD": "500 امتیاز معادل 30 دینار اردن است", "the 500 points equal 30 JOD for you": "500 امتیاز برای شما معادل 30 دینار اردن است", "token updated": "کد به روز شده است", "Add Location 2": "اضافه کردن مکان 2", "Add Location 3": "اضافه کردن مکان 3", "Add Location 4": "سایت را اضافه کنید 4", "Waiting for your location": "منتظر مکان شما هستیم", "Search for your destination": "مقصد خود را پیدا کنید", "Hi! This is": "خوش‌آمدید اين", "I am using": "من استفاده می کنم", "to ride with": "برای سوار شدن با", "as the driver.": "به عنوان راننده", "is driving a": "اون رانندگي ميکنه", "with license plate": "داشتن پلاک", "I am currently located at": "من در حال حاضر در", "Please go to Car now": "لطفا همین الان برید سراغ ماشین", "If you need to reach me, please contact the driver directly at": "اگر نیاز به تماس با من دارید، لطفاً مستقیماً با راننده تماس بگیرید", "No Car or Driver Found in your area.": "هیچ ماشین یا راننده ای در منطقه شما پیدا نشد.", "Please Try anther time": "سعی مجدد", "There no Driver Aplly your order sorry for that": "هیچ راننده ای وجود ندارد که بتواند درخواست شما را برآورده کند، متأسفیم.", "Trip Cancelled": "پرواز لغو شده است", "The Driver Will be in your location soon .": "راننده به زودی در محل شما خواهد بود.", "The distance less than 500 meter.": "فاصله کمتر از 500 متر است.", "Promo End !": "پیشنهاد به پایان می رسد!", "There is no notification yet": "هنوز اطلاعیه ای وجود ندارد", "Use Touch ID or Face ID to confirm payment": "برای تأیید پرداخت از Touch ID یا Face ID استفاده کنید", "Contact us for any questions on your order.": "برای هرگونه سوال در مورد سفارش خود با ما تماس بگیرید.", "Pyament Cancelled .": "پرداخت لغو شده است.", "type here": "نوشتن", "Scan Driver License": "گواهينامه؟", "Please put your licence in these border": "لطفا مجوز خود را در این محدوده قرار دهید", "Camera not initialized yet": "دوربین هنوز پیکربندی نشده است", "Take Image": "- # I need direction, ah, please #", "AI Page": "صفحه هوش مصنوعی", "Take Picture Of ID Card": "از کارت شناسایی خود عکس بگیرید", "Take Picture Of Driver License Card": "از کارت گواهینامه رانندگی خود عکس بگیرید.", "We are process picture please wait": "ما در حال پردازش تصاویر هستیم، لطفا صبر کنید.", "There is no data yet.": "هنوز هیچ داده ای وجود ندارد.", "Name :": "اسم...", "Drivers License Class:": "دسته گواهینامه رانندگی:", "Document Number:": "شماره سند:", "Address:": "آدرس:", "Height:": "قد، متوسط.", "Expiry Date:": "انقضا:", "Date of Birth:": "تولد: @ title: group", "You can't continue with us .": "‫ - می تونی ادامه بدی.", "You should renew Driver license": "باید گواهینامه رانندگی خود را تمدید کنید", "Detect Your Face": "اين جديده", "Go to next step": "به مرحله بعد برو", "scan Car License.": "معاینه گواهینامه خودرو.", "Name in arabic": "نام به عربی", "Drivers License Class": "گواهينامه؟", "Date of Birth": "- تاريخ تولد", "Age": "سالخوردگی", "Lets check Car license": "بیایید گواهینامه ماشین را بررسی کنیم", "Car Kind": "چه جور ماشینی ؟", "Car Plate": "پلاک اتومبیل", "Lets check License Back Face": "اجازه دهید مجوز سمت عقب را بررسی کنیم", "Car License Card": "کارت گواهینامه خودرو", "No image selected yet": "هنوز هیچ تصویری انتخاب نشده است", "Made :": "ساختن , بوجود اوردن , درست کردن , تصنيف کردن , خلق کردن , باعث شدن , وادار يامجبور کردن , تاسيس کردن , گاييدن , ساختمان , ساخت , سرشت , نظير , شبيه", "model :": "مدل:", "VIN :": "شماره ساختار:", "year :": "!", "ُExpire Date": "انقضا:", "Login Driver": "ورود به سیستم", "Password must br at least 6 character.": "رمز عبور باید حداقل 6 کاراکتر باشد.", "if you don't have account": "اگه اشکالي نداره", "Here recorded trips audio": "در اینجا ضبط های صوتی انطلق است", "Register as Driver": "به عنوان شریک راننده ثبت نام کنید", "Privacy Notice": "اطلاعیه حفظ حریم خصوصی", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "با انتخاب «موافقم» در زیر، شرایط و ضوابط را بررسی کرده، با آن موافقم و تأیید می کنم.", ". I am at least 18 years of age.": ". من حداقل 18 سال دارم.", "Log Out Page": "همه ي ارتباط ها قطع شد", "Log Off": "خروج CVS", "Register Driver": "راننده...\"راس وبر\"...", "Verify Email For Driver": "ایمیل راننده را چک کنید", "Admin DashBoard": "کنترل پنل مدیریت", "Your name": "اسمت", "your ride is applied": "انطلق شما اعمال شده است", "Your password": "اسم رمز شما تغییر کرده است.", "LE": "پوند مصر", "JOD": "دینار اردن", "m": "مستندسازی از", "We search nearst Driver to you": "ما به دنبال نزدیکترین شریک راننده به شما هستیم", "please wait till driver accept your order": "لطفا منتظر بمانید تا راننده درخواست شما را بپذیرد", "No accepted orders? Try raising your trip fee to attract riders.": "هیچ درخواستی پذیرفته نشد؟ سعی کنید هزینه پرواز خود را برای جذب مسافر افزایش دهید.", "You should select one": "شما باید یکی را انتخاب کنید", "The driver accept your order for": "راننده در عوض درخواست شما را پذیرفت", "Increase Fee": "هزینه ها را افزایش دهید", "No, thanks": "نه، متشکرم.", "The driver on your way": "راننده شما در راه است", "Total price from": "قیمت کل از", "Order Details Intaleq": "جزئیات درخواست:", "Order Applied": "درخواست اعمال شده است", "accepted your order": "درخواست شما پذیرفته شد", "We regret to inform you that another driver has accepted this order.": "متأسفانه به شما اطلاع می دهیم که شریک راننده دیگری این درخواست را پذیرفته است.", "Selected file:": "باز کردن پرونده‌ای موجود", "Your trip cost is": "هزینه انطلق شما", "this will delete all files from your device": "با این کار تمام فایل ها از دستگاه شما حذف می شود", "you have a negative balance of": "تراز منفی دارید", "in your": "که ما به تو ايمان نداشته باشيم.", "Exclusive offers and discounts always with the Intaleq app": "همیشه پیشنهادات و تخفیفات منحصر به فرد با اپلیکیشن انطلق", "Please go to Car Driver": "لطفا به سراغ راننده ماشین بروید", "wallet due to a previous trip.": "کیف پول به دلیل انطلق قبلی.", "Submit Question": "ارسال سوال", "Please enter your Question.": "لطفا سوال خود را وارد کنید", "Help Details": "جزئیات راهنما", "No trip yet found": "نبض اشعه گاما", "No Response yet.": "هنوز پاسخی داده نشده است.", "You Earn today is": "- ام، امروز ...", "You Have in": "شما آن را در", "Total points is": "مجموع امتیاز است", "Total Connection Duration:": "کل مدت تماس:", "H and": "H و", "Passenger name :": "يک مسافر", "Cost Of Trip IS": "هزینه انطلق است", "Arrival time": "دستيابي پذير", "arrival time to reach your point": "زمان رسیدن برای رسیدن به مقصد", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "برای انطلقهای سریع و تحویل، قیمت به صورت پویا محاسبه می شود. در مورد انطلقهای راحت، قیمت بستگی به زمان و مسافت دارد.", "Hello this is Driver": "سلام من راننده شما هستم", "Is the Passenger in your Car ?": "آیا مسافر در ماشین شما است؟", "Please wait for the passenger to enter the car before starting the trip.": "لطفا قبل از شروع انطلق منتظر ورود مسافر به وسیله نقلیه باشید.", "No ,still Waiting.": "نه من همچنان منتظرت هستم", "I arrive you": "\"سلام، مامور \"دانم", "I Arrive your site": "\"سلام، مامور \"دانم", "You are not in near to passenger location": "شما نزدیک محل مسافر نیستید", "please go to picker location exactly": "لطفا به محل دقیق انتخابی بروید", "You Can Cancel Trip And get Cost of Trip From": "می توانید انطلق را کنسل کنید و هزینه انطلق را از اینجا دریافت کنید", "Are you sure to cancel?": "آیا مطمئن هستید که می خواهید لغو کنید؟", "Yes": "بله , بلي , اري , بلي گفتن", "Insert Emergincy Number": "ـ شماره تلفن آمبولانس", "Best choice for comfort car and flexible route and stops point": "بهترین انتخاب برای ماشین راحت، مسیر انعطاف پذیر و نقطه توقف", "Insert": "درج", "This is for delivery or a motorcycle.": "این برای تحویل یا موتور است.", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "این سواری مستقیماً از نقطه شروع شما به مقصد شما با قیمت ثابت می رود. راننده باید مسیر برنامه ریزی شده را دنبال کند", "You can decline a request without any cost": "شما می توانید درخواست را بدون هیچ هزینه ای رد کنید", "Perfect for adventure seekers who want to experience something new and exciting": "ایده آل برای جویندگان ماجراجویی که می خواهند چیز جدید و هیجان انگیزی را امتحان کنند", "My current location is:": "مکان فعلی من این است:", "and I have a trip on": "و من یک انطلق به داخل دارم", "App with Passenger": "درخواست با مسافر", "You will be pay the cost to driver or we will get it from you on next trip": "هزینه به راننده شما پرداخت می شود یا در انطلق بعدی آن را از شما دریافت می کنیم", "Trip has Steps": "انطلق مراحلی دارد", "Distance from Passenger to destination is": "فاصله مسافر تا مقصد است", "price is": "قیمت است", "This ride type does not allow changes to the destination or additional stops": "این نوع انطلق اجازه تغییر مقصد یا توقف های اضافی را نمی دهد", "This price may be changed": "این قیمت ممکن است تغییر کند", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "سیم کارت نداره مشکلی نیست! مستقیماً از طریق برنامه ما با راننده خود تماس بگیرید. ما از فناوری پیشرفته برای اطمینان از حریم خصوصی شما استفاده می کنیم.", "This ride type allows changes, but the price may increase": "این نوع انطلق اجازه تغییرات را می دهد، اما ممکن است قیمت افزایش یابد", "message From passenger": "پیام مسافر", "Select one message": "حتی یدونه؟", "My location is correct. You can search for me using the navigation app": "مکان من درست است می توانید با استفاده از برنامه ناوبری من را جستجو کنید", "I'm waiting for you": ".فکر کنم منتظر شماست", "Hello, I'm at the agreed-upon location": "سلام من در محل مورد توافق هستم", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "ما متوجه شدیم که سرعت از 100 کیلومتر در ساعت فراتر رفته است. لطفا برای ایمنی خود سرعت خود را کم کنید. اگر احساس ناامنی می‌کنید، می‌توانید جزئیات پرواز خود را با یک مخاطب به اشتراک بگذارید یا با استفاده از دکمه قرمز خطر با پلیس تماس بگیرید.", "Warning: Intaleqing detected!": "هشدار: سرعت بیش از حد شناسایی شد!", "Please help! Contact me as soon as possible.": "لطفأ ، کمکم کن. در اسرع وقت با من تماس بگیرید.", "Share Trip Details": "جزئیات انطلق را به اشتراک بگذارید", "Car Plate is": "پلاک اتومبیل", "the 3000 points equal 3000 L.E for you": "3000 امتیاز برای شما معادل 3000 پوند مصر است", "So go and gain your money": "برو جلو و پولت را در بیاور", "the 3000 points equal 3000 L.E": "3000 امتیاز معادل 3000 پوند مصر است", "The payment was not approved. Please try again.": "پرداخت تایید نشد سعی مجدد", "Payment Failed": "پرداخت ناموفق", "Error": "اشتباه ميكني", "An error occurred during the payment process.": "خطایی در فرآیند پرداخت رخ داد.", "The payment was approved.": "پرداخت تایید شده است.", "Payment Successful": "پرداخت با موفقیت انجام شد", "No ride found yet": "نبض اشعه گاما", "Accept Order": "بسه ديگه.", "reject your order.": "درخواست شما رو رد کنيم... .", "Bottom Bar Example": "نمونه ای از نوار پایین", "Driver phone": "تلفن شریک راننده", "Statistics": "آمارها", "Origin": ".ابتداييهستن. ..", "Destination": "به مقصد", "Driver Name": "راننده...\"راس وبر\"...", "Driver Car Plate": "پلاک ماشین راننده", "Available for rides": "برای انطلقها موجود است", "Scan Id": "بررسی هویت", "Camera not initilaized yet": "دوربین هنوز پیکربندی نشده است", "Scan ID MklGoogle": "بررسی هویت MklGoogle", "Language": "زبان", "Jordan": "اردن", "USA": "- ايالات متحده -", "Egypt": "کشور مصر , مصر , پافشار , پاپي", "Turkey": "ترکیه", "Saudi Arabia": "عربستان سعودی", "Qatar": "تقطيرشدن , عرق گرفتن از , چکاندن", "Bahrain": "بحرین", "Kuwait": "کویت", "But you have a negative salary of": "اما شما حقوق منفی از", "Promo Code": "کد تبلیغاتی", "Your trip distance is": "مسافت انطلق شما است", "Enter promo code": "کد تبلیغاتی را وارد کنید", "You have promo!": "شما یک ترفیع دارید!", "Cost Duration": "هزينه ؟", "Duration is": "مدت زمان است", "Leave": "واگذار کردن , تسليم کردن , صرفنظرکردن از , ول کردن , ترک , رها کردن , انکار کردن , ترک کردن , چشم پوشيدن , سرزنش يا متهم کردن , چشم پوشيدن از , از قانون مستثني کردن", "Join": "متصل", "You Should be select reason.": "باید دلیل انتخاب کنی", "\$": "\$", "Waiting for Driver ...": "منتظر راننده ام...", "Latest Recent Trip": "آخرین انطلق", "from your list": "از لیست شما", "Do you want to change Work location": "آیا می خواهید محل کار را تغییر دهید؟", "Do you want to change Home location": "آیا می خواهید مکان خانه را تغییر دهید؟", "We Are Sorry That we dont have cars in your Location!": "متاسفیم که خودروها در محل شما در دسترس نیستند!", "Choose from Map": "از نقشه انتخاب کنید", "Pick your ride location on the map - Tap to confirm": "مکان سواری خود را روی نقشه انتخاب کنید - برای تأیید ضربه بزنید", "To Work": "اوه درسته ، پرونده ...", "Are you want to go this site": "آیا می خواهید به این سایت بروید؟", "Closest & Cheapest": "نزدیک ترین و ارزان ترین", "Work Saved": "نگهداري , حفظ , محافظت , جلوگيري , حراست", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq یک برنامه سواری ایمن، قابل اعتماد و در دسترس است.", "With Intaleq, you can get a ride to your destination in minutes.": "با Safar، می توانید در عرض چند دقیقه به مقصد خود برسید.", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "انطلق به ایمنی متعهد است و همه رهبران ما به دقت مورد بررسی قرار می گیرند و سوابق جنایی خود را بررسی می کنند.", "To Home": "آغازه", "Home Saved": "نگهداري , حفظ , محافظت , جلوگيري , حراست", "Destination selected": "مقصد مشخص شد - !", "Now select start pick": "اکنون Start Selection را انتخاب کنید", "Pick from map": "از نقشه انتخاب کنید", "Click here point": "اينجا كليك كنيد", "No Car in your site. Sorry!": "هیچ ماشینی در محل شما وجود ندارد. ببخشيد", "Nearest Car for you about": "نزدیکترین ماشین به شما تقریبا", "N/A": "بدون اطلاعات", "From :": "از , بواسطه , درنتيجه , از روي , مطابق , از پيش , قطع , خاموش , ملغي , پرت , دور , نسبت به , تا , که , تا اينکه , بجز , غير از , کي , چه شخصي , چه اشخاصي , چه کسي , هرکه , هر انکه , هر انکس , هرکسي که , چه کسي را , به چه کسي , کسيکه , ان کسي که", "Get Details of Trip": "دریافت جزئیات پرواز", "If you want add stop click here": "اگر می خواهید توقف اضافه کنید، اینجا را کلیک کنید", "Driver": "راننده ماشين , شوفر , رانندگي کردن , محرک , راننده , ماشين سوار", "Where you want go": "ميتوني اين قضيه رو باور کني؟ فکر ميکني کجا بخواي بري؟", "My Card": "کارتم", "Start Record": "درحال شروع برای ضبط", "Wallet": "کيسه , جيب , کيسه پول , کيف پول , پول , دارايي , وجوهات خزانه , غنچه کردن , جمع کردن , پول دزديدن , جيب بري کردن , کيف جيبي", "History of Trip": "تاریخ انطلق", "Helping Center": "مرکز کمک KDE", "Record saved": "رکورد ذخیره شده است", "Trips recorded": "پروازهای ثبت شده", "Select Your Country": "گزيدن , انتخاب کردن , خواستن , پسنديدن , برگزيدن", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "برای اطمینان از دریافت دقیق ترین اطلاعات برای موقعیت مکانی خود، لطفاً کشور خود را در زیر انتخاب کنید. این به شخصی‌سازی تجربه برنامه و محتوا برای کشورتان کمک می‌کند.", "Are you sure to delete recorded files": "آیا مطمئن هستید که فایل های ضبط شده را حذف می کنید؟", "Select recorded trip": "یک انطلق ثبت شده را انتخاب کنید", "Card Number": "بزن!", "Hi, Where to": "سلام به کجا", "Pick your destination from Map": "مقصد خود را از روی نقشه انتخاب کنید", "Add Stops": "مکث اضافه کنید", "Get Direction": "جهت را دریافت کنید", "Add Location": "اضافه کردن مکان", "Switch Rider": "تعویض مسافر", "You will arrive to your destination after timer end.": "پس از اتمام تایمر به مقصد خواهید رسید.", "You can cancel trip": "می توانید انطلق را لغو کنید", "The driver waitting you in picked location .": "راننده شما در محل تعیین شده منتظر شماست.", "Pay with Your": "پرداخت با استفاده از", "Pay with Credit Card": "پرداخت با کارت اعتباری", "Payment History": "سابقه پرداخت", "Show Promos to Charge": "نمایش تبلیغات حمل و نقل", "Point": "نقطه , خال , لکه , نقطه دار کردن , نوک , سر , نکته , ماده , اصل , موضوع , جهت , درجه , امتياز بازي , نمره درس , پوان , هدف , مسير , مرحله , قله , پايان , تيزکردن , گوشه دارکردن , نوکدار کردن , نوک گذاشتن (به) , خاطر نشان کردن , نشان دادن , متوجه ساختن , نقطه گذاري کردن , لک , لکه يا خال ميوه , ذره , لکه دار کردن , خالدار کردن", "Driver Balance": "کیف پول راننده", "Total Points is": "مجموع امتیاز است", "Total Budget from trips is": "بودجه کل انطلقها می باشد", "Total Amount:": "مبلغ کل:", "Total Budget from trips by": "بودجه کل انطلقها توسط", "Credit card is": "کارت بانکي سيهاون همراهمه", "This amount for all trip I get from Passengers": "این مبلغ برای تمام انطلقهایی است که از مسافران می گیرم", "Pay from my budget": "من از بودجه ام پرداخت می کنم", "This amount for all trip I get from Passengers and Collected For me in": "این مبلغ برای تمام سواری هایی است که از مسافران می گیرم و برایم جمع آوری شده است", "You can buy points from your budget": "شما می توانید از بودجه خود امتیاز خریداری کنید", "insert amount": "همش اونجاست", "You can buy Points to let you online": "می توانید امتیازهایی را خریداری کنید تا بتوانید به صورت آنلاین وارد شوید", "by this list below": "از طریق این لیست زیر", "Create Wallet to receive your money": "برای دریافت وجوه خود یک کیف پول ایجاد کنید", "Enter your feedback here": "بازخورد خود را اینجا وارد کنید", "Please enter your feedback.": "لطفا متن بازخورد خود را وارد کنید", "Feedback": "فعال‌سازی & راه‌اندازی باز‌خورد", "Click here to Show it in Map": "برای مشاهده روی نقشه اینجا را کلیک کنید", "Canceled": "مطمئن باش اينطور نميشه", "Type your Email": "ايميل تو رو چک ميکنم", "No I want": "من از اونا نيستم", "Email is": "پست الکترونیکی", "Phone Number is": "شماره تلفن", "Date of Birth is": "- تاريخ تولد", "Sex is": "جنسیت است", "Car Details": "جزئیات خودرو", "VIN is": "رونوشت skeleton", "Color is": "رنگ است", "Make is": "ساخته شده است", "Model is": "مدل از:", "Year is": "دنار", "Edit Your data": "داده های خود را ویرایش کنید", "write vin for your car": "شماره شاسی ماشین خود را وارد کنید", "VIN": "داريم شماره بدنه ماشينشون رو رديابي ميکنيم", "write Color for your car": "رنگ ماشین خود را وارد کنید", "write Make for your car": "مدل ماشین خود را بنویسید", "write Model for your car": "مدل ماشین خود را وارد کنید", "write Year for your car": "سال ماشین خود را وارد کنید", "write Expiration Date for your car": "تاریخ انقضای وسیله نقلیه خود را وارد کنید", "Tariffs": "تعاریف", "Minimum fare": "حاشیه‌ها:", "Maximum fare": "براورد کردن , تقويم کردن , قيمت کردن , مطلع کردن , اگاهي دادن", "Flag-down fee": "هزینه های خرابی", "Including Tax": "از جمله مالیات", "BookingFee": "زندان؟ چطور فکر...", "Morning": "صبح بخير.", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "از ساعت 07:30 تا 10:30 (پنجشنبه، جمعه، شنبه، دوشنبه)", "Evening": "غروب , سرشب , شب هنگام , شبانگاه", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "از ساعت 12:00 الی 15:00 (پنجشنبه، جمعه، شنبه، دوشنبه)", "Night": "شب بخير.", "You have in account": "تو اکانت داری", "Select Country": "کشور را انتخاب کنید", "Ride Today :": "درخواست انطلق امروز:", "After this period": "اون ميگذره", "You can't cancel!": "نمیتونی", "from 23:59 till 05:30": "از ساعت 23:59 تا 05:30", "Rate Driver": "راننده...\"راس وبر\"...", "Total Cost is": "کل هزینه است", "Write note": "-يه يادداشت !", "Time to arrive": "زمان مورد انتظار ورود", "Ride Summaries": "خلاصه انطلق", "Total Cost": "هزینه کل", "Average of Hours of": "ساعتهای کاری", "is ON for this month": "در حال اجرا برای این ماه", "Days": "روز", "Total Hours on month": "تعداد کل ساعت در ماه", "Counts of Hours on days": "تعداد ساعات یک روز", "OrderId": "بسه ديگه.", "created time": "ایجادشده", "Intaleq Over": "پاکو", "I will slow down": "من سرعتم را کم می کنم", "Map Passenger": "نقشه مسافر", "Be Slowly": "آهسته برو", "If you want to make Google Map App run directly when you apply order": "اگر می خواهید برنامه Google Maps را مستقیماً هنگام اعمال فرمان راه اندازی کنید", "You can change the language of the app": "می توانید زبان برنامه را تغییر دهید", "Your Budget less than needed": "بودجه شما کمتر از مقدار مورد نیاز است", "You can change the Country to get all features": "می توانید کشور را برای دریافت همه ویژگی ها تغییر دهید", "Change Country": "کشور را تغییر دهید" }, "zh": { "Order": "订单", "OrderVIP": "VIP订单", "Cancel Trip": "取消行程", "Passenger Cancel Trip": "乘客取消行程", "VIP Order": "VIP订单", "The driver accepted your trip": "司机接受了您的行程", "message From passenger": "来自乘客的消息", "Cancel": "取消", "Trip Cancelled. The cost of the trip will be added to your wallet.": "行程已取消。行程费用将添加到您的钱包。", "token change": "令牌更改", "face detect": "面部检测", "Face Detection Result": "面部检测结果", "similar": "相似", "not similar": "不相似", "Hi ,I will go now": "嗨,我现在就去", "Passenger come to you": "乘客正在向您走来", "Call Income": "来电", "Call Income from Passenger": "来自乘客的来电", "Criminal Document Required": "需要犯罪文件", "You should have upload it .": "您应该上传它。", "Call End": "通话结束", "The order has been accepted by another driver.": "订单已被另一位司机接受。", "The order Accepted by another Driver": "订单已被另一位司机接受", "We regret to inform you that another driver has accepted this order.": "我们很遗憾地通知您,另一位司机已接受此订单。", "Driver Applied the Ride for You": "司机为您申请了行程", "Applied": "已应用", "Hi ,I Arrive your site": "嗨,我到达您的位置了", "Please go to Car Driver": "请到汽车司机处", "Ok I will go now.": "好的,我现在就去。", "Accepted Ride": "接受行程", "Driver Accepted the Ride for You": "司机为您接受了行程", "Promo": "促销", "Show latest promo": "显示最新促销", "Trip Monitoring": "行程监控", "Driver Is Going To Passenger": "司机正在前往乘客处", "Please stay on the picked point.": "请留在选定的上车点。", "message From Driver": "来自司机的消息", "Trip is Begin": "行程开始", "Cancel Trip from driver": "司机取消行程", "We will look for a new driver.\nPlease wait.": "我们将寻找新的司机。\n请稍候。", "The driver canceled your ride.": "司机取消了您的行程。", "Driver Finish Trip": "司机完成行程", "you will pay to Driver": "您将支付给司机", "Don’t forget your personal belongings.": "不要忘记您的个人物品。", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "请确保您带好所有个人物品,并在离开前将任何剩余费用(如果适用)添加到您的钱包中。感谢您选择Intaleq应用程序", "Finish Monitor": "结束监控", "Trip finished": "行程已完成", "Call Income from Driver": "来自司机的来电", "Driver Cancelled Your Trip": "司机取消了您的行程", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "您将支付给司机,您将支付司机的时间成本,请查看您的Intaleq钱包", "Order Applied": "订单已应用", //firebase "registration_date": "SignUpDate", "expiration_date": "結束日期", "rating_count": "評論數量", "rating_driver": "職業駕駛評分", "age": "年齡", "vin": "車輛識別號碼", "car_color": "顏色", "car_plate": "車牌號碼", "car_model": "汽車型號:", "education": "教育", "gender": "性別", "birthdate": "出生日期", "Approve Driver Documents": "核準職業駕駛文件", "Total Budget is": "總預算", "You will recieve code in sms message": "你會透過短訊收到驗證碼", "Please enter": "請輸入", "We need your phone number to contact you and to help you receive orders.": "我們需要你的電話號碼聯絡你,並協助你接收訂單。", "The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.": "犯罪紀錄上的全名與駕駛執照上的姓名不符。請檢查並提供正確的文件。", "The national number on your driver’s license does not match the one on your ID document. Please verify and provide the correct documents.": "駕駛執照上的國民登記號碼與身分證件上的號碼不符。請檢查並提供正確的文件。", "Capture an Image of Your Criminal Record": "拍攝犯罪紀錄的相片", "IssueDate": "簽發日期", "Capture an Image of Your car license front": "從正面拍攝你的汽車駕駛執照", "Capture an Image of Your ID Document front": "從正面拍攝身分證件相片", "NationalID": "國民登記號碼", "FullName": "全名", "InspectionResult": "檢查結果", "Criminal Record": "犯罪紀錄", "The email or phone number is already registered.": "電郵或電話號碼已登記。", "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.": "若要透過Uber Travel App成為共乘職業駕駛,您需要上傳駕駛執照、身分證明文件和車輛登記文件。我們的人工智能系統將在2-3分鐘內立即審查並驗證其真實性。文件通過審核後,你便可透過Uber Travel App成為司機夥伴。請注意,提供偽造文件是嚴重違法行為,可能會導致立即終止和法律後果。", "Documents check": "文件驗證", "Driver's License": "駕駛執照", "License Type": "授權類型", "National Number": "國民身分證號碼:", "Name (Arabic)": "姓名(阿拉伯文)", "Name (English)": "英語", "Address": "標題", "Issue Date": "簽發日期", "Expiry Date": "到期日期", "License Categories": "許可證類別", "driver_license": "駕駛執照", "Capture an Image of Your Driver License": "請拍攝駕駛執照的相片", "ID Documents Back": "身分證件外觀", "National ID": "國民身分證", "Occupation": "職業", "Gender": "性別", "Religion": "宗教", "Marital Status": "婚姻狀況", "Full Name (Marital)": "全名(配偶)", "Expiration Date": "結束日期", "Capture an Image of Your ID Document Back": "拍攝身份證明文件背面的相片", "ID Documents Front": "身分證件正面", "First Name": "名字", "CardID": "拍攝身份證明文件背面的相片", "Full Name": "全名", "Vehicle Details Front": "正面車輛詳細資訊", "Plate Number": "車牌號碼", "Owner Name": "所有者姓名", "Vehicle Details Back": "再次提供車輛詳細資訊", "Make": "制作", "Model": "汽車型號:", "Year": "年", "Chassis": "機箱", "Color": "顏色", "Displacement": "替代", "Fuel": "燃料", "Tax Expiry Date": "到期日期", "Inspection Date": "考核日期", "Capture an Image of Your car license back": "請再次拍攝車輛執照的相片", "Capture an Image of Your Driver’s License": "請拍攝駕駛執照的相片", "Sign in with Google for easier email and name entry": "使用Google登入,輕鬆輸入電子郵件和姓名", "You will choose allow all the time to be ready receive orders": "您可以選擇隨時接受現成訂單", "Welcome to Intaleq!": "歡迎來到Safar !", "Get to your destination quickly and easily.": "輕鬆快捷地前往目的地。", "Enjoy a safe and comfortable ride.": "享受安全舒適的行程。", "Choose Language": "選擇語言", "Login": "登錄", "Pay with Wallet": "使用銀包付款", "Invalid MPIN": "MPIN代碼無效", "Invalid OTP": "無效的驗證碼", "Enter your email address": "輸入您的電子郵件地址", "Please enter Your Email.": "請輸入...", "Enter your phone number": "輸入你的電話號碼", "Please enter your phone number.": "請輸入您的電話號碼。", "Please enter Your Password.": "輸入您的密碼", "Submit": "提交", "if you dont have account": "如果你沒有帳戶", "Register": "馬德羅", "Accept Ride's Terms & Review Privacy Notice": "接受行程條款並查看隱私權聲明", "By selecting 'I Agree' below, I have reviewed and agree to the Terms of Use and acknowledge the Privacy Notice. I am at least 18 years of age.": "在下方選擇「我同意」,即表示我已閱讀並同意使用條款,並確認隱私權聲明。我已年滿18歲。", "I Agree": "同意", "First name": "名字", "Enter your first name": "輸入您的名字", "Please enter your first name.": "請輸入您的姓名。", "Last name": "姓氏", "Enter your last name": "輸入姓氏", "Please enter your last name.": "請輸入您的姓名。", "City": "城市", "Please enter your City.": "請輸入...", "Male": "男性", "Female": "女", "Verify Email": "驗證電子郵件", "We sent 5 digit to your Email provided": "我們已將5位數傳送至你提供的電郵", "5 digit": "PIN碼( 5位數)", "Send Verification Code": "驗證碼", "Your Ride Duration is": "你的行程時間為", "You will be thier in": "你會把它們放進去", "You trip distance is": "你的行程距離為", "Fee is": "費用為", "To :": "Suoi To", "Add Promo": "新增優惠", "Confirm Selection": "確認選擇", "distance is": "距離為", "duration is": "持續時間為", "I don't need a ride anymore": "我不再需要接載服務", "I was just trying the application": "我只是想試試App", "No driver accepted my request": "沒有職業駕駛接受我的訂單", "I added the wrong pick-up/drop-off location": "你新增的上下車地點有誤", "I don't have a reason": "我沒有理由", "Other": "其他 ", "Can we know why you want to cancel Ride ?": "請問您想取消行程的原因為何?", "Cancel Ride": "取消!", "Add Payment Method": "新增付款方式", "Your Wallet balance is": "您的錢包餘額為", "Ride Wallet": "行程錢包", "Payment Method": "付款方式", "Type here Place": "在此輸入地點", "Are You sure to ride to": "您確定要搭乘前往", "Confirm": "確認", "Back": "返回", "You are Delete": "您正在刪除", "Deleted": "已刪除", "You Dont Have Any places yet !": "您還沒有任何名額!", "Favorite Places": "最愛的好去處", "From : Current Location": "當前位置:", "Where to": "在哪裡?", "Notifications": "通知", "Profile": "個人資料", "Home": "首頁", "My Cared": "MyCurt", "Add Card": "新增卡片", "Add Credit Card": "新增信用卡", "Please enter the cardholder name": "請輸入持卡人姓名", "Please enter the expiry date": "請輸入到期日", "Please enter the CVV code": "請輸入卡片驗證碼", "Go To Favorite Places": "前往「最愛好去處」", "Go to this Target": "前往此目標", "My Profile": "個人資料", "Sign Out": "退出", "Home Page": "首頁", "Are you want to go to this site": "是否要前往此地點", "MyLocation": "我的位置", "my location": "我的位置", "Target": "目的", "Update": "更新", "You Should choose rate figure": "您必須選擇正確的號碼", "Login Captin": "登入隊長", "Register Captin": "隊長登記", "Send Verfication Code": "發送驗證碼", "End Ride": "搭乘", "Minute": "分", "Go to passenger Location now": "立即前往乘客所在地點", "Duration of the Ride is": "行程時間為", "Distance of the Ride is": "行程距離為", "Name of the Passenger is": "乘客的姓名是", "Hello this is Captain": "你好,我是隊長", "Start the Ride": "開始行程", "Please Wait If passenger want To Cancel!": "如果乘客想取消行程,請稍候!", "Total Duration:": "總持續時間:", "Active Duration:": "作用中步驟持續時間", "Waiting for Captin ...": "正在等候艦長…", "Age is": "年齡為", "Rating is": "評分為", "to arrive you.": "與您聯絡。", "Order History": "記錄訂單紀錄", "My Wallet": "我的錢包", "Tariff": "費率", "Settings": "設定", "Feed Back": "意見回饋", "Promos": "額外獎勵", "Please enter a valid 16-digit card number": "請輸入有效的訂單編號。", "Add Phone": "致電", "Please enter a phone number": "請輸入電話號碼", "You dont Add Emergency Phone Yet!": "你尚未新增緊急電話!", "You will arrive to your destination after": "你將於之後抵達目的地", "You can cancel Ride now": "你現在可以取消行程", "You Can cancel Ride After Captain did not come in the time": "船長未及時抵達後,您可以取消行程", "If you in Car Now. Press Start The Ride": "如果你現在在車上輕點「開始行程」", "You Dont Have Any amount in": "您在沒有任何金額", "Wallet!": "錢包!", "You Have": "您有", "Save Credit Card": "保留信用卡", "Show Promos": "查看優惠", "10 and get 4% discount": "10即享4%折扣", "20 and get 6% discount": "20即享6%折扣", "40 and get 8% discount": "40即享8%折扣", "100 and get 11% discount": "100%折扣11%", "Pay with Your PayPal": "使用PayPal付款", "You will choose one of above !": "你將選擇上面的其中一個選項!", "Cancel": "取消", "Delete My Account": "刪除我的帳戶", "Edit Profile": "編輯個人資料", "Name": "名稱字體", "Update Gender": "更新性別", "Education": "教育", "Update Education": "更新教育背景", "Employment Type": "工作類型", "SOS Phone": "SOS電話", "High School Diploma": "高中文憑", "Associate Degree": "聯合文憑學位", "Bachelor's Degree": "學士學位", "Master's Degree": "碩士學位", "Doctoral Degree": "博士學位", "Promos For today": "本日優惠", "Copy this Promo to use it in your Ride!": "複製此優惠,以便在行程中使用!", "To change some Settings": "若要變更部分設定", "To change Language the App": "變更App語言的步驟", "Order Request Page": "訂單申請頁面", "Rouats of Trip": "拉瓦特之旅", "Passenger Name is": "乘客姓名", "Total From Passenger is": "乘客支付的總金額為", "Duration To Passenger is": "距離乘客的持續時間", "Distance To Passenger is": "與乘客的距離為", "Total For You is": "你的總金額為", "Distance is": "距離", "KM": "公裏", "Duration of Trip is": "行程時間為", "Minutes": "分", "Apply Order": "套用訂單", "Refuse Order": "拒絕申請", "Rate Captain": "隊長評分", "Enter your Note": "輸入備註", "Type something...": "寫點東西...", "Submit rating": "提供評估", "Rate Passenger": "乘客評分", "Ride Summary": "旅程摘要", "welcome_message": "歡迎訊息", "app_description": "ApplicationDescription", "get_to_destination": "抵達目的地", "get_a_ride": "預約行程", "safe_and_comfortable": "安全舒適", "committed_to_safety": "致力保障安全", "Driver Applied the Ride for You": "代您完成行程的職業駕駛", "Show latest promo": "顯示最新優惠", "Cancel Trip": "取消行程", "Passenger Cancel Trip": "乘客取消行程", "Please stay on the picked point.": "請停留在所選地點。", "Trip is Begin": "旅程開始", "Hi ,I will go now": "嗨,我現在就去", "Passenger come to you": "乘客即將抵達", "Hi ,I Arrive your site": ",您好:您已抵達所在地點。", "Driver Finish Trip": "職業駕駛行程結束", "you will pay to Driver": "您將向職業駕駛付款", "Driver Cancel Your Trip": "司機夥伴,請取消行程。", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "您將向職業駕駛支付您將支付職業駕駛花費的時間看看您的Intaleq錢包", "I will go now": "我現在就去。", "You Have Tips": "你有貼士", "tips": "貼士", "Total is": "總金額為", "No,I want": "不,我想要", "Your fee is": "您的費用為", "Do you want to pay Tips for this Driver": "您想給這位職業駕駛小費嗎?", "Tip is": "我的貼士", "Camera Access Denied.": "相機存取被拒。", "Open Settings": "開啟設定", "GPS Required Allow !.": "需要啟用GPS !", "Your Account is Deleted": "您的帳戶已刪除", "Are you sure to delete your account?": "您確定要刪除您的帳戶嗎?", "Your data will be erased after 2 weeks": "您的資料將在2週後刪除", "And you will can't return to use app after 1 month": "你將可在一個月後返回App", "Enter Your First Name": "輸入您的名字", "Are you Sure to LogOut?": "您確定要登出嗎?", "Email Wrong": "電子郵件", "Email you inserted is Wrong.": "您輸入的電子郵件地址有誤。", "You have finished all times": "你已經完成了所有的時間", "if you want help you can email us here": "如果您需要幫助,請發送電子郵件至此處", "Thanks": "謝謝", "Email Us": "發送電子郵件給我們", "I cant register in your app in face detection": "我無法透過臉部偵測功能註冊你的應用程式", "Hi": "ni hao", "No face detected": "未偵測到臉部", "Image detecting result is": "影像偵測的結果是", "from 3 times Take Attention": "超過3次引起你的注意", "Be sure for take accurate images please": "請務必拍攝準確的相片", "You have": "您有", "image verified": "相片已公證", "Next": "下一步", "There is no help Question here": "這裡沒有幫助問題", "Call End": "結束通話", "You dont have Points": "您沒有積分", "You Are Stopped For this Day !": "您今天已被暫停!", "You must be charge your Account": "您必須為您的帳戶充值", "You Refused 3 Rides this Day that is the reason": "你今天拒絕了3個行程,因此", "See you Tomorrow!": "明天見!", "Recharge my Account": "向我的帳戶充值", "Ok , See you Tomorrow": "好吧,明天見。", "You are Stopped": "你已停止接單", "Connected": "已連線", "Not Connected": "離線", "Your are far from passenger location": "您距離乘客所在地點很遠", "go to your passenger location before": "請在前前往乘客所在地點", "Passenger cancel trip": "乘客已取消行程", "You will get cost of your work for this trip": "你將獲得這趟旅程的費用", "in your wallet": "在您的錢包中", "you gain": "您賺取了", "Order Cancelled": "訂單已取消", "Order Cancelled by Passenger": "乘客已取消預約", "Success": "成功", "Feedback data saved successfully": "已成功儲存評鑑資料", "No Promo for today .": "今天沒有優惠。", "Select your destination": "選擇目的地", "Search for your Start point": "尋找出發點", "Search for waypoint": "搜尋WIPOINT點", "Current Location": "當前位置", "Add Location 1": "添加位置1", "You must Verify email !.": "必須驗證電子郵件!", "Cropper": "收割", "Saved Sucssefully": "儲存成功", "Select Date": "選擇日期", "Birth Date": "出生日期", "Ok": "也已无大碍", "the 500 points equal 30 JOD": "500分等於30 JOD", "the 500 points equal 30 JOD for you": "500積分等於30 JOD", "token updated": "代碼已更新", "Add Location 2": "添加位置2", "Add Location 3": "新增地點3", "Add Location 4": "新增地點4", "Waiting for your location": "正在等候你的地點", "Search for your destination": "尋找目的地", "Hi! This is": "您好!那個酷", "I am using": "我使用", "to ride with": "提供搭乘服務", "as the driver.": "成為職業駕駛。", "is driving a": "上線開車", "with license plate": "有車牌號碼", "I am currently located at": "我目前在", "Please go to Car now": "請立即上車", "If you need to reach me, please contact the driver directly at": "如需聯絡我,請直接聯絡職業駕駛:", "No Car or Driver Found in your area.": "您所在地區沒有找到車輛或職業駕駛。", "Please Try anther time": "請再試一次", "There no Driver Aplly your order sorry for that": "很抱歉,沒有職業駕駛能夠滿足您的要求。", "Trip Cancelled": "行程已取消", "The Driver Will be in your location soon .": "職業駕駛即將抵達您的所在地點。", "The distance less than 500 meter.": "距離不到500米。", "Promo End !": "表演結束了!", "There is no notification yet": "尚無通知", "Use Touch ID or Face ID to confirm payment": "使用Touch ID或Face ID確認付款", "Contact us for any questions on your order.": "如對訂單有任何疑問,請聯絡我們。", "Pyament Cancelled .": "付款已取消。", "type here": "在此輸入", "Scan Driver License": "駕駛執照檢查", "Please put your licence in these border": "請將執照放置在這些範圍內", "Camera not initialized yet": "相機尚未設定", "Take Image": "拍攝相片", "AI Page": "AI頁面", "Take Picture Of ID Card": "請拍攝身份證明文件的相片", "Take Picture Of Driver License Card": "請拍攝駕駛執照的相片。", "We are process picture please wait": "我們正在處理圖片,請稍候。", "There is no data yet.": "尚無數據。", "Name :": "名稱字體", "Drivers License Class:": "駕照類別:", "Document Number:": "文件編號:", "Address:": "標題", "Height:": "長度:", "Expiry Date:": "到期日期:", "Date of Birth:": "出生日期:", "You can't continue with us .": "您無法繼續使用我們的服務。", "You should renew Driver license": "你必須更新駕駛執照", "Detect Your Face": "發現你的臉孔", "Go to next step": "前往下一步", "scan Car License.": "車輛牌照審查。", "Name in arabic": "姓名(阿拉伯文)", "Drivers License Class": "駕照類別", "Date of Birth": "出生日期", "Age": "年齡", "Lets check Car license": "請檢查車牌號碼", "Car Kind": "車輛類型", "Car Plate": "車牌號碼", "Lets check License Back Face": "請檢查背面執照", "Car License Card": "車輛牌照", "No image selected yet": "尚未選擇相片", "Made :": "製作儀式", "model :": "型號:", "VIN :": "底盤編號:", "year :": "年份:", "ُExpire Date": "結束日期", "Login Driver": "職業駕駛登入", "Password must br at least 6 character.": "密碼必須至少為6個字元。", "if you don't have account": "如果你沒有帳戶", "Here recorded trips audio": "以下是行程錄音", "Register as Driver": "註冊成為職業駕駛", "Privacy Notice": "隱私權聲明", "By selecting \"I Agree\" below, I have reviewed and agree to the Terms of Use and acknowledge the": "在下方選擇「我同意」,即表示我已查看、同意並確認條款與細則", ". I am at least 18 years of age.": ". 我已年滿18歲。", "Log Out Page": "結帳頁面", "Log Off": "退出", "Register Driver": "職業駕駛紀錄", "Verify Email For Driver": "查看職業駕駛的電子郵件地址", "Admin DashBoard": "管理員儀表板", "Your name": "您的姓名", "your ride is applied": "已套用你的行程", "Your password": "您的密碼", "LE": "埃及鎊", "JOD": "約旦第納爾", "m": "陳", "We search nearst Driver to you": "我們正在尋找距離您最近的職業駕駛", "please wait till driver accept your order": "請等候職業駕駛接受您的預約", "No accepted orders? Try raising your trip fee to attract riders.": "沒有已接受的訂單?請嘗試提高行程費用,以吸引乘客。", "You should select one": "您必須選擇一項", "The driver accept your order for": "職業駕駛已接受您的預約", "Increase Fee": "增加費用", "No, thanks": "不用了,謝謝", "The driver on your way": "職業駕駛正在途中", "Total price from": "總價最低", "Order Details Intaleq": "Intaleq訂單詳細資訊", "Order Applied": "訂單已套用", "accepted your order": "您的申請已被接受", "We regret to inform you that another driver has accepted this order.": "很抱歉通知您,其他職業駕駛已接受此預約。", "Selected file:": "所選檔案:", "Your trip cost is": "行程費用", "this will delete all files from your device": "這將刪除您裝置上的所有檔案", "you have a negative balance of": "您的餘額為負數", "in your": "VIC", "Exclusive offers and discounts always with the Intaleq app": "隨時透過旅遊應用程式享受專屬優惠和折扣", "Please go to Car Driver": "請前往車輛的職業駕駛處", "wallet due to a previous trip.": "因上一趟行程而產生的錢包。", "Submit Question": "提交問題", "Please enter your Question.": "請輸入您的問題。", "Help Details": "幫助詳情", "No trip yet found": "尚未找到行程", "No Response yet.": "還沒有回復。", "You Earn today is": "您今天的收入是", "You Have in": "您有", "Total points is": "總分為", "Total Connection Duration:": "總連線持續時間:", "H and": "H和", "Passenger name :": "乘客姓名:", "Cost Of Trip IS": "行程費用為", "Arrival time": "抵達時間", "arrival time to reach your point": "抵達目的地的時間", "For Intaleq and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance": "對於快速行程和外送行程,價格會自動計算。為了提供舒適的行程體驗,行程費用會根據行程時間和距離而定。", "Hello this is Driver": ",您好:我是職業駕駛", "Is the Passenger in your Car ?": "乘客是否在您的車內?", "Please wait for the passenger to enter the car before starting the trip.": "請等候乘客上車後再開始行程。", "No ,still Waiting.": "不,我還在等你。", "I arrive you": "我抓住你了", "I Arrive your site": "我抓住你了", "You are not in near to passenger location": "您不在乘客所在地點附近", "please go to picker location exactly": "請前往所選項目的確切位置", "You Can Cancel Trip And get Cost of Trip From": "您可以取消行程,並透過獲得行程費用", "Are you sure to cancel?": "您確定要取消嗎?", "Yes": "是", "Insert Emergincy Number": "輸入緊急電話號碼", "Best choice for comfort car and flexible route and stops point": "舒適的車輛、靈活的路線和停車點的最佳選擇", "Insert": "插入", "This is for delivery or a motorcycle.": "適用於送遞或電單車。", "This trip goes directly from your starting point to your destination for a fixed price. The driver must follow the planned route": "這趟行程會直接從您的出發地點前往目的地,費用為均一價。職業駕駛必須按照規劃路線行駛", "You can decline a request without any cost": "你可以免費拒絕申請", "Perfect for adventure seekers who want to experience something new and exciting": "非常適合想嘗試新奇刺激體驗的探險者", "My current location is:": "我目前的位置是:", "and I have a trip on": "我在有趟行程", "App with Passenger": "向乘客提出申請", "You will be pay the cost to driver or we will get it from you on next trip": "費用會支付給職業駕駛,否則我們會在下趟行程中向您收取", "Trip has Steps": "此行程有個步驟", "Distance from Passenger to destination is": "乘客與目的地的距離為", "price is": "價格為", "This ride type does not allow changes to the destination or additional stops": "此行程類型不允許變更目的地或其他停靠點", "This price may be changed": "此價格可能會有變動", "No SIM card, no problem! Call your driver directly through our app. We use advanced technology to ensure your privacy.": "沒有SIM卡,沒問題!請直接透過App聯絡職業駕駛。我們使用先進技術來確保您的隱私。", "This ride type allows changes, but the price may increase": "此旅程類型允許變更,但價格可能會上漲", "message From passenger": "來自乘客的訊息", "Select one message": "選擇一則訊息", "My location is correct. You can search for me using the navigation app": "我的位置正確。你可以使用導航應用程式搜尋我", "I'm waiting for you": "我在等你", "Hello, I'm at the agreed-upon location": ",您好:我在約定的地點", "We noticed the Intaleq is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button.": "我們注意到車速超過每小時100公裏。為了您的安全,請放慢速度。如果你感到不安全,可以與聯絡人分享行程詳細資料,或使用紅色遇險按鈕致電警方。", "Warning: Intaleqing detected!": "警告:偵測到超速!", "Please help! Contact me as soon as possible.": "請幫幫我!請盡快與我聯絡。", "Share Trip Details": "提供行程詳細資訊", "Car Plate is": "車牌號碼", "the 3000 points equal 3000 L.E for you": "3000分等於3000 EGP", "So go and gain your money": "開始賺取收入", "the 3000 points equal 3000 L.E": "3000分等於3000 EGP", "The payment was not approved. Please try again.": "付款未批準。請再試一次。", "Payment Failed": "付款失敗", "Error": "錯誤", "An error occurred during the payment process.": "您的付款發生錯誤。", "The payment was approved.": "付款已批準。", "Payment Successful": "付款成功", "No ride found yet": "尚未找到行程", "Accept Order": "接受預約", "reject your order.": "拒絕你的申請。", "Bottom Bar Example": "底部欄範例", "Driver phone": "職業駕駛電話", "Statistics": "統計資料", "Origin": "資產", "Destination": "目的地", "Driver Name": "職業駕駛姓名", "Driver Car Plate": "駕駛車牌號碼", "Available for rides": "可供預約行程", "Scan Id": "身分驗證", "Camera not initilaized yet": "相機尚未設定", "Scan ID MklGoogle": "MklGoogle身分檢查", "Language": "語言", "Jordan": "約旦", "USA": "美國", "Egypt": "埃及", "Turkey": "土耳其", "Saudi Arabia": "沙特阿拉伯", "Qatar": "卡塔爾", "Bahrain": "巴林", "Kuwait": "科威特", "But you have a negative salary of": "但你的負薪水是", "Promo Code": "優惠碼", "Your trip distance is": "你的行程距離為", "Enter promo code": "輸入優惠序號", "You have promo!": "你有晉升機會!", "Cost Duration": "費用持續時間", "Duration is": "持續時間為", "Leave": "離開", "Join": "加入", "You Should be select reason.": "您必須選擇一個原因。", "\$": "\$", "Waiting for Driver ...": "正在等候職業駕駛…", "Latest Recent Trip": "最新行程", "from your list": "從你的心水清單中", "Do you want to change Work location": "您想變更工作地點嗎?", "Do you want to change Home location": "您是否要更改房源的位置", "We Are Sorry That we dont have cars in your Location!": "很抱歉,你所在地區無法提供車輛服務!", "Choose from Map": "從地圖中選擇", "Pick your ride location on the map - Tap to confirm": "在地圖上選擇上車地點,點按即可確認", "To Work": "商務差旅", "Are you want to go this site": "是否要前往此地點", "Closest & Cheapest": "距離最近、價格最便宜", "Work Saved": "已儲存:", "Intaleq is the ride-hailing app that is safe, reliable, and accessible.": "Intaleq是一款安全、可靠且易於使用的叫車App。", "With Intaleq, you can get a ride to your destination in minutes.": "透過行程,你可以在幾分鐘內預約行程前往目的地。", "Intaleq is committed to safety, and all of our captains are carefully screened and background checked.": "Safar致力於安全,我們所有的指揮官都經過仔細審查和背景調查。", "To Home": "前往首頁", "Home Saved": "已儲存:", "Destination selected": "已選取目的地", "Now select start pick": "現在選擇「開始選擇」", "Pick from map": "從地圖中選擇", "Click here point": "點擊此處", "No Car in your site. Sorry!": "你所在地區沒有車輛。糟糕!", "Nearest Car for you about": "距離您最近的車輛大約", "N/A": "無信息", "From :": "寄件人:", "Get Details of Trip": "取得旅程詳情", "If you want add stop click here": "如果你想新增停車點,請按一下此處", "Driver": "職業駕駛", "Where you want go": "你想去哪裡?", "My Card": "我的信用卡", "Start Record": "開始錄制", "Wallet": "錢包", "History of Trip": "行程日期", "Helping Center": "說明中心", "Record saved": "記錄已儲存", "Trips recorded": "已記錄的行程", "Select Your Country": "選擇你的國家/地區", "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country.": "為確保您有最準確的位置資訊,請在下方選擇您的國家/地區。這將有助於為您的國家/地區自訂應用程式體驗和內容。", "Are you sure to delete recorded files": "您確定要刪除記錄的檔案嗎", "Select recorded trip": "選擇記錄的行程", "Card Number": "卡號", "Hi, Where to": "您好,想去哪裡?", "Pick your destination from Map": "從地圖上選擇目的地", "Add Stops": "新增停靠點", "Get Direction": "取得路線", "Add Location": "新增地點", "Switch Rider": "切換乘客", "You will arrive to your destination after timer end.": "您會在計時器結束後抵達目的地。", "You can cancel trip": "你可以取消行程", "The driver waitting you in picked location .": "職業駕駛正在指定地點等您。", "Pay with Your": "付款方式:", "Pay with Credit Card": "使用信用卡付款", "Payment History": "付款紀錄", "Show Promos to Charge": "顯示運送優惠", "Point": "一個點", "Driver Balance": "職業駕駛錢包", "Total Points is": "總分為", "Total Budget from trips is": "行程總預算為", "Total Amount:": "總金額:", "Total Budget from trips by": "的總預算行程費用", "Credit card is": "信用卡", "This amount for all trip I get from Passengers": "此金額適用於我收到的所有乘客行程", "Pay from my budget": "從我的預算中支付", "This amount for all trip I get from Passengers and Collected For me in": "此金額適用於我從乘客收取的所有行程", "You can buy points from your budget": "您可以從預算中購買積分", "insert amount": "輸入金額", "You can buy Points to let you online": "您可以購買積分,以便線上存取", "by this list below": "透過以下清單", "Create Wallet to receive your money": "建立錢包以收取款項", "Enter your feedback here": "在此輸入您的意見回饋", "Please enter your feedback.": "請輸入備註文字", "Feedback": "意見回饋", "Click here to Show it in Map": "按一下此處即可在地圖上查看", "Canceled": "已取消", "Type your Email": "輸入你的電郵", "No I want": "不,我想要", "Email is": "電子郵件", "Phone Number is": "電話號碼為", "Date of Birth is": "出生日期為", "Sex is": "性別為", "Car Details": "車輛詳情", "VIN is": "底盤編號", "Color is": "顏色是", "Make is": "Make is", "Model is": "表單來源:", "Year is": "年", "Edit Your data": "編輯您的詳細資訊", "write vin for your car": "寫下車輛的底盤號碼", "VIN": "底盤編號", "write Color for your car": "輸入車輛顏色", "write Make for your car": "為你的車輛撰寫廠牌", "write Model for your car": "輸入您的汽車型號", "write Year for your car": "輸入車輛年份", "write Expiration Date for your car": "輸入車輛的有效期限", "Tariffs": "定義", "Minimum fare": "最低行程費用", "Maximum fare": "最高價格", "Flag-down fee": "中途停留費用", "Including Tax": "含稅", "BookingFee": "預訂費", "Morning": "上午", "from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)": "07:30 - 10:30 (周四、周五、周六、周一)", "Evening": "晚上", "from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)": "12:00 - 15:00 (周四、周五、周六、周一)", "Night": "晚", "You have in account": "您在帳戶中有", "Select Country": "選擇國家/地區", "Ride Today :": "立即預約行程:", "After this period": "在此期間之後", "You can't cancel!": "你不能取消!", "from 23:59 till 05:30": "23:59 - 05:30", "Rate Driver": "職業駕駛價值觀", "Total Cost is": "總費用為", "Write note": "撰寫備註", "Time to arrive": "預計抵達時間", "Ride Summaries": "旅程摘要", "Total Cost": "總費用", "Average of Hours of": "平均工作時數", "is ON for this month": "本月運行", "Days": "天", "Total Hours on month": "每月總時數", "Counts of Hours on days": "小時(天)", "OrderId": "訂單編號", "created time": "建立時間", "Intaleq Over": "速度高於", "I will slow down": "我會慢下來。", "Map Passenger": "乘客地圖", "Be Slowly": "慢一點", "If you want to make Google Map App run directly when you apply order": "如果您想在應用命令時直接啟動Google地圖", "You can change the language of the app": "您可以變更App的語言", "Your Budget less than needed": "您的預算不足", "You can change the Country to get all features": "您可以更改國家/地區以獲得所有功能", "Change Country": "非國家" }, "ar-gulf": { "Order": "طلب", "OrderVIP": "طلب VIP", "Cancel Trip": "إلغاء الرحلة", "Passenger Cancel Trip": "الراكب ألغى الرحلة", "VIP Order": "طلب VIP", "The driver accepted your trip": "السائق قبل رحلتك", "message From passenger": "رسالة من الراكب", "Cancel": "إلغاء", "Trip Cancelled. The cost of the trip will be added to your wallet.": "تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.", "token change": "تغيير الرمز", "face detect": "كشف الوجه", "Face Detection Result": "نتيجة كشف الوجه", "similar": "مشابه", "not similar": "غير مشابه", "Hi ,I will go now": "هلا، أنا بروح الحين", "Passenger come to you": "الراكب جاي لك", "Call Income": "مكالمة واردة", "Call Income from Passenger": "مكالمة واردة من الراكب", "Criminal Document Required": "مطلوب وثيقة جنائية", "You should have upload it .": "لازم تكون حملتها.", "Call End": "انتهاء المكالمة", "The order has been accepted by another driver.": "الطلب تم قبوله من سائق ثاني.", "The order Accepted by another Driver": "الطلب تم قبوله من سائق ثاني", "We regret to inform you that another driver has accepted this order.": "نتأسف لإبلاغك أن سائق آخر قد قبل هذا الطلب.", "Driver Applied the Ride for You": "السائق قدم طلب الرحلة لك", "Applied": "تم التقديم", "Hi ,I Arrive your site": "هلا، وصلت موقعك", "Please go to Car Driver": "لو سمحت روح حق سائق السيارة", "Ok I will go now.": "اوكي بروح الحين.", "Accepted Ride": "تم قبول الرحلة", "Driver Accepted the Ride for You": "السائق قبل الرحلة لك", "Promo": "عرض", "Show latest promo": "عرض أحدث عرض", "Trip Monitoring": "مراقبة الرحلة", "Driver Is Going To Passenger": "السائق في طريقه حق الراكب", "Please stay on the picked point.": "لو سمحت خليك في نقطة الالتقاط المحددة.", "message From Driver": "رسالة من السائق", "Trip is Begin": "الرحلة بدت", "Cancel Trip from driver": "إلغاء الرحلة من السائق", "We will look for a new driver.\nPlease wait.": "بندور على سائق جديد.\nلو سمحت انتظر.", "The driver canceled your ride.": "السائق ألغى رحلتك.", "Driver Finish Trip": "السائق أنهى الرحلة", "you will pay to Driver": "بتدفع حق السائق", "Don’t forget your personal belongings.": "لا تنسى أغراضك الشخصية.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "لو سمحت تأكد إن معاك كل أغراضك الشخصية وإن أي مبلغ متبقي، إذا فيه، تم إضافته لمحفظتك قبل لا تمشي. شكراً لاستخدامك تطبيق Intaleq", "Finish Monitor": "إنهاء المراقبة", "Trip finished": "الرحلة انتهت", "Call Income from Driver": "مكالمة واردة من السائق", "Driver Cancelled Your Trip": "السائق ألغى رحلتك", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "بتدفع حق السائق بتدفع تكلفة وقت السائق شوف محفظة Intaleq مالتك", "Order Applied": "تم تطبيق الطلب" }, "ar-ma": { "Order": "طلب", "OrderVIP": "طلب VIP", "Cancel Trip": "إلغي الرحلة", "Passenger Cancel Trip": "الزبون ألغى الرحلة", "VIP Order": "طلب VIP", "The driver accepted your trip": "السائق قبل الرحلة ديالك", "message From passenger": "رسالة من الزبون", "Cancel": "إلغاء", "Trip Cancelled. The cost of the trip will be added to your wallet.": "الرحلة ملغية. الفلوس ديال الرحلة غادي تزاد في الجيب ديالك.", "token change": "تبديل الرمز", "face detect": "كشف الوجه", "Face Detection Result": "نتيجة كشف الوجه", "similar": "مشابه", "not similar": "ماشي مشابه", "Hi ,I will go now": "مرحبا، أنا غادي نمشي دابا", "Passenger come to you": "الزبون جاي عندك", "Call Income": "مكالمة واردة", "Call Income from Passenger": "مكالمة واردة من الزبون", "Criminal Document Required": "مطلوب وثيقة جنائية", "You should have upload it .": "خاصك تكون حملتيها.", "Call End": "نهاية المكالمة", "The order has been accepted by another driver.": "الطلب تقبل من عند سائق آخر.", "The order Accepted by another Driver": "الطلب تقبل من عند سائق آخر", "We regret to inform you that another driver has accepted this order.": "كنتأسفوا نبلغوك باللي سائق آخر قبل هذا الطلب.", "Driver Applied the Ride for You": "السائق قدم الطلب ليك", "Applied": "تطبق", "Hi ,I Arrive your site": "مرحبا، وصلت للموقع ديالك", "Please go to Car Driver": "الله يرحم الوالدين سير عند سائق السيارة", "Ok I will go now.": "واخا، غادي نمشي دابا.", "Accepted Ride": "الرحلة مقبولة", "Driver Accepted the Ride for You": "السائق قبل الرحلة ليك", "Promo": "عرض ترويجي", "Show latest promo": "عرض آخر عرض ترويجي", "Trip Monitoring": "مراقبة الرحلة", "Driver Is Going To Passenger": "السائق غادي في الطريق ليك", "Please stay on the picked point.": "الله يرحم الوالدين بقا في نقطة الالتقاط اللي تحددات.", "message From Driver": "رسالة من السائق", "Trip is Begin": "الرحلة بدات", "Cancel Trip from driver": "إلغاء الرحلة من السائق", "We will look for a new driver.\nPlease wait.": "غادي نقلبوا على سائق جديد.\nالله يرحم الوالدين تسنى.", "The driver canceled your ride.": "السائق ألغى الرحلة ديالك.", "Driver Finish Trip": "السائق سالا الرحلة", "you will pay to Driver": "غادي تخلص السائق", "Don’t forget your personal belongings.": "متنساش حوايجك الشخصية.", "Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Intaleq app": "الله يرحم الوالدين تأكد باللي معاك كل حوايجك الشخصية وباللي أي مبلغ باقي، إلا كان، تزاد في الجيب ديالك قبل ما تمشي. شكرا لاستعمالك تطبيق Intaleq", "Finish Monitor": "سالي المراقبة", "Trip finished": "الرحلة سالات", "Call Income from Driver": "مكالمة واردة من السائق", "Driver Cancelled Your Trip": "السائق ألغى الرحلة ديالك", "you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet": "غادي تخلص السائق غادي تخلص تكلفة وقت السائق شوف الجيب ديال Intaleq ديالك", "Order Applied": "الطلب طبق", //firebase above } }; } ================================================== FILE PATH: ./lib/controller/local/phone_intel/helpers.dart ================================================== import 'countries.dart'; bool isNumeric(String s) => s.isNotEmpty && int.tryParse(s.replaceAll("+", "")) != null; String removeDiacritics(String str) { var withDia = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž'; var withoutDia = 'AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZz'; for (int i = 0; i < withDia.length; i++) { str = str.replaceAll(withDia[i], withoutDia[i]); } return str; } extension CountryExtensions on List { List stringSearch(String search) { search = removeDiacritics(search.toLowerCase()); return where( (country) => isNumeric(search) || search.startsWith("+") ? country.dialCode.contains(search) : removeDiacritics(country.name.replaceAll("+", "").toLowerCase()) .contains(search) || country.nameTranslations.values.any((element) => removeDiacritics(element.toLowerCase()).contains(search)), ).toList(); } } ================================================== FILE PATH: ./lib/controller/local/phone_intel/intl_phone_field.dart ================================================== library intl_phone_field; import 'dart:async'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import './countries.dart'; import './phone_number.dart'; import 'country_picker_dialog.dart'; import 'helpers.dart'; class IntlPhoneField extends StatefulWidget { /// The TextFormField key. final GlobalKey? formFieldKey; /// Whether to hide the text being edited (e.g., for passwords). final bool obscureText; /// How the text should be aligned horizontally. final TextAlign textAlign; /// How the text should be aligned vertically. final TextAlignVertical? textAlignVertical; final VoidCallback? onTap; /// {@macro flutter.widgets.editableText.readOnly} final bool readOnly; final FormFieldSetter? onSaved; /// {@macro flutter.widgets.editableText.onChanged} /// /// See also: /// /// * [inputFormatters], which are called before [onChanged] /// runs and can validate and change ("format") the input value. /// * [onEditingComplete], [onSubmitted], [onSelectionChanged]: /// which are more specialized input change notifications. final ValueChanged? onChanged; final ValueChanged? onCountryChanged; /// An optional method that validates an input. Returns an error string to display if the input is invalid, or null otherwise. /// /// A [PhoneNumber] is passed to the validator as argument. /// The validator can handle asynchronous validation when declared as a [Future]. /// Or run synchronously when declared as a [Function]. /// /// By default, the validator checks whether the input number length is between selected country's phone numbers min and max length. /// If `disableLengthCheck` is not set to `true`, your validator returned value will be overwritten by the default validator. /// But, if `disableLengthCheck` is set to `true`, your validator will have to check phone number length itself. final FutureOr Function(PhoneNumber?)? validator; /// {@macro flutter.widgets.editableText.keyboardType} final TextInputType keyboardType; /// Controls the text being edited. /// /// If null, this widget will create its own [TextEditingController]. final TextEditingController? controller; /// Defines the keyboard focus for this widget. /// /// The [focusNode] is a long-lived object that's typically managed by a /// [StatefulWidget] parent. See [FocusNode] for more information. /// /// To give the keyboard focus to this widget, provide a [focusNode] and then /// use the current [FocusScope] to request the focus: /// /// ```dart /// FocusScope.of(context).requestFocus(myFocusNode); /// ``` /// /// This happens automatically when the widget is tapped. /// /// To be notified when the widget gains or loses the focus, add a listener /// to the [focusNode]: /// /// ```dart /// focusNode.addListener(() { print(myFocusNode.hasFocus); }); /// ``` /// /// If null, this widget will create its own [FocusNode]. /// /// ## Keyboard /// /// Requesting the focus will typically cause the keyboard to be shown /// if it's not showing already. /// /// On Android, the user can hide the keyboard - without changing the focus - /// with the system back button. They can restore the keyboard's visibility /// by tapping on a text field. The user might hide the keyboard and /// switch to a physical keyboard, or they might just need to get it /// out of the way for a moment, to expose something it's /// obscuring. In this case requesting the focus again will not /// cause the focus to change, and will not make the keyboard visible. /// /// This widget builds an [EditableText] and will ensure that the keyboard is /// showing when it is tapped by calling [EditableTextState.requestKeyboard()]. final FocusNode? focusNode; /// {@macro flutter.widgets.editableText.onSubmitted} /// /// See also: /// /// * [EditableText.onSubmitted] for an example of how to handle moving to /// the next/previous field when using [TextInputAction.next] and /// [TextInputAction.previous] for [textInputAction]. final void Function(String)? onSubmitted; /// If false the widget is "disabled": it ignores taps, the [TextFormField]'s /// [decoration] is rendered in grey, /// [decoration]'s [InputDecoration.counterText] is set to `""`, /// and the drop down icon is hidden no matter [showDropdownIcon] value. /// /// If non-null this property overrides the [decoration]'s /// [Decoration.enabled] property. final bool enabled; /// The appearance of the keyboard. /// /// This setting is only honored on iOS devices. /// /// If unset, defaults to the brightness of [ThemeData.brightness]. final Brightness? keyboardAppearance; /// Initial Value for the field. /// This property can be used to pre-fill the field. final String? initialValue; final String languageCode; /// 2 letter ISO Code or country dial code. /// /// ```dart /// initialCountryCode: 'IN', // India /// initialCountryCode: '+225', // Côte d'Ivoire /// ``` final String? initialCountryCode; /// List of Country to display see countries.dart for format final List? countries; /// The decoration to show around the text field. /// /// By default, draws a horizontal line under the text field but can be /// configured to show an icon, label, hint text, and error text. /// /// Specify null to remove the decoration entirely (including the /// extra padding introduced by the decoration to save space for the labels). final InputDecoration decoration; /// The style to use for the text being edited. /// /// This text style is also used as the base style for the [decoration]. /// /// If null, defaults to the `subtitle1` text style from the current [Theme]. final TextStyle? style; /// Disable view Min/Max Length check final bool disableLengthCheck; /// Won't work if [enabled] is set to `false`. final bool showDropdownIcon; final BoxDecoration dropdownDecoration; /// The style use for the country dial code. final TextStyle? dropdownTextStyle; /// {@macro flutter.widgets.editableText.inputFormatters} final List? inputFormatters; /// The text that describes the search input field. /// /// When the input field is empty and unfocused, the label is displayed on top of the input field (i.e., at the same location on the screen where text may be entered in the input field). /// When the input field receives focus (or if the field is non-empty), the label moves above (i.e., vertically adjacent to) the input field. final String searchText; /// Position of an icon [leading, trailing] final IconPosition dropdownIconPosition; /// Icon of the drop down button. /// /// Default is [Icon(Icons.arrow_drop_down)] final Icon dropdownIcon; /// Whether this text field should focus itself if nothing else is already focused. final bool autofocus; /// Autovalidate mode for text form field. /// /// If [AutovalidateMode.onUserInteraction], this FormField will only auto-validate after its content changes. /// If [AutovalidateMode.always], it will auto-validate even without user interaction. /// If [AutovalidateMode.disabled], auto-validation will be disabled. /// /// Defaults to [AutovalidateMode.onUserInteraction]. final AutovalidateMode? autovalidateMode; /// Whether to show or hide country flag. /// /// Default value is `true`. final bool showCountryFlag; /// Message to be displayed on autoValidate error /// /// Default value is `Invalid Mobile Number`. final String? invalidNumberMessage; /// The color of the cursor. final Color? cursorColor; /// How tall the cursor will be. final double? cursorHeight; /// How rounded the corners of the cursor should be. final Radius? cursorRadius; /// How thick the cursor will be. final double cursorWidth; /// Whether to show cursor. final bool? showCursor; /// The padding of the Flags Button. /// /// The amount of insets that are applied to the Flags Button. /// /// If unset, defaults to [EdgeInsets.zero]. final EdgeInsetsGeometry flagsButtonPadding; /// The type of action button to use for the keyboard. final TextInputAction? textInputAction; /// Optional set of styles to allow for customizing the country search /// & pick dialog final PickerDialogStyle? pickerDialogStyle; /// The margin of the country selector button. /// /// The amount of space to surround the country selector button. /// /// If unset, defaults to [EdgeInsets.zero]. final EdgeInsets flagsButtonMargin; /// Enable the autofill hint for phone number. final bool disableAutoFillHints; /// If null, default magnification configuration will be used. final TextMagnifierConfiguration? magnifierConfiguration; const IntlPhoneField({ Key? key, this.formFieldKey, this.initialCountryCode, this.languageCode = 'en', this.disableAutoFillHints = false, this.obscureText = false, this.textAlign = TextAlign.left, this.textAlignVertical, this.onTap, this.readOnly = false, this.initialValue, this.keyboardType = TextInputType.phone, this.controller, this.focusNode, this.decoration = const InputDecoration(), this.style, this.dropdownTextStyle, this.onSubmitted, this.validator, this.onChanged, this.countries, this.onCountryChanged, this.onSaved, this.showDropdownIcon = true, this.dropdownDecoration = const BoxDecoration(), this.inputFormatters, this.enabled = true, this.keyboardAppearance, @Deprecated('Use searchFieldInputDecoration of PickerDialogStyle instead') this.searchText = 'Search country', this.dropdownIconPosition = IconPosition.leading, this.dropdownIcon = const Icon(Icons.arrow_drop_down), this.autofocus = false, this.textInputAction, this.autovalidateMode = AutovalidateMode.onUserInteraction, this.showCountryFlag = true, this.cursorColor, this.disableLengthCheck = false, this.flagsButtonPadding = EdgeInsets.zero, this.invalidNumberMessage = 'Invalid Mobile Number', this.cursorHeight, this.cursorRadius = Radius.zero, this.cursorWidth = 2.0, this.showCursor = true, this.pickerDialogStyle, this.flagsButtonMargin = EdgeInsets.zero, this.magnifierConfiguration, }) : super(key: key); @override State createState() => _IntlPhoneFieldState(); } class _IntlPhoneFieldState extends State { late List _countryList; late Country _selectedCountry; late List filteredCountries; late String number; String? validatorMessage; @override void initState() { super.initState(); _countryList = widget.countries ?? countries; filteredCountries = _countryList; number = widget.initialValue ?? ''; if (widget.initialCountryCode == null && number.startsWith('+')) { number = number.substring(1); // parse initial value _selectedCountry = countries.firstWhere( (country) => number.startsWith(country.fullCountryCode), orElse: () => _countryList.first); // remove country code from the initial number value number = number.replaceFirst( RegExp("^${_selectedCountry.fullCountryCode}"), ""); } else { _selectedCountry = _countryList.firstWhere( (item) => item.code == (widget.initialCountryCode ?? 'US'), orElse: () => _countryList.first); // remove country code from the initial number value if (number.startsWith('+')) { number = number.replaceFirst( RegExp("^\\+${_selectedCountry.fullCountryCode}"), ""); } else { number = number.replaceFirst( RegExp("^${_selectedCountry.fullCountryCode}"), ""); } } if (widget.autovalidateMode == AutovalidateMode.always) { final initialPhoneNumber = PhoneNumber( countryISOCode: _selectedCountry.code, countryCode: '+${_selectedCountry.dialCode}', number: widget.initialValue ?? '', ); final value = widget.validator?.call(initialPhoneNumber); if (value is String) { validatorMessage = value; } else { (value as Future).then((msg) { validatorMessage = msg; }); } } } Future _changeCountry() async { filteredCountries = _countryList; await showDialog( context: context, useRootNavigator: false, builder: (context) => StatefulBuilder( builder: (ctx, setState) => CountryPickerDialog( languageCode: widget.languageCode.toLowerCase(), style: widget.pickerDialogStyle, filteredCountries: filteredCountries, searchText: widget.searchText, countryList: _countryList, selectedCountry: _selectedCountry, onCountryChanged: (Country country) { _selectedCountry = country; widget.onCountryChanged?.call(country); setState(() {}); }, ), ), ); if (mounted) setState(() {}); } @override Widget build(BuildContext context) { return TextFormField( key: widget.formFieldKey, initialValue: (widget.controller == null) ? number : null, autofillHints: widget.disableAutoFillHints ? null : [AutofillHints.telephoneNumberNational], readOnly: widget.readOnly, obscureText: widget.obscureText, textAlign: widget.textAlign, textAlignVertical: widget.textAlignVertical, cursorColor: widget.cursorColor, onTap: widget.onTap, controller: widget.controller, focusNode: widget.focusNode, cursorHeight: widget.cursorHeight, cursorRadius: widget.cursorRadius, cursorWidth: widget.cursorWidth, showCursor: widget.showCursor, onFieldSubmitted: widget.onSubmitted, magnifierConfiguration: widget.magnifierConfiguration, decoration: widget.decoration.copyWith( prefixIcon: _buildFlagsButton(), counterText: !widget.enabled ? '' : null, ), style: widget.style, onSaved: (value) { widget.onSaved?.call( PhoneNumber( countryISOCode: _selectedCountry.code, countryCode: '+${_selectedCountry.dialCode}${_selectedCountry.regionCode}', number: value!, ), ); }, onChanged: (value) async { final phoneNumber = PhoneNumber( countryISOCode: _selectedCountry.code, countryCode: '+${_selectedCountry.fullCountryCode}', number: value, ); if (widget.autovalidateMode != AutovalidateMode.disabled) { validatorMessage = await widget.validator?.call(phoneNumber); } widget.onChanged?.call(phoneNumber); }, validator: (value) { if (value == null || !isNumeric(value)) return validatorMessage; if (!widget.disableLengthCheck) { return value.length >= _selectedCountry.minLength && value.length <= _selectedCountry.maxLength ? null : widget.invalidNumberMessage; } return validatorMessage; }, maxLength: widget.disableLengthCheck ? null : _selectedCountry.maxLength, keyboardType: widget.keyboardType, inputFormatters: widget.inputFormatters, enabled: widget.enabled, keyboardAppearance: widget.keyboardAppearance, autofocus: widget.autofocus, textInputAction: widget.textInputAction, autovalidateMode: widget.autovalidateMode, ); } Container _buildFlagsButton() { return Container( margin: widget.flagsButtonMargin, child: DecoratedBox( decoration: widget.dropdownDecoration, child: InkWell( borderRadius: widget.dropdownDecoration.borderRadius as BorderRadius?, onTap: widget.enabled ? _changeCountry : null, child: Padding( padding: widget.flagsButtonPadding, child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox( width: 4, ), if (widget.enabled && widget.showDropdownIcon && widget.dropdownIconPosition == IconPosition.leading) ...[ widget.dropdownIcon, const SizedBox(width: 4), ], if (widget.showCountryFlag) ...[ kIsWeb ? Image.asset( 'assets/flags/${_selectedCountry.code.toLowerCase()}.png', package: 'intl_phone_field', width: 32, ) : Text( _selectedCountry.flag, style: const TextStyle(fontSize: 18), ), const SizedBox(width: 8), ], FittedBox( child: Text( '+${_selectedCountry.dialCode}', style: widget.dropdownTextStyle, ), ), if (widget.enabled && widget.showDropdownIcon && widget.dropdownIconPosition == IconPosition.trailing) ...[ const SizedBox(width: 4), widget.dropdownIcon, ], const SizedBox(width: 8), ], ), ), ), ), ); } } enum IconPosition { leading, trailing, } ================================================== FILE PATH: ./lib/controller/local/phone_intel/country_picker_dialog.dart ================================================== import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:sefer_driver/controller/local/phone_intel/helpers.dart'; import 'countries.dart'; class PickerDialogStyle { final Color? backgroundColor; final TextStyle? countryCodeStyle; final TextStyle? countryNameStyle; final Widget? listTileDivider; final EdgeInsets? listTilePadding; final EdgeInsets? padding; final Color? searchFieldCursorColor; final InputDecoration? searchFieldInputDecoration; final EdgeInsets? searchFieldPadding; final double? width; PickerDialogStyle({ this.backgroundColor, this.countryCodeStyle, this.countryNameStyle, this.listTileDivider, this.listTilePadding, this.padding, this.searchFieldCursorColor, this.searchFieldInputDecoration, this.searchFieldPadding, this.width, }); } class CountryPickerDialog extends StatefulWidget { final List countryList; final Country selectedCountry; final ValueChanged onCountryChanged; final String searchText; final List filteredCountries; final PickerDialogStyle? style; final String languageCode; const CountryPickerDialog({ Key? key, required this.searchText, required this.languageCode, required this.countryList, required this.onCountryChanged, required this.selectedCountry, required this.filteredCountries, this.style, }) : super(key: key); @override State createState() => _CountryPickerDialogState(); } class _CountryPickerDialogState extends State { late List _filteredCountries; late Country _selectedCountry; @override void initState() { _selectedCountry = widget.selectedCountry; _filteredCountries = widget.filteredCountries.toList() ..sort( (a, b) => a .localizedName(widget.languageCode) .compareTo(b.localizedName(widget.languageCode)), ); super.initState(); } @override Widget build(BuildContext context) { final mediaWidth = MediaQuery.of(context).size.width; final width = widget.style?.width ?? mediaWidth; const defaultHorizontalPadding = 40.0; const defaultVerticalPadding = 24.0; return Dialog( insetPadding: EdgeInsets.symmetric( vertical: defaultVerticalPadding, horizontal: mediaWidth > (width + defaultHorizontalPadding * 2) ? (mediaWidth - width) / 2 : defaultHorizontalPadding), backgroundColor: widget.style?.backgroundColor, child: Container( padding: widget.style?.padding ?? const EdgeInsets.all(10), child: Column( children: [ Padding( padding: widget.style?.searchFieldPadding ?? const EdgeInsets.all(0), child: TextField( cursorColor: widget.style?.searchFieldCursorColor, decoration: widget.style?.searchFieldInputDecoration ?? InputDecoration( suffixIcon: const Icon(Icons.search), labelText: widget.searchText, ), onChanged: (value) { _filteredCountries = widget.countryList.stringSearch(value) ..sort( (a, b) => a .localizedName(widget.languageCode) .compareTo(b.localizedName(widget.languageCode)), ); if (mounted) setState(() {}); }, ), ), const SizedBox(height: 20), Expanded( child: ListView.builder( shrinkWrap: true, itemCount: _filteredCountries.length, itemBuilder: (ctx, index) => Column( children: [ ListTile( leading: kIsWeb ? Image.asset( 'assets/flags/${_filteredCountries[index].code.toLowerCase()}.png', package: 'intl_phone_field', width: 32, ) : Text( _filteredCountries[index].flag, style: const TextStyle(fontSize: 18), ), contentPadding: widget.style?.listTilePadding, title: Text( _filteredCountries[index] .localizedName(widget.languageCode), style: widget.style?.countryNameStyle ?? const TextStyle(fontWeight: FontWeight.w700), ), trailing: Text( '+${_filteredCountries[index].dialCode}', style: widget.style?.countryCodeStyle ?? const TextStyle(fontWeight: FontWeight.w700), ), onTap: () { _selectedCountry = _filteredCountries[index]; widget.onCountryChanged(_selectedCountry); Navigator.of(context).pop(); }, ), widget.style?.listTileDivider ?? const Divider(thickness: 1), ], ), ), ), ], ), ), ); } } ================================================== FILE PATH: ./lib/controller/local/phone_intel/countries.dart ================================================== // see: https://en.wikipedia.org/wiki/List_of_country_calling_codes // for list of country/calling codes const List countries = [ Country( name: "Afghanistan", nameTranslations: { "sk": "Afganistan", "se": "Afghanistan", "pl": "Afganistan", "no": "Afghanistan", "ja": "アフガニスタン", "it": "Afghanistan", "zh": "阿富汗", "nl": "Afghanistan", "de": "Afghanistan", "fr": "Afghanistan", "es": "Afganistán", "en": "Afghanistan", "pt_BR": "Afeganistão", "sr-Cyrl": "Авганистан", "sr-Latn": "Avganistan", "zh_TW": "阿富汗", "tr": "Afganistan", "ro": "Afganistan", "ar": "أفغانستان", "fa": "افغانستان", "yue": "阿富汗" }, flag: "🇦🇫", code: "AF", dialCode: "93", minLength: 9, maxLength: 9, ), Country( name: "Åland Islands", nameTranslations: { "sk": "Alandy", "se": "Ålánda", "pl": "Wyspy Alandzkie", "no": "Åland", "ja": "オーランド諸島", "it": "Isole Åland", "zh": "奥兰群岛", "nl": "Åland", "de": "Ålandinseln", "fr": "Îles Åland", "es": "Islas Åland", "en": "Åland Islands", "pt_BR": "Ilhas Aland", "sr-Cyrl": "Аландска Острва", "sr-Latn": "Alandska Ostrva", "zh_TW": "奧蘭群島", "tr": "Åland", "ro": "Insulele Åland", "ar": "جزر أولاند", "fa": "جزیره اولاند", "yue": "奧蘭群島" }, flag: "🇦🇽", code: "AX", dialCode: "358", minLength: 15, maxLength: 15, ), Country( name: "Albania", nameTranslations: { "sk": "Albánsko", "se": "Albánia", "pl": "Albania", "no": "Albania", "ja": "アルバニア", "it": "Albania", "zh": "阿尔巴尼亚", "nl": "Albanië", "de": "Albanien", "fr": "Albanie", "es": "Albania", "en": "Albania", "pt_BR": "Albânia", "sr-Cyrl": "Албанија", "sr-Latn": "Albanija", "zh_TW": "阿爾巴尼亞", "tr": "Arnavutluk", "ro": "Albania", "ar": "ألبانيا", "fa": "آلبانی", "yue": "阿爾巴尼亞" }, flag: "🇦🇱", code: "AL", dialCode: "355", minLength: 9, maxLength: 9, ), Country( name: "Algeria", nameTranslations: { "sk": "Alžírsko", "se": "Algeria", "pl": "Algieria", "no": "Algerie", "ja": "アルジェリア", "it": "Algeria", "zh": "阿尔及利亚", "nl": "Algerije", "de": "Algerien", "fr": "Algérie", "es": "Argelia", "en": "Algeria", "pt_BR": "Argélia", "sr-Cyrl": "Аргентина", "sr-Latn": "Argentina", "zh_TW": "阿爾及利亞", "tr": "Cezayir", "ro": "Algeria", "ar": "الجزائر", "fa": "الجزیره", "yue": "阿爾及利亞" }, flag: "🇩🇿", code: "DZ", dialCode: "213", minLength: 9, maxLength: 9, ), Country( name: "American Samoa", nameTranslations: { "sk": "Americká Samoa", "se": "Amerihká Samoa", "pl": "Samoa Amerykańskie", "no": "Amerikansk Samoa", "ja": "米領サモア", "it": "Samoa americane", "zh": "美属萨摩亚", "nl": "Amerikaans-Samoa", "de": "Amerikanisch-Samoa", "fr": "Samoa américaines", "es": "Samoa Americana", "en": "American Samoa", "pt_BR": "Samoa Americana", "sr-Cyrl": "Америчка Самоа", "sr-Latn": "Američka Samoa", "zh_TW": "美屬薩摩亞", "tr": "Amerikan Samoası", "ro": "Samoa Americană", "ar": "ساموا الأمريكية", "fa": "ساموا آمریکا", "yue": "美屬薩摩亞" }, flag: "🇦🇸", code: "AS", dialCode: "1684", minLength: 7, maxLength: 7, ), Country( name: "Andorra", nameTranslations: { "sk": "Andorra", "se": "Andorra", "pl": "Andora", "no": "Andorra", "ja": "アンドラ", "it": "Andorra", "zh": "安道尔", "nl": "Andorra", "de": "Andorra", "fr": "Andorre", "es": "Andorra", "en": "Andorra", "pt_BR": "Andorra", "sr-Cyrl": "Андора", "sr-Latn": "Andora", "zh_TW": "安道爾", "tr": "Andora", "ro": "Andorra", "ar": "أندورا", "fa": "آندورا", "yue": "安道爾" }, flag: "🇦🇩", code: "AD", dialCode: "376", minLength: 6, maxLength: 6, ), Country( name: "Angola", nameTranslations: { "sk": "Angola", "se": "Angola", "pl": "Angola", "no": "Angola", "ja": "アンゴラ", "it": "Angola", "zh": "安哥拉", "nl": "Angola", "de": "Angola", "fr": "Angola", "es": "Angola", "en": "Angola", "pt_BR": "Angola", "sr-Cyrl": "Ангола", "sr-Latn": "Angola", "zh_TW": "安哥拉", "tr": "Angola", "ro": "Angola", "ar": "أنغولا", "fa": "آنگولا", "yue": "安哥拉" }, flag: "🇦🇴", code: "AO", dialCode: "244", minLength: 9, maxLength: 9, ), Country( name: "Anguilla", nameTranslations: { "sk": "Anguilla", "se": "Anguilla", "pl": "Anguilla", "no": "Anguilla", "ja": "アンギラ", "it": "Anguilla", "zh": "安圭拉", "nl": "Anguilla", "de": "Anguilla", "fr": "Anguilla", "es": "Anguila", "en": "Anguilla", "pt_BR": "Anguilla", "sr-Cyrl": "Ангвила", "sr-Latn": "Angvila", "zh_TW": "安圭拉", "tr": "Anguilla", "ro": "Anguilla", "ar": "أنغويلا", "fa": "آنگولیا", "yue": "安圭拉" }, flag: "🇦🇮", code: "AI", dialCode: "1264", minLength: 7, maxLength: 7, ), Country( name: "Antarctica", nameTranslations: { "sk": "Antarktída", "se": "Antárktis", "pl": "Antarktyda", "no": "Antarktis", "ja": "南極", "it": "Antartide", "zh": "南极洲", "nl": "Antarctica", "de": "Antarktis", "fr": "Antarctique", "es": "Antártida", "en": "Antarctica", "pt_BR": "Antártica", "sr-Cyrl": "Антарктик", "sr-Latn": "Antarktik", "zh_TW": "南極", "tr": "Antarktika", "ro": "Antarctica", "ar": "القارة القطبية الجنوبية", "fa": "قطب جنوب", "yue": "南极洲" }, flag: "🇦🇶", code: "AQ", dialCode: "672", minLength: 6, maxLength: 6, ), Country( name: "Antigua and Barbuda", nameTranslations: { "sk": "Antigua a Barbuda", "se": "Antigua ja Barbuda", "pl": "Antigua i Barbuda", "no": "Antigua og Barbuda", "ja": "アンティグア・バーブーダ", "it": "Antigua e Barbuda", "zh": "安提瓜和巴布达", "nl": "Antigua en Barbuda", "de": "Antigua und Barbuda", "fr": "Antigua-et-Barbuda", "es": "Antigua y Barbuda", "en": "Antigua & Barbuda", "pt_BR": "Antigua e Barbuda", "sr-Cyrl": "Антигва и Барбуда", "sr-Latn": "Antigva i Barbuda", "zh_TW": "安提瓜和巴布達", "tr": "Antigua ve Barbuda", "ro": "Antigua şi Barbuda", "ar": "أنتيغوا وباربودا", "fa": "آنتیگوآ و باربودا", "yue": "安提瓜同巴布达" }, flag: "🇦🇬", code: "AG", dialCode: "1268", minLength: 7, maxLength: 7, ), Country( name: "Argentina", nameTranslations: { "sk": "Argentína", "se": "Argentina", "pl": "Argentyna", "no": "Argentina", "ja": "アルゼンチン", "it": "Argentina", "zh": "阿根廷", "nl": "Argentinië", "de": "Argentinien", "fr": "Argentine", "es": "Argentina", "en": "Argentina", "pt_BR": "Argentina", "sr-Cyrl": "Аргентина", "sr-Latn": "Argentina", "zh_TW": "阿根廷", "tr": "Arjantin", "ro": "Argentina", "ar": "الأرجنتين", "fa": "آرژانتین", "yue": "阿根廷" }, flag: "🇦🇷", code: "AR", dialCode: "54", minLength: 12, maxLength: 12, ), Country( name: "Armenia", nameTranslations: { "sk": "Arménsko", "se": "Armenia", "pl": "Armenia", "no": "Armenia", "ja": "アルメニア", "it": "Armenia", "zh": "亚美尼亚", "nl": "Armenië", "de": "Armenien", "fr": "Arménie", "es": "Armenia", "en": "Armenia", "pt_BR": "Armênia", "sr-Cyrl": "Јерменија", "sr-Latn": "Jermenija", "zh_TW": "亞美尼亞", "tr": "Ermenistan", "ro": "Armenia", "ar": "أرمينيا", "fa": "ارمنستان", "yue": "亞美尼亞" }, flag: "🇦🇲", code: "AM", dialCode: "374", minLength: 8, maxLength: 8, ), Country( name: "Aruba", nameTranslations: { "sk": "Aruba", "se": "Aruba", "pl": "Aruba", "no": "Aruba", "ja": "アルバ", "it": "Aruba", "zh": "阿鲁巴", "nl": "Aruba", "de": "Aruba", "fr": "Aruba", "es": "Aruba", "en": "Aruba", "pt_BR": "Aruba", "sr-Cyrl": "Аруба", "sr-Latn": "Aruba", "zh_TW": "阿魯巴", "tr": "Aruba", "ro": "Aruba", "ar": "أروبا", "fa": "آروبا", "yue": "阿魯巴島" }, flag: "🇦🇼", code: "AW", dialCode: "297", minLength: 7, maxLength: 7, ), Country( name: "Australia", nameTranslations: { "sk": "Austrália", "se": "Austrália", "pl": "Australia", "no": "Australia", "ja": "オーストラリア", "it": "Australia", "zh": "澳大利亚", "nl": "Australië", "de": "Australien", "fr": "Australie", "es": "Australia", "en": "Australia", "pt_BR": "Austrália", "sr-Cyrl": "Аустралија", "sr-Latn": "Australija", "zh_TW": "澳州", "tr": "Avustralya", "ro": "Australia", "ar": "أستراليا", "fa": "استرالیا", "yue": "澳洲" }, flag: "🇦🇺", code: "AU", dialCode: "61", minLength: 9, maxLength: 9, ), Country( name: "Austria", nameTranslations: { "sk": "Rakúsko", "se": "Nuortariika", "pl": "Austria", "no": "Østerrike", "ja": "オーストリア", "it": "Austria", "zh": "奥地利", "nl": "Oostenrijk", "de": "Österreich", "fr": "Autriche", "es": "Austria", "en": "Austria", "pt_BR": "Áustria", "sr-Cyrl": "Аустрија", "sr-Latn": "Austrija", "zh_TW": "奥地利", "tr": "Avusturya", "ro": "Austria", "ar": "النمسا", "fa": "اتریش", "yue": "奧地利" }, flag: "🇦🇹", code: "AT", dialCode: "43", minLength: 13, maxLength: 13, ), Country( name: "Azerbaijan", nameTranslations: { "sk": "Azerbajdžan", "se": "Aserbaižan", "pl": "Azerbejdżan", "no": "Aserbajdsjan", "ja": "アゼルバイジャン", "it": "Azerbaigian", "zh": "阿塞拜疆", "nl": "Azerbeidzjan", "de": "Aserbaidschan", "fr": "Azerbaïdjan", "es": "Azerbaiyán", "en": "Azerbaijan", "pt_BR": "Azerbaijão", "sr-Cyrl": "Азербејџан", "sr-Latn": "Azerbejdžan", "zh_TW": "亞塞拜然", "tr": "Azerbaycan", "ro": "Azerbaidjan", "ar": "أذربيجان", "fa": "آذربایجان", "yue": "阿塞拜疆" }, flag: "🇦🇿", code: "AZ", dialCode: "994", minLength: 9, maxLength: 9, ), Country( name: "Bahamas", nameTranslations: { "sk": "Bahamy", "se": "Bahamas", "pl": "Bahamy", "no": "Bahamas", "ja": "バハマ", "it": "Bahamas", "zh": "巴哈马", "nl": "Bahama's", "de": "Bahamas", "fr": "Bahamas", "es": "Bahamas", "en": "Bahamas", "pt_BR": "Bahamas", "sr-Cyrl": "Бахаме", "sr-Latn": "Bahame", "zh_TW": "巴哈馬", "tr": "Bahama", "ro": "Bahamas", "ar": "باهاماس", "fa": "باهاماس", "yue": "巴哈馬" }, flag: "🇧🇸", code: "BS", dialCode: "1242", minLength: 7, maxLength: 7, ), Country( name: "Bahrain", nameTranslations: { "sk": "Bahrajn", "se": "Bahrain", "pl": "Bahrajn", "no": "Bahrain", "ja": "バーレーン", "it": "Bahrein", "zh": "巴林", "nl": "Bahrein", "de": "Bahrain", "fr": "Bahreïn", "es": "Baréin", "en": "Bahrain", "pt_BR": "Bahrain", "sr-Cyrl": "Бахреин", "sr-Latn": "Bahrein", "zh_TW": "巴林", "tr": "Bahreyn", "ro": "Bahrein", "ar": "البحرين", "fa": "بحرین", "yue": "巴林" }, flag: "🇧🇭", code: "BH", dialCode: "973", minLength: 8, maxLength: 8, ), Country( name: "Bangladesh", nameTranslations: { "sk": "Bangladéš", "se": "Bangladesh", "pl": "Bangladesz", "no": "Bangladesh", "ja": "バングラデシュ", "it": "Bangladesh", "zh": "孟加拉国", "nl": "Bangladesh", "de": "Bangladesch", "fr": "Bangladesh", "es": "Bangladés", "en": "Bangladesh", "pt_BR": "Bangladesh", "sr-Cyrl": "Бангладеш", "sr-Latn": "Bangladeš", "zh_TW": "孟加拉", "tr": "Bangladeş", "ro": "Bangladesh", "ar": "بنغلاديش", "fa": "بنگلادش", "yue": "孟加拉囯" }, flag: "🇧🇩", code: "BD", dialCode: "880", minLength: 10, maxLength: 10, ), Country( name: "Barbados", nameTranslations: { "sk": "Barbados", "se": "Barbados", "pl": "Barbados", "no": "Barbados", "ja": "バルバドス", "it": "Barbados", "zh": "巴巴多斯", "nl": "Barbados", "de": "Barbados", "fr": "Barbade", "es": "Barbados", "en": "Barbados", "pt_BR": "Barbados", "sr-Cyrl": "Барбадос", "sr-Latn": "Barbados", "zh_TW": "巴巴多斯", "tr": "Barbados", "ro": "Barbados", "ar": "باربادوس", "fa": "باربادوس", "yue": "巴巴多斯" }, flag: "🇧🇧", code: "BB", dialCode: "1246", minLength: 7, maxLength: 7, ), Country( name: "Belarus", nameTranslations: { "sk": "Bielorusko", "se": "Vilges-Ruošša", "pl": "Białoruś", "no": "Hviterussland", "ja": "ベラルーシ", "it": "Bielorussia", "zh": "白俄罗斯", "nl": "Belarus", "de": "Belarus", "fr": "Biélorussie", "es": "Bielorrusia", "en": "Belarus", "pt_BR": "Bielo-Rússia", "sr-Cyrl": "Белорусија", "sr-Latn": "Belorusija", "zh_TW": "白俄羅斯", "tr": "Belarus", "ro": "Belarus", "ar": "بيلاروس", "fa": "بلاروس", "yue": "白俄羅斯" }, flag: "🇧🇾", code: "BY", dialCode: "375", minLength: 10, maxLength: 10, ), Country( name: "Belgium", nameTranslations: { "sk": "Belgicko", "se": "Belgia", "pl": "Belgia", "no": "Belgia", "ja": "ベルギー", "it": "Belgio", "zh": "比利时", "nl": "België", "de": "Belgien", "fr": "Belgique", "es": "Bélgica", "en": "Belgium", "pt_BR": "Bélgica", "sr-Cyrl": "Белгија", "sr-Latn": "Belgija", "zh_TW": "比利時", "tr": "Belçika", "ro": "Belgia", "ar": "بلجيكا", "fa": "بلژیک", "yue": "比利時" }, flag: "🇧🇪", code: "BE", dialCode: "32", minLength: 9, maxLength: 9, ), Country( name: "Belize", nameTranslations: { "sk": "Belize", "se": "Belize", "pl": "Belize", "no": "Belize", "ja": "ベリーズ", "it": "Belize", "zh": "伯利兹", "nl": "Belize", "de": "Belize", "fr": "Belize", "es": "Belice", "en": "Belize", "pt_BR": "Belize", "sr-Cyrl": "Белизе", "sr-Latn": "Belize", "zh_TW": "伯利茲", "tr": "Belize", "ro": "Belize", "ar": "بليز", "fa": "بليز", "yue": "伯利茲" }, flag: "🇧🇿", code: "BZ", dialCode: "501", minLength: 7, maxLength: 7, ), Country( name: "Benin", nameTranslations: { "sk": "Benin", "se": "Benin", "pl": "Benin", "no": "Benin", "ja": "ベナン", "it": "Benin", "zh": "贝宁", "nl": "Benin", "de": "Benin", "fr": "Bénin", "es": "Benín", "en": "Benin", "pt_BR": "Benin", "sr-Cyrl": "Бенин", "sr-Latn": "Benin", "zh_TW": "貝南", "tr": "Benin", "ro": "Benin", "ar": "بنين", "fa": "بنين", "yue": "貝寧" }, flag: "🇧🇯", code: "BJ", dialCode: "229", minLength: 8, maxLength: 8, ), Country( name: "Bermuda", nameTranslations: { "sk": "Bermudy", "se": "Bermuda", "pl": "Bermudy", "no": "Bermuda", "ja": "バミューダ", "it": "Bermuda", "zh": "百慕大", "nl": "Bermuda", "de": "Bermuda", "fr": "Bermudes", "es": "Bermudas", "en": "Bermuda", "pt_BR": "Bermudas", "sr-Cyrl": "Бермуда", "sr-Latn": "Bermuda", "zh_TW": "百慕達", "tr": "Bermuda", "ro": "Insulele Bermude", "ar": "برمودا", "fa": "برمودا", "yue": "百慕大" }, flag: "🇧🇲", code: "BM", dialCode: "1441", minLength: 7, maxLength: 7, ), Country( name: "Bhutan", nameTranslations: { "sk": "Bhután", "se": "Bhutan", "pl": "Bhutan", "no": "Bhutan", "ja": "ブータン", "it": "Bhutan", "zh": "不丹", "nl": "Bhutan", "de": "Bhutan", "fr": "Bhoutan", "es": "Bután", "en": "Bhutan", "pt_BR": "Butão", "sr-Cyrl": "Бутан", "sr-Latn": "Butan", "zh_TW": "不丹", "tr": "Bhutan", "ro": "Bhutan", "ar": "بوتان", "fa": "بوتان", "yue": "不丹" }, flag: "🇧🇹", code: "BT", dialCode: "975", minLength: 8, maxLength: 8, ), Country( name: "Bolivia, Plurinational State of bolivia", nameTranslations: { "sk": "Bolívia", "se": "Bolivia", "pl": "Boliwia", "no": "Bolivia", "ja": "ボリビア", "it": "Bolivia", "zh": "玻利维亚", "nl": "Bolivia", "de": "Bolivien", "fr": "Bolivie", "es": "Bolivia", "en": "Bolivia", "pt_BR": "Bolívia", "sr-Cyrl": "Боливија", "sr-Latn": "Bolivija", "zh_TW": "玻利維亞", "tr": "Bolivya", "ro": "Bolivia", "ar": "بوليفيا", "fa": "بولیوی", "yue": "玻利維亞(多民族國家)" }, flag: "🇧🇴", code: "BO", dialCode: "591", minLength: 8, maxLength: 8, ), Country( name: "Bosnia and Herzegovina", nameTranslations: { "sk": "Bosna a Hercegovina", "se": "Bosnia-Hercegovina", "pl": "Bośnia i Hercegowina", "no": "Bosnia-Hercegovina", "ja": "ボスニア・ヘルツェゴビナ", "it": "Bosnia ed Erzegovina", "zh": "波斯尼亚和黑塞哥维那", "nl": "Bosnië en Herzegovina", "de": "Bosnien und Herzegowina", "fr": "Bosnie-Herzégovine", "es": "Bosnia y Herzegovina", "en": "Bosnia & Herzegovina", "pt_BR": "Bósnia e Herzegovina", "sr-Cyrl": "Босна и Херцеговина", "sr-Latn": "Bosna i Hercegovina", "zh_TW": "波士尼亞和黑塞哥維那", "tr": "Bosna Hersek", "ro": "Bosnia și Herțegovina", "ar": "البوسنة والهرسك", "fa": "بوسنی و هرزگوین", "yue": "波斯尼亞黑塞哥維那" }, flag: "🇧🇦", code: "BA", dialCode: "387", minLength: 9, maxLength: 9, ), Country( name: "Botswana", nameTranslations: { "sk": "Botswana", "se": "Botswana", "pl": "Botswana", "no": "Botswana", "ja": "ボツワナ", "it": "Botswana", "zh": "博茨瓦纳", "nl": "Botswana", "de": "Botsuana", "fr": "Botswana", "es": "Botsuana", "en": "Botswana", "pt_BR": "Botswana", "sr-Cyrl": "Боцвана", "sr-Latn": "Bocvana", "zh_TW": "博茨瓦納", "tr": "Botsvana", "ro": "Botswana", "ar": "بوتسوانا", "fa": "بوتسوانا", "yue": "博茨瓦納" }, flag: "🇧🇼", code: "BW", dialCode: "267", minLength: 8, maxLength: 8, ), Country( name: "Bouvet Island", nameTranslations: { "sk": "Bouvetov ostrov", "se": "Bouvet-sullot", "pl": "Wyspa Bouveta", "no": "Bouvetøya", "ja": "ブーベ島", "it": "Isola Bouvet", "zh": "布韦岛", "nl": "Bouveteiland", "de": "Bouvetinsel", "fr": "Île Bouvet", "es": "Isla Bouvet", "en": "Bouvet Island", "pt_BR": "Ilha Bouvet", "sr-Cyrl": "Острво Буве", "sr-Latn": "Ostrvo Buve", "zh_TW": "布維特島", "tr": "Bouvet Adası", "ro": "Insula Bouvet", "ar": "جزيرة بوفيه", "fa": "جزیره بووه", "yue": "布维特岛" }, flag: "🇧🇻", code: "BV", dialCode: "47", minLength: 15, maxLength: 15, ), Country( name: "Brazil", nameTranslations: { "sk": "Brazília", "se": "Brasil", "pl": "Brazylia", "no": "Brasil", "ja": "ブラジル", "it": "Brasile", "zh": "巴西", "nl": "Brazilië", "de": "Brasilien", "fr": "Brésil", "es": "Brasil", "en": "Brazil", "pt_BR": "Brasil", "sr-Cyrl": "Бразил", "sr-Latn": "Brazil", "zh_TW": "巴西", "tr": "Brezilya", "ro": "Brazilia", "ar": "البرازيل", "fa": "برزیل", "yue": "巴西" }, flag: "🇧🇷", code: "BR", dialCode: "55", minLength: 11, maxLength: 11, ), Country( name: "British Indian Ocean Territory", nameTranslations: { "sk": "Britské indickooceánske územie", "se": "British Indian Ocean Territory", "pl": "Brytyjskie Terytorium Oceanu Indyjskiego", "no": "Det britiske territoriet i Indiahavet", "ja": "英領インド洋地域", "it": "Territorio britannico dell'Oceano Indiano", "zh": "英属印度洋领地", "nl": "Brits Indische Oceaanterritorium", "de": "Britisches Territorium im Indischen Ozean", "fr": "Territoire britannique de l'océan Indien", "es": "Territorio Británico del Océano Índico", "en": "British Indian Ocean Territory", "pt_BR": "Território Britânico do Oceano Índico", "sr-Cyrl": "Британска територија Индијског океана", "sr-Latn": "Britanska teritorija Indijskog okeana", "zh_TW": "英屬印度洋領地", "tr": "Britanya Hint Okyanusu Toprakları", "ro": "Teritoriul Britanic din Oceanul Indian", "ar": "إقليم المحيط الهندي البريطاني", "fa": "سرزمین دریایی هند - بریتانیا", "yue": "英屬印度洋領土" }, flag: "🇮🇴", code: "IO", dialCode: "246", minLength: 7, maxLength: 7, ), Country( name: "Brunei Darussalam", nameTranslations: { "sk": "Brunej", "se": "Brunei", "pl": "Brunei", "no": "Brunei", "ja": "ブルネイ", "it": "Brunei", "zh": "文莱", "nl": "Brunei", "de": "Brunei Darussalam", "fr": "Brunéi Darussalam", "es": "Brunéi", "en": "Brunei", "pt_BR": "Brunei", "sr-Cyrl": "Брунеј", "sr-Latn": "Brunej", "zh_TW": "汶萊", "tr": "Bruney", "ro": "Brunei", "ar": "بروناي", "fa": "برونئی", "yue": "文萊達魯薩蘭國" }, flag: "🇧🇳", code: "BN", dialCode: "673", minLength: 7, maxLength: 7, ), Country( name: "Bulgaria", nameTranslations: { "sk": "Bulharsko", "se": "Bulgária", "pl": "Bułgaria", "no": "Bulgaria", "ja": "ブルガリア", "it": "Bulgaria", "zh": "保加利亚", "nl": "Bulgarije", "de": "Bulgarien", "fr": "Bulgarie", "es": "Bulgaria", "en": "Bulgaria", "pt_BR": "Bulgária", "sr-Cyrl": "Бугарска", "sr-Latn": "Bugarska", "zh_TW": "保加利亞", "tr": "Bulgaristan", "ro": "Bulgaria", "ar": "بلغاريا", "fa": "بلغارستان", "yue": "保加利亞" }, flag: "🇧🇬", code: "BG", dialCode: "359", minLength: 9, maxLength: 9, ), Country( name: "Burkina Faso", nameTranslations: { "sk": "Burkina Faso", "se": "Burkina Faso", "pl": "Burkina Faso", "no": "Burkina Faso", "ja": "ブルキナファソ", "it": "Burkina Faso", "zh": "布基纳法索", "nl": "Burkina Faso", "de": "Burkina Faso", "fr": "Burkina Faso", "es": "Burkina Faso", "en": "Burkina Faso", "pt_BR": "Burkina Faso", "sr-Cyrl": "Буркина Фасо", "sr-Latn": "Burkina Faso", "zh_TW": "布吉納法索", "tr": "Burkina Faso", "ro": "Burkina Faso", "ar": "بوركينا فاسو", "fa": "بورکینافاسو", "yue": "布基納法索" }, flag: "🇧🇫", code: "BF", dialCode: "226", minLength: 8, maxLength: 8, ), Country( name: "Burundi", nameTranslations: { "sk": "Burundi", "se": "Burundi", "pl": "Burundi", "no": "Burundi", "ja": "ブルンジ", "it": "Burundi", "zh": "布隆迪", "nl": "Burundi", "de": "Burundi", "fr": "Burundi", "es": "Burundi", "en": "Burundi", "pt_BR": "Burundi", "sr-Cyrl": "Бурунди", "sr-Latn": "Burundi", "zh_TW": "蒲隆地", "tr": "Burundi", "ro": "Burundi", "ar": "بوروندي", "fa": "بوروندی", "yue": "蒲隆地" }, flag: "🇧🇮", code: "BI", dialCode: "257", minLength: 8, maxLength: 8, ), Country( name: "Cambodia", nameTranslations: { "sk": "Kambodža", "se": "Kambodža", "pl": "Kambodża", "no": "Kambodsja", "ja": "カンボジア", "it": "Cambogia", "zh": "柬埔寨", "nl": "Cambodja", "de": "Kambodscha", "fr": "Cambodge", "es": "Camboya", "en": "Cambodia", "pt_BR": "Camboja", "sr-Cyrl": "Камбоџа", "sr-Latn": "Kambodža", "zh_TW": "柬埔寨", "tr": "Kamboçya", "ro": "Cambogia", "ar": "كمبوديا", "fa": "کامبوج", "yue": "柬埔寨" }, flag: "🇰🇭", code: "KH", dialCode: "855", minLength: 9, maxLength: 9, ), Country( name: "Cameroon", nameTranslations: { "sk": "Kamerun", "se": "Kamerun", "pl": "Kamerun", "no": "Kamerun", "ja": "カメルーン", "it": "Camerun", "zh": "喀麦隆", "nl": "Kameroen", "de": "Kamerun", "fr": "Cameroun", "es": "Camerún", "en": "Cameroon", "pt_BR": "Camarões", "sr-Cyrl": "Камерун", "sr-Latn": "Kamerun", "zh_TW": "喀麥隆", "tr": "Kamerun", "ro": "Camerun", "ar": "الكاميرون", "fa": "کامرون", "yue": "喀 麥 隆" }, flag: "🇨🇲", code: "CM", dialCode: "237", minLength: 9, maxLength: 9, ), Country( name: "Canada", nameTranslations: { "sk": "Kanada", "se": "Kanáda", "pl": "Kanada", "no": "Canada", "ja": "カナダ", "it": "Canada", "zh": "加拿大", "nl": "Canada", "de": "Kanada", "fr": "Canada", "es": "Canadá", "en": "Canada", "pt_BR": "Canadá", "sr-Cyrl": "Канада", "sr-Latn": "Kanada", "zh_TW": "加拿大", "tr": "Kanada", "ro": "Canada", "ar": "كندا", "fa": "کانادا", "yue": "加拿大" }, flag: "🇨🇦", code: "CA", dialCode: "1", minLength: 10, maxLength: 10, ), Country( name: "Cayman Islands", nameTranslations: { "sk": "Kajmanie ostrovy", "se": "Cayman-sullot", "pl": "Kajmany", "no": "Caymanøyene", "ja": "ケイマン諸島", "it": "Isole Cayman", "zh": "开曼群岛", "nl": "Kaaimaneilanden", "de": "Kaimaninseln", "fr": "Îles Caïmans", "es": "Islas Caimán", "en": "Cayman Islands", "pt_BR": "Ilhas Cayman", "sr-Cyrl": "Кајманска Острва", "sr-Latn": "Kajmanska Ostrva", "zh_TW": "開曼群島", "tr": "Cayman Adaları", "ro": "Insulele Cayman", "ar": "جزر كايمان", "fa": "جزایر کیمن", "yue": "開曼群島" }, flag: "🇰🇾", code: "KY", dialCode: "345", minLength: 7, maxLength: 7, ), Country( name: "Central African Republic", nameTranslations: { "sk": "Stredoafrická republika", "se": "Gaska-Afrihká dásseváldi", "pl": "Republika Środkowoafrykańska", "no": "Den sentralafrikanske republikk", "ja": "中央アフリカ共和国", "it": "Repubblica Centrafricana", "zh": "中非共和国", "nl": "Centraal-Afrikaanse Republiek", "de": "Zentralafrikanische Republik", "fr": "République centrafricaine", "es": "República Centroafricana", "en": "Central African Republic", "pt_BR": "República Centro-Africana", "sr-Cyrl": "Централноафричка Република", "sr-Latn": "Centralnoafrička Republika", "zh_TW": "中非共和國", "tr": "Orta Afrika Cumhuriyeti", "ro": "Republica Centrafricană", "ar": "جمهورية أفريقيا الوسطى", "fa": "جمهوری افریقای مرکزی", "yue": "中非共和國" }, flag: "🇨🇫", code: "CF", dialCode: "236", minLength: 8, maxLength: 8, ), Country( name: "Chad", nameTranslations: { "sk": "Čad", "se": "Tčad", "pl": "Czad", "no": "Tsjad", "ja": "チャド", "it": "Ciad", "zh": "乍得", "nl": "Tsjaad", "de": "Tschad", "fr": "Tchad", "es": "Chad", "en": "Chad", "pt_BR": "Chade", "sr-Cyrl": "Чад", "sr-Latn": "Čad", "zh_TW": "查德", "tr": "Çad", "ro": "Ciad", "ar": "تشاد", "fa": "چاد", "yue": "乍得" }, flag: "🇹🇩", code: "TD", dialCode: "235", minLength: 7, maxLength: 7, ), Country( name: "Chile", nameTranslations: { "sk": "Čile", "se": "Čiile", "pl": "Chile", "no": "Chile", "ja": "チリ", "it": "Cile", "zh": "智利", "nl": "Chili", "de": "Chile", "fr": "Chili", "es": "Chile", "en": "Chile", "pt_BR": "Chile", "sr-Cyrl": "Чиле", "sr-Latn": "Čile", "zh_TW": "智利", "tr": "Şili", "ro": "Chile", "ar": "تشيلي", "fa": "شیلی", "yue": "智利" }, flag: "🇨🇱", code: "CL", dialCode: "56", minLength: 9, maxLength: 9, ), Country( name: "China", nameTranslations: { "sk": "Čína", "se": "Kiinná", "pl": "Chiny", "no": "Kina", "ja": "中国", "it": "Cina", "zh": "中国", "nl": "China", "de": "China", "fr": "Chine", "es": "China", "en": "China", "pt_BR": "China", "sr-Cyrl": "Кина", "sr-Latn": "Kina", "zh_TW": "中國", "tr": "Çin", "ro": "China", "ar": "الصين", "fa": "چین", "yue": "中國" }, flag: "🇨🇳", code: "CN", dialCode: "86", minLength: 11, maxLength: 12, ), Country( name: "Christmas Island", nameTranslations: { "sk": "Vianočný ostrov", "se": "Juovllat-sullot", "pl": "Wyspa Bożego Narodzenia", "no": "Christmasøya", "ja": "クリスマス島", "it": "Isola Christmas", "zh": "圣诞岛", "nl": "Christmaseiland", "de": "Weihnachtsinsel", "fr": "Île Christmas", "es": "Isla de Navidad", "en": "Christmas Island", "pt_BR": "Ilha do Natal", "sr-Cyrl": "Ускршња Острва", "sr-Latn": "Uskršnja Ostrva", "zh_TW": "聖誕島", "tr": "Christmas Adası", "ro": "Insula Crăciunului", "ar": "جزيرة عيد الميلاد", "fa": "جزیره کریسمس", "yue": "聖誕島" }, flag: "🇨🇽", code: "CX", dialCode: "61", minLength: 15, maxLength: 15, ), Country( name: "Cocos (Keeling) Islands", nameTranslations: { "sk": "Kokosové ostrovy", "se": "Cocos-sullot", "pl": "Wyspy Kokosowe", "no": "Kokosøyene", "ja": "ココス(キーリング)諸島", "it": "Isole Cocos (Keeling)", "zh": "科科斯(基林)群岛", "nl": "Cocoseilanden", "de": "Kokosinseln", "fr": "Îles Cocos", "es": "Islas Cocos", "en": "Cocos (Keeling) Islands", "pt_BR": "Ilhas Cocos (Keeling)", "sr-Cyrl": "Кокосова Острва", "sr-Latn": "Kokosova Ostrva", "zh_TW": "科科斯(基林)群島", "tr": "Cocos (Keyling) Adaları", "ro": "Insulele Cocos", "ar": "جزر كوكوس", "fa": "جزایر کوکوس", "yue": "可可島(基林)群島" }, flag: "🇨🇨", code: "CC", dialCode: "61", minLength: 15, maxLength: 15, ), Country( name: "Colombia", nameTranslations: { "sk": "Kolumbia", "se": "Kolombia", "pl": "Kolumbia", "no": "Colombia", "ja": "コロンビア", "it": "Colombia", "zh": "哥伦比亚", "nl": "Colombia", "de": "Kolumbien", "fr": "Colombie", "es": "Colombia", "en": "Colombia", "pt_BR": "Colômbia", "sr-Cyrl": "Колумбија", "sr-Latn": "Kolumbija", "zh_TW": "哥倫比亞", "tr": "Kolombiya", "ro": "Columbia", "ar": "كولومبيا", "fa": "کلمبیا", "yue": "哥倫比亞" }, flag: "🇨🇴", code: "CO", dialCode: "57", minLength: 10, maxLength: 10, ), Country( name: "Comoros", nameTranslations: { "sk": "Komory", "se": "Komoros", "pl": "Komory", "no": "Komorene", "ja": "コモロ", "it": "Comore", "zh": "科摩罗", "nl": "Comoren", "de": "Komoren", "fr": "Comores", "es": "Comoras", "en": "Comoros", "pt_BR": "Comores", "sr-Cyrl": "Комори", "sr-Latn": "Komori", "zh_TW": "科摩羅", "tr": "Komor Adaları", "ro": "Comore", "ar": "جزر القمر", "fa": "جزیره کومور", "yue": "科摩羅" }, flag: "🇰🇲", code: "KM", dialCode: "269", minLength: 7, maxLength: 7, ), Country( name: "Congo", nameTranslations: { "sk": "Konžská republika", "se": "Kongo-Brazzaville", "pl": "Kongo", "no": "Kongo-Brazzaville", "ja": "コンゴ共和国(ブラザビル)", "it": "Congo-Brazzaville", "zh": "刚果(布)", "nl": "Congo-Brazzaville", "de": "Kongo-Brazzaville", "fr": "Congo-Brazzaville", "es": "Congo", "en": "Congo - Brazzaville", "pt_BR": "República do Congo", "sr-Cyrl": "Република Конго", "sr-Latn": "Republika Kongo", "zh_TW": "剛果共和國(布拉柴維爾)", "tr": "Kongo Cumhuriyeti", "ro": "Republica Congo", "ar": "جمهورية الكونغو", "fa": "جمهوری کنگو", "yue": "剛果(共和國)" }, flag: "🇨🇬", code: "CG", dialCode: "242", minLength: 7, maxLength: 7, ), Country( name: "Congo, The Democratic Republic of the Congo", nameTranslations: { "sk": "Konžská demokratická republika", "se": "Kongo-Kinshasa", "pl": "Demokratyczna Republika Konga", "no": "Kongo-Kinshasa", "ja": "コンゴ民主共和国(キンシャサ)", "it": "Congo - Kinshasa", "zh": "刚果(金)", "nl": "Congo-Kinshasa", "de": "Kongo-Kinshasa", "fr": "Congo-Kinshasa", "es": "República Democrática del Congo", "en": "Congo - Kinshasa", "pt_BR": "República Democrática do Congo", "sr-Cyrl": "Демократска Република Конго", "sr-Latn": "Demokratska Republika Kongo", "zh_TW": "剛果民主共和國(金沙薩)", "tr": "Kongo Demokratik Cumhuriyeti", "ro": "Republica Democrată Congo", "ar": "جمهورية الكونغو الديمقراطية", "fa": "جمهوری دموکراتیک کنگو", "yue": "剛果(金)" }, flag: "🇨🇩", code: "CD", dialCode: "243", minLength: 9, maxLength: 9, ), Country( name: "Cook Islands", nameTranslations: { "sk": "Cookove ostrovy", "se": "Cook-sullot", "pl": "Wyspy Cooka", "no": "Cookøyene", "ja": "クック諸島", "it": "Isole Cook", "zh": "库克群岛", "nl": "Cookeilanden", "de": "Cookinseln", "fr": "Îles Cook", "es": "Islas Cook", "en": "Cook Islands", "pt_BR": "Ilhas Cook", "sr-Cyrl": "Кукова Острва", "sr-Latn": "Kukova Ostrva", "zh_TW": "庫克群島", "tr": "Cook Adaları", "ro": "Insulele Cook", "ar": "جزر كوك", "fa": "جزایر کوک", "yue": "庫克群島" }, flag: "🇨🇰", code: "CK", dialCode: "682", minLength: 5, maxLength: 5, ), Country( name: "Costa Rica", nameTranslations: { "sk": "Kostarika", "se": "Costa Rica", "pl": "Kostaryka", "no": "Costa Rica", "ja": "コスタリカ", "it": "Costa Rica", "zh": "哥斯达黎加", "nl": "Costa Rica", "de": "Costa Rica", "fr": "Costa Rica", "es": "Costa Rica", "en": "Costa Rica", "pt_BR": "Costa Rica", "sr-Cyrl": "Коста Рика", "sr-Latn": "Kosta Rika", "zh_TW": "哥斯大黎加", "tr": "Kosta Rika", "ro": "Costa Rica", "ar": "كوستاريكا", "fa": "کاستاریکا", "yue": "哥斯達黎加" }, flag: "🇨🇷", code: "CR", dialCode: "506", minLength: 8, maxLength: 8, ), Country( name: "Côte d'Ivoire", nameTranslations: { "sk": "Pobrežie Slonoviny", "se": "Elfenbenariddu", "pl": "Côte d'Ivoire", "no": "Elfenbenskysten", "ja": "コートジボワール", "it": "Costa d'Avorio", "zh": "科特迪瓦", "nl": "Ivoorkust", "de": "Côte d'Ivoire", "fr": "Côte d'Ivoire", "es": "Côte d'Ivoire", "en": "Côte d'Ivoire", "pt_BR": "Côte d'Ivoire", "sr-Cyrl": "Обала Слоноваче", "sr-Latn": "Obala Slonovače", "zh_TW": "象牙海岸", "tr": "Fildişi Kıyısı", "ro": "Coasta de fildeș", "ar": "ساحل العاج", "fa": "ساحل عاج", "yue": "科特迪瓦" }, flag: "🇨🇮", code: "CI", dialCode: "225", minLength: 10, maxLength: 10, ), Country( name: "Croatia", nameTranslations: { "sk": "Chorvátsko", "se": "Kroátia", "pl": "Chorwacja", "no": "Kroatia", "ja": "クロアチア", "it": "Croazia", "zh": "克罗地亚", "nl": "Kroatië", "de": "Kroatien", "fr": "Croatie", "es": "Croacia", "en": "Croatia", "pt_BR": "Croácia", "sr-Cyrl": "Хрватска", "sr-Latn": "Hrvatska", "zh_TW": "克羅埃西亞", "tr": "Hırvatistan", "ro": "Croația", "ar": "كرواتيا", "fa": "کرواسی", "yue": "克羅地亞" }, flag: "🇭🇷", code: "HR", dialCode: "385", minLength: 12, maxLength: 12, ), Country( name: "Cuba", nameTranslations: { "sk": "Kuba", "se": "Kuba", "pl": "Kuba", "no": "Cuba", "ja": "キューバ", "it": "Cuba", "zh": "古巴", "nl": "Cuba", "de": "Kuba", "fr": "Cuba", "es": "Cuba", "en": "Cuba", "pt_BR": "Cuba", "sr-Cyrl": "Куба", "sr-Latn": "Kuba", "zh_TW": "古巴", "tr": "Küba", "ro": "Cuba", "ar": "كوبا", "fa": "كوبا", "yue": "古巴" }, flag: "🇨🇺", code: "CU", dialCode: "53", minLength: 8, maxLength: 8, ), Country( name: "Cyprus", nameTranslations: { "sk": "Cyprus", "se": "Kypros", "pl": "Cypr", "no": "Kypros", "ja": "キプロス", "it": "Cipro", "zh": "塞浦路斯", "nl": "Cyprus", "de": "Zypern", "fr": "Chypre", "es": "Chipre", "en": "Cyprus", "pt_BR": "Chipre", "sr-Cyrl": "Кипар", "sr-Latn": "Kipar", "zh_TW": "塞普勒斯", "tr": "Kıbrıs", "ro": "Cipru", "ar": "قبرص", "fa": "قبرس", "yue": "塞浦路斯" }, flag: "🇨🇾", code: "CY", dialCode: "357", minLength: 8, maxLength: 8, ), Country( name: "Czech Republic", nameTranslations: { "sk": "Česko", "se": "Čeahkka", "pl": "Czechy", "no": "Tsjekkia", "ja": "チェコ", "it": "Cechia", "zh": "捷克", "nl": "Tsjechië", "de": "Tschechien", "fr": "Tchéquie", "es": "Chequia", "en": "Czechia", "pt_BR": "Czechia", "sr-Cyrl": "Чешка", "sr-Latn": "Češka", "zh_TW": "捷克", "tr": "Çek Cumhuriyeti", "ro": "Cehia", "ar": "جمهورية التشيك", "fa": "جمهوری چک", "yue": "捷克共和國" }, flag: "🇨🇿", code: "CZ", dialCode: "420", minLength: 9, maxLength: 9, ), Country( name: "Denmark", nameTranslations: { "sk": "Dánsko", "se": "Dánmárku", "pl": "Dania", "no": "Danmark", "ja": "デンマーク", "it": "Danimarca", "zh": "丹麦", "nl": "Denemarken", "de": "Dänemark", "fr": "Danemark", "es": "Dinamarca", "en": "Denmark", "pt_BR": "Dinamarca", "sr-Cyrl": "Данска", "sr-Latn": "Danska", "zh_TW": "丹麥", "tr": "Danimarka", "ro": "Danemarca", "ar": "الدنمارك", "fa": "دانمارک", "yue": "丹麥" }, flag: "🇩🇰", code: "DK", dialCode: "45", minLength: 8, maxLength: 8, ), Country( name: "Djibouti", nameTranslations: { "sk": "Džibutsko", "se": "Djibouti", "pl": "Dżibuti", "no": "Djibouti", "ja": "ジブチ", "it": "Gibuti", "zh": "吉布提", "nl": "Djibouti", "de": "Dschibuti", "fr": "Djibouti", "es": "Yibuti", "en": "Djibouti", "pt_BR": "Djibouti", "sr-Cyrl": "Џибути", "sr-Latn": "Džibuti", "zh_TW": "吉布地", "tr": "Cibuti", "ro": "Djibouti", "ar": "جيبوتي", "fa": "جیبوتی", "yue": "吉布提" }, flag: "🇩🇯", code: "DJ", dialCode: "253", minLength: 6, maxLength: 6, ), Country( name: "Dominica", nameTranslations: { "sk": "Dominika", "se": "Dominica", "pl": "Dominika", "no": "Dominica", "ja": "ドミニカ国", "it": "Dominica", "zh": "多米尼克", "nl": "Dominica", "de": "Dominica", "fr": "Dominique", "es": "Dominica", "en": "Dominica", "pt_BR": "Dominica", "sr-Cyrl": "Доминика", "sr-Latn": "Dominika", "zh_TW": "多明尼加", "tr": "Dominika", "ro": "Dominica", "ar": "دومينيكا", "fa": "دومينيكا", "yue": "多米尼加" }, flag: "🇩🇲", code: "DM", dialCode: "1767", minLength: 7, maxLength: 7, ), Country( name: "Dominican Republic", nameTranslations: { "sk": "Dominikánska republika", "se": "Dominikána dásseváldi", "pl": "Dominikana", "no": "Den dominikanske republikk", "ja": "ドミニカ共和国", "it": "Repubblica Dominicana", "zh": "多米尼加共和国", "nl": "Dominicaanse Republiek", "de": "Dominikanische Republik", "fr": "République dominicaine", "es": "República Dominicana", "en": "Dominican Republic", "pt_BR": "República Dominicana", "sr-Cyrl": "Доминиканска Република", "sr-Latn": "Dominikanska Republika", "zh_TW": "多明尼加共和國", "tr": "Dominik Cumhuriyeti", "ro": "Republica Dominicană", "ar": "جمهورية الدومينيكان", "fa": "جمهوری دومنیکن", "yue": "多明尼加共和國" }, flag: "🇩🇴", code: "DO", dialCode: "1", minLength: 10, maxLength: 10, ), Country( name: "Ecuador", nameTranslations: { "sk": "Ekvádor", "se": "Ecuador", "pl": "Ekwador", "no": "Ecuador", "ja": "エクアドル", "it": "Ecuador", "zh": "厄瓜多尔", "nl": "Ecuador", "de": "Ecuador", "fr": "Équateur", "es": "Ecuador", "en": "Ecuador", "pt_BR": "Equador", "sr-Cyrl": "Еквадор", "sr-Latn": "Ekvador", "zh_TW": "厄瓜多", "tr": "Ekvador", "ro": "Ecuador", "ar": "الإكوادور", "fa": "اكوادور", "yue": "厄瓜多爾" }, flag: "🇪🇨", code: "EC", dialCode: "593", minLength: 8, maxLength: 9, ), Country( name: "Egypt", nameTranslations: { "sk": "Egypt", "se": "Egypt", "pl": "Egipt", "no": "Egypt", "ja": "エジプト", "it": "Egitto", "zh": "埃及", "nl": "Egypt", "de": "Ägypt", "fr": "Égypte", "es": "Egipt", "en": "Egypt", "pt_BR": "Egito", "sr-Cyrl": "Египат", "sr-Latn": "Egipat", "zh_TW": "埃及", "tr": "Mısır", "ro": "Egipt", "ar": "مصر", "fa": "مصر", "yue": "埃及" }, flag: "🇪🇬", code: "EG", dialCode: "2", minLength: 11, maxLength: 11, ), Country( name: "El Salvador", nameTranslations: { "sk": "Salvádor", "se": "El Salvador", "pl": "Salwador", "no": "El Salvador", "ja": "エルサルバドル", "it": "El Salvador", "zh": "萨尔瓦多", "nl": "El Salvador", "de": "El Salvador", "fr": "Salvador", "es": "El Salvador", "en": "El Salvador", "pt_BR": "El Salvador", "sr-Cyrl": "Салвадор", "sr-Latn": "Salvador", "zh_TW": "薩爾瓦多", "tr": "El Salvador", "ro": "Salvador", "ar": "السلفادور", "fa": "ال سالوادور", "yue": "薩爾瓦多" }, flag: "🇸🇻", code: "SV", dialCode: "503", minLength: 11, maxLength: 11, ), Country( name: "Equatorial Guinea", nameTranslations: { "sk": "Rovníková Guinea", "se": "Ekvatoriála Guinea", "pl": "Gwinea Równikowa", "no": "Ekvatorial-Guinea", "ja": "赤道ギニア", "it": "Guinea Equatoriale", "zh": "赤道几内亚", "nl": "Equatoriaal-Guinea", "de": "Äquatorialguinea", "fr": "Guinée équatoriale", "es": "Guinea Ecuatorial", "en": "Equatorial Guinea", "pt_BR": "Guiné Equatorial", "sr-Cyrl": "Екваторијална Гвинеја", "sr-Latn": "Ekvatorijalna Gvineja", "zh_TW": "赤道幾內亞", "tr": "Ekvator Ginesi", "ro": "Guineea Ecuatorială", "ar": "غينيا الاستوائية", "fa": "گینه استوایی", "yue": "赤道幾內亞" }, flag: "🇬🇶", code: "GQ", dialCode: "240", minLength: 6, maxLength: 6, ), Country( name: "Eritrea", nameTranslations: { "sk": "Eritrea", "se": "Eritrea", "pl": "Erytrea", "no": "Eritrea", "ja": "エリトリア", "it": "Eritrea", "zh": "厄立特里亚", "nl": "Eritrea", "de": "Eritrea", "fr": "Érythrée", "es": "Eritrea", "en": "Eritrea", "pt_BR": "Eritreia", "sr-Cyrl": "Еритреја", "sr-Latn": "Eritreja", "zh_TW": "厄立特裡亞", "tr": "Eritre", "ro": "Eritreea", "ar": "إريتريا", "fa": "اریتره", "yue": "厄立特里亞" }, flag: "🇪🇷", code: "ER", dialCode: "291", minLength: 7, maxLength: 7, ), Country( name: "Estonia", nameTranslations: { "sk": "Estónsko", "se": "Estlánda", "pl": "Estonia", "no": "Estland", "ja": "エストニア", "it": "Estonia", "zh": "爱沙尼亚", "nl": "Estland", "de": "Estland", "fr": "Estonie", "es": "Estonia", "en": "Estonia", "pt_BR": "Estônia", "sr-Cyrl": "Естонија", "sr-Latn": "Estonija", "zh_TW": "愛沙尼亞", "tr": "Estonya", "ro": "Estonia", "ar": "إستونيا", "fa": "استونی", "yue": "愛沙尼亞" }, flag: "🇪🇪", code: "EE", dialCode: "372", minLength: 10, maxLength: 10, ), Country( name: "Ethiopia", nameTranslations: { "sk": "Etiópia", "se": "Etiopia", "pl": "Etiopia", "no": "Etiopia", "ja": "エチオピア", "it": "Etiopia", "zh": "埃塞俄比亚", "nl": "Ethiopië", "de": "Äthiopien", "fr": "Éthiopie", "es": "Etiopía", "en": "Ethiopia", "pt_BR": "Etiópia", "sr-Cyrl": "Етиопија", "sr-Latn": "Etiopija", "zh_TW": "伊索比亞", "tr": "Etiyopya", "ro": "Etiopia", "ar": "إثيوبيا", "fa": "اتیوپی", "yue": "埃塞俄比亞" }, flag: "🇪🇹", code: "ET", dialCode: "251", minLength: 9, maxLength: 9, ), Country( name: "Falkland Islands (Malvinas)", nameTranslations: { "sk": "Falklandy", "se": "Falklandsullot", "pl": "Falklandy", "no": "Falklandsøyene", "ja": "フォークランド諸島", "it": "Isole Falkland", "zh": "福克兰群岛", "nl": "Falklandeilanden", "de": "Falklandinseln", "fr": "Îles Malouines", "es": "Islas Malvinas", "en": "Falkland Islands", "pt_BR": "Ilhas Falkland", "sr-Cyrl": "Фокландска Острва", "sr-Latn": "Foklandska Ostrva", "zh_TW": "福克蘭群島", "tr": "Falkland Adaları", "ro": "Insulele Falklands", "ar": "جزر فوكلاند", "fa": "جزایر فالکلند", "yue": "福克蘭群島(馬爾維納斯群島)" }, flag: "🇫🇰", code: "FK", dialCode: "500", minLength: 5, maxLength: 5, ), Country( name: "Faroe Islands", nameTranslations: { "sk": "Faerské ostrovy", "se": "Fearsullot", "pl": "Wyspy Owcze", "no": "Færøyene", "ja": "フェロー諸島", "it": "Isole Fær Øer", "zh": "法罗群岛", "nl": "Faeröer", "de": "Färöer", "fr": "Îles Féroé", "es": "Islas Feroe", "en": "Faroe Islands", "pt_BR": "ilhas Faroe", "sr-Cyrl": "Фарска Острва", "sr-Latn": "Farska Ostrva", "zh_TW": "法羅群島", "tr": "Faroe Adaları", "ro": "Insulele Feroe", "ar": "جزر فارو", "fa": "جزایر فارو", "yue": "法羅群島" }, flag: "🇫🇴", code: "FO", dialCode: "298", minLength: 6, maxLength: 6, ), Country( name: "Fiji", nameTranslations: { "sk": "Fidži", "se": "Fijisullot", "pl": "Fidżi", "no": "Fiji", "ja": "フィジー", "it": "Figi", "zh": "斐济", "nl": "Fiji", "de": "Fidschi", "fr": "Fidji", "es": "Fiyi", "en": "Fiji", "pt_BR": "Fiji", "sr-Cyrl": "Фиџи", "sr-Latn": "Fidži", "zh_TW": "斐濟", "tr": "Fiji", "ro": "Fiji", "ar": "فيجي", "fa": "فيجي", "yue": "斐濟" }, flag: "🇫🇯", code: "FJ", dialCode: "679", minLength: 7, maxLength: 7, ), Country( name: "Finland", nameTranslations: { "sk": "Fínsko", "se": "Suopma", "pl": "Finlandia", "no": "Finland", "ja": "フィンランド", "it": "Finlandia", "zh": "芬兰", "nl": "Finland", "de": "Finnland", "fr": "Finlande", "es": "Finlandia", "en": "Finland", "pt_BR": "Finlândia", "sr-Cyrl": "Финска", "sr-Latn": "Finska", "zh_TW": "芬蘭", "tr": "Finlandiya", "ro": "Finlanda", "ar": "فنلندا", "fa": "فنلاند", "yue": "芬蘭" }, flag: "🇫🇮", code: "FI", dialCode: "358", minLength: 12, maxLength: 12, ), Country( name: "France", nameTranslations: { "sk": "Francúzsko", "se": "Frankriika", "pl": "Francja", "no": "Frankrike", "ja": "フランス", "it": "Francia", "zh": "法国", "nl": "Frankrijk", "de": "Frankreich", "fr": "France", "es": "Francia", "en": "France", "pt_BR": "França", "sr-Cyrl": "Француска", "sr-Latn": "Francuska", "zh_TW": "法國", "tr": "Fransa", "ro": "Franța", "ar": "فرنسا", "fa": "فرانسه", "yue": "法國" }, flag: "🇫🇷", code: "FR", dialCode: "33", minLength: 9, maxLength: 9, ), Country( name: "French Guiana", nameTranslations: { "sk": "Francúzska Guyana", "se": "Frankriikka Guayana", "pl": "Gujana Francuska", "no": "Fransk Guyana", "ja": "仏領ギアナ", "it": "Guyana francese", "zh": "法属圭亚那", "nl": "Frans-Guyana", "de": "Französisch-Guayana", "fr": "Guyane française", "es": "Guayana Francesa", "en": "French Guiana", "pt_BR": "Guiana Francesa", "sr-Cyrl": "Француска Гвајана", "sr-Latn": "Francuska Gvajana", "zh_TW": "法屬蓋亞那", "tr": "Fransız Guyanası", "ro": "Guiana Franceză", "ar": "غويانا الفرنسية", "fa": "گویان فرانسه", "yue": "法屬圭亞那" }, flag: "🇬🇫", code: "GF", dialCode: "594", minLength: 15, maxLength: 15, ), Country( name: "French Polynesia", nameTranslations: { "sk": "Francúzska Polynézia", "se": "Frankriikka Polynesia", "pl": "Polinezja Francuska", "no": "Fransk Polynesia", "ja": "仏領ポリネシア", "it": "Polinesia francese", "zh": "法属波利尼西亚", "nl": "Frans-Polynesië", "de": "Französisch-Polynesien", "fr": "Polynésie française", "es": "Polinesia Francesa", "en": "French Polynesia", "pt_BR": "Polinésia Francesa", "sr-Cyrl": "Француска Полинезија", "sr-Latn": "Francuska Polinezija", "zh_TW": "法屬玻里尼西亞", "tr": "Fransız Polinezyası", "ro": "Polinezia Franceză", "ar": "بولينزيا الفرنسية", "fa": "پلی‌نزی فرانسه", "yue": "法屬波利尼西亞" }, flag: "🇵🇫", code: "PF", dialCode: "689", minLength: 6, maxLength: 6, ), Country( name: "French Southern Territories", nameTranslations: { "sk": "Francúzske južné a antarktické územia", "se": "French Southern Territories", "pl": "Francuskie Terytoria Południowe i Antarktyczne", "no": "De franske sørterritorier", "ja": "仏領極南諸島", "it": "Terre australi francesi", "zh": "法属南部领地", "nl": "Franse Gebieden in de zuidelijke Indische Oceaan", "de": "Französische Süd- und Antarktisgebiete", "fr": "Terres australes françaises", "es": "Territorios Australes Franceses", "en": "French Southern Territories", "pt_BR": "Territórios Franceses do Sul", "sr-Cyrl": "Француске јужне и антарктичке земље", "sr-Latn": "Francuske južne i antarktičke zemlje", "zh_TW": "法屬南部屬地", "tr": "Fransız Güney ve Antarktika Toprakları", "ro": "Teritoriile australe și antarctice franceze", "ar": "أراض فرنسية جنوبية وأنتارتيكية", "fa": "سرزمین‌های جنوبی فرانسه", "yue": "法國南部領土" }, flag: "🇹🇫", code: "TF", dialCode: "262", minLength: 15, maxLength: 15, ), Country( name: "Gabon", nameTranslations: { "sk": "Gabon", "se": "Gabon", "pl": "Gabon", "no": "Gabon", "ja": "ガボン", "it": "Gabon", "zh": "加蓬", "nl": "Gabon", "de": "Gabun", "fr": "Gabon", "es": "Gabón", "en": "Gabon", "pt_BR": "Gabão", "sr-Cyrl": "Габон", "sr-Latn": "Gabon", "zh_TW": "加彭", "tr": "Gabon", "ro": "Gabon", "ar": "الغابون", "fa": "گابن", "yue": "加蓬" }, flag: "🇬🇦", code: "GA", dialCode: "241", minLength: 9, maxLength: 9, ), Country( name: "Gambia", nameTranslations: { "sk": "Gambia", "se": "Gámbia", "pl": "Gambia", "no": "Gambia", "ja": "ガンビア", "it": "Gambia", "zh": "冈比亚", "nl": "Gambia", "de": "Gambia", "fr": "Gambie", "es": "Gambia", "en": "Gambia", "pt_BR": "Gâmbia", "sr-Cyrl": "Гамбија", "sr-Latn": "Gambija", "zh_TW": "岡比亞", "tr": "Gambiya", "ro": "Gambia", "ar": "غامبيا", "fa": "گامبیا", "yue": "岡比亞" }, flag: "🇬🇲", code: "GM", dialCode: "220", minLength: 7, maxLength: 7, ), Country( name: "Georgia", nameTranslations: { "sk": "Gruzínsko", "se": "Georgia", "pl": "Gruzja", "no": "Georgia", "ja": "ジョージア", "it": "Georgia", "zh": "格鲁吉亚", "nl": "Georgië", "de": "Georgien", "fr": "Géorgie", "es": "Georgia", "en": "Georgia", "pt_BR": "Georgia", "sr-Cyrl": "Грузија", "sr-Latn": "Gruzija", "zh_TW": "喬治亞", "tr": "Gürcistan", "ro": "Georgia", "ar": "جورجيا", "fa": "گرجستان", "yue": "格魯吉亞" }, flag: "🇬🇪", code: "GE", dialCode: "995", minLength: 8, maxLength: 9, ), Country( name: "Germany", nameTranslations: { "sk": "Nemecko", "se": "Duiska", "pl": "Niemcy", "no": "Tyskland", "ja": "ドイツ", "it": "Germania", "zh": "德国", "nl": "Duitsland", "de": "Deutschland", "fr": "Allemagne", "es": "Alemania", "en": "Germany", "pt_BR": "Alemanha", "sr-Cyrl": "Немачка", "sr-Latn": "Nemačka", "zh_TW": "德國", "tr": "Almanya", "ro": "Germania", "ar": "ألمانيا", "fa": "آلمان", "yue": "德國" }, flag: "🇩🇪", code: "DE", dialCode: "49", minLength: 9, maxLength: 13, ), Country( name: "Ghana", nameTranslations: { "sk": "Ghana", "se": "Ghana", "pl": "Ghana", "no": "Ghana", "ja": "ガーナ", "it": "Ghana", "zh": "加纳", "nl": "Ghana", "de": "Ghana", "fr": "Ghana", "es": "Ghana", "en": "Ghana", "pt_BR": "Gana", "sr-Cyrl": "Гана", "sr-Latn": "Gana", "zh_TW": "迦納", "tr": "Gana", "ro": "Ghana", "ar": "غانا", "fa": "غنا", "yue": "加納" }, flag: "🇬🇭", code: "GH", dialCode: "233", minLength: 9, maxLength: 9, ), Country( name: "Gibraltar", nameTranslations: { "sk": "Gibraltár", "se": "Gibraltar", "pl": "Gibraltar", "no": "Gibraltar", "ja": "ジブラルタル", "it": "Gibilterra", "zh": "直布罗陀", "nl": "Gibraltar", "de": "Gibraltar", "fr": "Gibraltar", "es": "Gibraltar", "en": "Gibraltar", "pt_BR": "Gibraltar", "sr-Cyrl": "Гибралтар", "sr-Latn": "Gibraltar", "zh_TW": "直布羅陀", "tr": "Cebelitarık", "ro": "Gibraltar", "ar": "جبل طارق", "fa": "جبل الطارق", "yue": "直布羅陀" }, flag: "🇬🇮", code: "GI", dialCode: "350", minLength: 8, maxLength: 8, ), Country( name: "Greece", nameTranslations: { "sk": "Grécko", "se": "Greika", "pl": "Grecja", "no": "Hellas", "ja": "ギリシャ", "it": "Grecia", "zh": "希腊", "nl": "Griekenland", "de": "Griechenland", "fr": "Grèce", "es": "Grecia", "en": "Greece", "pt_BR": "Grécia", "sr-Cyrl": "Грчка", "sr-Latn": "Grčka", "zh_TW": "希臘", "tr": "Yunanistan", "ro": "Grecia", "ar": "اليونان", "fa": "یونان", "yue": "希臘" }, flag: "🇬🇷", code: "GR", dialCode: "30", minLength: 10, maxLength: 10, ), Country( name: "Greenland", nameTranslations: { "sk": "Grónsko", "se": "Kalaallit Nunaat", "pl": "Grenlandia", "no": "Grønland", "ja": "グリーンランド", "it": "Groenlandia", "zh": "格陵兰", "nl": "Groenland", "de": "Grönland", "fr": "Groenland", "es": "Groenlandia", "en": "Greenland", "pt_BR": "Groenlândia", "sr-Cyrl": "Гренланд", "sr-Latn": "Grenland", "zh_TW": "格陵蘭", "tr": "Grönland", "ro": "Groenlanda", "ar": "جرينلاند", "fa": "گرینلند", "yue": "格陵蘭" }, flag: "🇬🇱", code: "GL", dialCode: "299", minLength: 6, maxLength: 6, ), Country( name: "Grenada", nameTranslations: { "sk": "Grenada", "se": "Grenada", "pl": "Grenada", "no": "Grenada", "ja": "グレナダ", "it": "Grenada", "zh": "格林纳达", "nl": "Grenada", "de": "Grenada", "fr": "Grenade", "es": "Granada", "en": "Grenada", "pt_BR": "Grenada", "sr-Cyrl": "Гренада", "sr-Latn": "Grenada", "zh_TW": "格林納達", "tr": "Grenada", "ro": "Grenada", "ar": "غرينادا", "fa": "گرنادا", "yue": "格林納達" }, flag: "🇬🇩", code: "GD", dialCode: "1473", minLength: 7, maxLength: 7, ), Country( name: "Guadeloupe", nameTranslations: { "sk": "Guadeloupe", "se": "Guadeloupe", "pl": "Gwadelupa", "no": "Guadeloupe", "ja": "グアドループ", "it": "Guadalupa", "zh": "瓜德罗普", "nl": "Guadeloupe", "de": "Guadeloupe", "fr": "Guadeloupe", "es": "Guadalupe", "en": "Guadeloupe", "pt_BR": "Guadalupe", "sr-Cyrl": "Гваделуп", "sr-Latn": "Gvadelup", "zh_TW": "瓜地洛普", "tr": "Guadeloupe", "ro": "Guadelupa", "ar": "غوادلوب", "fa": "گوادلوپ", "yue": "瓜德罗普" }, flag: "🇬🇵", code: "GP", dialCode: "590", minLength: 15, maxLength: 15, ), Country( name: "Guam", nameTranslations: { "sk": "Guam", "se": "Guam", "pl": "Guam", "no": "Guam", "ja": "グアム", "it": "Guam", "zh": "关岛", "nl": "Guam", "de": "Guam", "fr": "Guam", "es": "Guam", "en": "Guam", "pt_BR": "Guam", "sr-Cyrl": "Гвам", "sr-Latn": "Gvam", "zh_TW": "關島", "tr": "Guam", "ro": "Guam", "ar": "غوام", "fa": "گوام", "yue": "關島" }, flag: "🇬🇺", code: "GU", dialCode: "1671", minLength: 7, maxLength: 7, ), Country( name: "Guatemala", nameTranslations: { "sk": "Guatemala", "se": "Guatemala", "pl": "Gwatemala", "no": "Guatemala", "ja": "グアテマラ", "it": "Guatemala", "zh": "危地马拉", "nl": "Guatemala", "de": "Guatemala", "fr": "Guatemala", "es": "Guatemala", "en": "Guatemala", "pt_BR": "Guatemala", "sr-Cyrl": "Гватемала", "sr-Latn": "Gvatemala", "zh_TW": "瓜地馬拉", "tr": "Guatemala", "ro": "Guatemala", "ar": "غواتيمالا", "fa": "گواتمالا", "yue": "危地馬拉" }, flag: "🇬🇹", code: "GT", dialCode: "502", minLength: 8, maxLength: 8, ), Country( name: "Guernsey", nameTranslations: { "sk": "Guernsey", "se": "Guernsey", "pl": "Guernsey", "no": "Guernsey", "ja": "ガーンジー", "it": "Guernsey", "zh": "根西岛", "nl": "Guernsey", "de": "Guernsey", "fr": "Guernesey", "es": "Guernsey", "en": "Guernsey", "pt_BR": "Guernsey", "sr-Cyrl": "Гернзи", "sr-Latn": "Gernzi", "zh_TW": "根息島", "tr": "Guernsey", "ro": "Guernsey", "ar": "غيرنزي", "fa": "گرنزی", "yue": "格恩西島" }, flag: "🇬🇬", code: "GG", dialCode: "44", minLength: 6, maxLength: 6, ), Country( name: "Guinea", nameTranslations: { "sk": "Guinea", "se": "Guinea", "pl": "Gwinea", "no": "Guinea", "ja": "ギニア", "it": "Guinea", "zh": "几内亚", "nl": "Guinee", "de": "Guinea", "fr": "Guinée", "es": "Guinea", "en": "Guinea", "pt_BR": "Guiné", "sr-Cyrl": "Гвинеја", "sr-Latn": "Gvineja", "zh_TW": "幾內亞", "tr": "Gine", "ro": "Guinea", "ar": "غينيا", "fa": "گینه", "yue": "幾內亞" }, flag: "🇬🇳", code: "GN", dialCode: "224", minLength: 8, maxLength: 9, ), Country( name: "Guinea-Bissau", nameTranslations: { "sk": "Guinea-Bissau", "se": "Guinea-Bissau", "pl": "Gwinea Bissau", "no": "Guinea-Bissau", "ja": "ギニアビサウ", "it": "Guinea-Bissau", "zh": "几内亚比绍", "nl": "Guinee-Bissau", "de": "Guinea-Bissau", "fr": "Guinée-Bissau", "es": "Guinea-Bisáu", "en": "Guinea-Bissau", "pt_BR": "Guiné-bissau", "sr-Cyrl": "Гвинеја Бисао", "sr-Latn": "Gvineja Bisao", "zh_TW": "幾內亞比索", "tr": "Gine-Bissau", "ro": "Guineea-Bissau", "ar": "غينيا بيساو", "fa": "گینه بیسائو", "yue": "幾內亞比紹" }, flag: "🇬🇼", code: "GW", dialCode: "245", minLength: 7, maxLength: 7, ), Country( name: "Guyana", nameTranslations: { "sk": "Guyana", "se": "Guyana", "pl": "Gujana", "no": "Guyana", "ja": "ガイアナ", "it": "Guyana", "zh": "圭亚那", "nl": "Guyana", "de": "Guyana", "fr": "Guyana", "es": "Guyana", "en": "Guyana", "pt_BR": "Guiana", "sr-Cyrl": "Гвајана", "sr-Latn": "Gvajana", "zh_TW": "蓋亞那", "tr": "Guyana", "ro": "Guyana", "ar": "غيانا", "fa": "گویان", "yue": "圭亞那" }, flag: "🇬🇾", code: "GY", dialCode: "592", minLength: 7, maxLength: 7, ), Country( name: "Haiti", nameTranslations: { "sk": "Haiti", "se": "Haiti", "pl": "Haiti", "no": "Haiti", "ja": "ハイチ", "it": "Haiti", "zh": "海地", "nl": "Haïti", "de": "Haiti", "fr": "Haïti", "es": "Haití", "en": "Haiti", "pt_BR": "Haiti", "sr-Cyrl": "Хаити", "sr-Latn": "Haiti", "zh_TW": "海地", "tr": "Haiti", "ro": "Haiti", "ar": "هايتي", "fa": "هائیتی", "yue": "海地" }, flag: "🇭🇹", code: "HT", dialCode: "509", minLength: 8, maxLength: 8, ), Country( name: "Heard Island and Mcdonald Islands", nameTranslations: { "sk": "Heardov ostrov a Macdonaldove ostrovy", "se": "Heard- ja McDonald-sullot", "pl": "Wyspy Heard i McDonalda", "no": "Heard- og McDonaldøyene", "ja": "ハード島・マクドナルド諸島", "it": "Isole Heard e McDonald", "zh": "赫德岛和麦克唐纳群岛", "nl": "Heard en McDonaldeilanden", "de": "Heard und McDonaldinseln", "fr": "Îles Heard et McDonald", "es": "Islas Heard y McDonald", "en": "Heard & McDonald Islands", "pt_BR": "Ilhas Heard e McDonald", "sr-Cyrl": "Острва Херд и Макдоналд", "sr-Latn": "Ostrva Herd i Makdonald", "zh_TW": "赫德暨麥當勞群島", "tr": "Heard Adası ve McDonald Adaları", "ro": "Insula Heard și Insulele McDonald", "ar": "جزيرة هيرد وجزر ماكدونالد", "fa": "جزیره هرد و جزایر مک‌دونالد", "yue": "赫德岛同麦克唐纳群岛" }, flag: "🇭🇲", code: "HM", dialCode: "672", minLength: 15, maxLength: 15, ), Country( name: "Holy See (Vatican City State)", nameTranslations: { "sk": "Vatikán", "se": "Vatikána", "pl": "Watykan", "no": "Vatikanstaten", "ja": "バチカン市国", "it": "Città del Vaticano", "zh": "梵蒂冈", "nl": "Vaticaanstad", "de": "Vatikanstadt", "fr": "État de la Cité du Vatican", "es": "Ciudad del Vaticano", "en": "Vatican City", "pt_BR": "Cidade do Vaticano", "sr-Cyrl": "Ватикан", "sr-Latn": "Vatikan", "zh_TW": "梵蒂岡", "tr": "Vatikan", "ro": "Vatican", "ar": "الفاتيكان", "fa": "واتیکان", "yue": "梵蒂岡城國" }, flag: "🇻🇦", code: "VA", dialCode: "379", minLength: 10, maxLength: 10, ), Country( name: "Honduras", nameTranslations: { "sk": "Honduras", "se": "Honduras", "pl": "Honduras", "no": "Honduras", "ja": "ホンジュラス", "it": "Honduras", "zh": "洪都拉斯", "nl": "Honduras", "de": "Honduras", "fr": "Honduras", "es": "Honduras", "en": "Honduras", "pt_BR": "Honduras", "sr-Cyrl": "Хондурас", "sr-Latn": "Honduras", "zh_TW": "宏都拉斯", "tr": "Honduras", "ro": "Honduras", "ar": "هندوراس", "fa": "هندوراس", "yue": "洪都拉斯" }, flag: "🇭🇳", code: "HN", dialCode: "504", minLength: 8, maxLength: 8, ), Country( name: "Hong Kong", nameTranslations: { "sk": "Hongkong – OAO Číny", "se": "Hongkong", "pl": "SRA Hongkong (Chiny)", "no": "Hongkong S.A.R. Kina", "ja": "中華人民共和国香港特別行政区", "it": "RAS di Hong Kong", "zh": "中国香港特别行政区", "nl": "Hongkong SAR van China", "de": "Sonderverwaltungsregion Hongkong", "fr": "R.A.S. chinoise de Hong Kong", "es": "RAE de Hong Kong (China)", "en": "Hong Kong SAR China", "pt_BR": "RAE de Hong Kong China", "sr-Cyrl": "Хонг Конг", "sr-Latn": "Hong Kong", "zh_TW": "香港", "tr": "Hong Kong", "ro": "Hong Kong", "ar": "هونغ كونغ", "fa": "هنگ کنگ", "yue": "香港" }, flag: "🇭🇰", code: "HK", dialCode: "852", minLength: 8, maxLength: 8, ), Country( name: "Hungary", nameTranslations: { "sk": "Maďarsko", "se": "Ungár", "pl": "Węgry", "no": "Ungarn", "ja": "ハンガリー", "it": "Ungheria", "zh": "匈牙利", "nl": "Hongarije", "de": "Ungarn", "fr": "Hongrie", "es": "Hungría", "en": "Hungary", "pt_BR": "Hungria", "sr-Cyrl": "Мађарска", "sr-Latn": "Mađarska", "zh_TW": "匈牙利", "tr": "Macaristan", "ro": "Ungaria", "ar": "المجر", "fa": "مجارستان", "yue": "匈牙利" }, flag: "🇭🇺", code: "HU", dialCode: "36", minLength: 9, maxLength: 9, ), Country( name: "Iceland", nameTranslations: { "sk": "Island", "se": "Islánda", "pl": "Islandia", "no": "Island", "ja": "アイスランド", "it": "Islanda", "zh": "冰岛", "nl": "IJsland", "de": "Island", "fr": "Islande", "es": "Islandia", "en": "Iceland", "pt_BR": "Islândia", "sr-Cyrl": "Исланд", "sr-Latn": "Island", "zh_TW": "冰島", "tr": "İzlanda", "ro": "Islanda", "ar": "آيسلندا", "fa": "ایسلند", "yue": "冰島" }, flag: "🇮🇸", code: "IS", dialCode: "354", minLength: 7, maxLength: 9, ), Country( name: "India", nameTranslations: { "sk": "India", "se": "India", "pl": "Indie", "no": "India", "ja": "インド", "it": "India", "zh": "印度", "nl": "India", "de": "Indien", "fr": "Inde", "es": "India", "en": "India", "pt_BR": "Índia", "sr-Cyrl": "Индија", "sr-Latn": "Indija", "zh_TW": "印度", "tr": "Hindistan", "ro": "India", "ar": "الهند", "fa": "هند", "yue": "印度" }, flag: "🇮🇳", code: "IN", dialCode: "91", minLength: 10, maxLength: 10, ), Country( name: "Indonesia", nameTranslations: { "sk": "Indonézia", "se": "Indonesia", "pl": "Indonezja", "no": "Indonesia", "ja": "インドネシア", "it": "Indonesia", "zh": "印度尼西亚", "nl": "Indonesië", "de": "Indonesien", "fr": "Indonésie", "es": "Indonesia", "en": "Indonesia", "pt_BR": "Indonésia", "sr-Cyrl": "Индонезија", "sr-Latn": "Indonezija", "zh_TW": "印尼", "tr": "Endonezya", "ro": "Indonezia", "ar": "إندونيسيا", "fa": "اندونزی", "yue": "印尼" }, flag: "🇮🇩", code: "ID", dialCode: "62", minLength: 10, maxLength: 13, ), Country( name: "Iran, Islamic Republic of Persian Gulf", nameTranslations: { "sk": "Irán", "se": "Iran", "pl": "Iran", "no": "Iran", "ja": "イラン", "it": "Iran", "zh": "伊朗", "nl": "Iran", "de": "Iran", "fr": "Iran", "es": "Irán", "en": "Iran", "pt_BR": "Irã", "sr-Cyrl": "Иран", "sr-Latn": "Iran", "zh_TW": "伊朗", "tr": "İran", "ro": "Iran", "ar": "إيران", "fa": "ایران", "yue": "伊朗" }, flag: "🇮🇷", code: "IR", dialCode: "98", minLength: 10, maxLength: 10, ), Country( name: "Iraq", nameTranslations: { "sk": "Irak", "se": "Irak", "pl": "Irak", "no": "Irak", "ja": "イラク", "it": "Iraq", "zh": "伊拉克", "nl": "Irak", "de": "Irak", "fr": "Irak", "es": "Irak", "en": "Iraq", "pt_BR": "Iraque", "sr-Cyrl": "Ирак", "sr-Latn": "Irak", "zh_TW": "伊拉克", "tr": "Irak", "ro": "Irak", "ar": "العراق", "fa": "عراق", "yue": "伊拉克" }, flag: "🇮🇶", code: "IQ", dialCode: "964", minLength: 10, maxLength: 10, ), Country( name: "Ireland", nameTranslations: { "sk": "Írsko", "se": "Irlánda", "pl": "Irlandia", "no": "Irland", "ja": "アイルランド", "it": "Irlanda", "zh": "爱尔兰", "nl": "Ierland", "de": "Irland", "fr": "Irlande", "es": "Irlanda", "en": "Ireland", "pt_BR": "Irlanda", "sr-Cyrl": "Ирска", "sr-Latn": "Irska", "zh_TW": "愛爾蘭", "tr": "İrlanda", "ro": "Irlanda", "ar": "أيرلندا", "fa": "ایرلند", "yue": "愛爾蘭" }, flag: "🇮🇪", code: "IE", dialCode: "353", minLength: 7, maxLength: 9, ), Country( name: "Isle of Man", nameTranslations: { "sk": "Ostrov Man", "se": "Mann-sullot", "pl": "Wyspa Man", "no": "Man", "ja": "マン島", "it": "Isola di Man", "zh": "马恩岛", "nl": "Isle of Man", "de": "Isle of Man", "fr": "Île de Man", "es": "Isla de Man", "en": "Isle of Man", "pt_BR": "Ilha de Man", "sr-Cyrl": "Острво Мен", "sr-Latn": "Ostrvo Men", "zh_TW": "曼島", "tr": "Man Adası", "ro": "Insula Man", "ar": "جزيرة مان", "fa": "جزیره مان", "yue": "马伊岛" }, flag: "🇮🇲", code: "IM", dialCode: "44", minLength: 6, maxLength: 6, ), Country( name: "Israel", nameTranslations: { "sk": "Izrael", "se": "Israel", "pl": "Izrael", "no": "Israel", "ja": "イスラエル", "it": "Israele", "zh": "以色列", "nl": "Israël", "de": "Israel", "fr": "Israël", "es": "Israel", "en": "Israel", "pt_BR": "Israel", "sr-Cyrl": "Израел", "sr-Latn": "Izrael", "zh_TW": "以色列", "tr": "İsrail", "ro": "Israel", "ar": "إسرائيل", "fa": "إسرائيل", "yue": "以色列" }, flag: "🇮🇱", code: "IL", dialCode: "972", minLength: 9, maxLength: 9, ), Country( name: "Campione d'Italia", nameTranslations: { "sk": "Taliansko", "se": "Itália", "pl": "Włochy", "no": "Italia", "ja": "イタリア", "it": "Italia", "zh": "意大利", "nl": "Italië", "de": "Italien", "fr": "Italie", "es": "Italia", "en": "Italy", "pt_BR": "Itália", "sr-Cyrl": "Италија", "sr-Latn": "Italija", "zh_TW": "義大利", "tr": "İtalya", "ro": "Italia", "ar": "إيطاليا", "fa": "ایتالیا", "yue": "意大利" }, flag: "🇮🇹", code: "IT", dialCode: "39", minLength: 9, maxLength: 10, ), Country( name: "Jamaica", nameTranslations: { "sk": "Jamajka", "se": "Jamaica", "pl": "Jamajka", "no": "Jamaica", "ja": "ジャマイカ", "it": "Giamaica", "zh": "牙买加", "nl": "Jamaica", "de": "Jamaika", "fr": "Jamaïque", "es": "Jamaica", "en": "Jamaica", "pt_BR": "Jamaica", "sr-Cyrl": "Јамајка", "sr-Latn": "Jamajka", "zh_TW": "牙買加", "tr": "Jamaika", "ro": "Jamaica", "ar": "جامايكا", "fa": "جامائیکا", "yue": "牙買加" }, flag: "🇯🇲", code: "JM", dialCode: "1876", minLength: 7, maxLength: 7, ), Country( name: "Japan", nameTranslations: { "sk": "Japonsko", "se": "Japána", "pl": "Japonia", "no": "Japan", "ja": "日本", "it": "Giappone", "zh": "日本", "nl": "Japan", "de": "Japan", "fr": "Japon", "es": "Japón", "en": "Japan", "pt_BR": "Japão", "sr-Cyrl": "Јапан", "sr-Latn": "Japan", "zh_TW": "日本", "tr": "Japonya", "ro": "Japonia", "ar": "اليابان", "fa": "ژاپن", "yue": "日本" }, flag: "🇯🇵", code: "JP", dialCode: "81", minLength: 10, maxLength: 10, ), Country( name: "Jersey", nameTranslations: { "sk": "Jersey", "se": "Jersey", "pl": "Jersey", "no": "Jersey", "ja": "ジャージー", "it": "Jersey", "zh": "泽西岛", "nl": "Jersey", "de": "Jersey", "fr": "Jersey", "es": "Jersey", "en": "Jersey", "pt_BR": "Jersey", "sr-Cyrl": "Џерзи", "sr-Latn": "Džerzi", "zh_TW": "澤西", "tr": "Jersey", "ro": "Jersey", "ar": "جيرزي", "fa": "جرزی", "yue": "澤西" }, flag: "🇯🇪", code: "JE", dialCode: "44", minLength: 6, maxLength: 6, ), Country( name: "Jordan", nameTranslations: { "sk": "Jordánsko", "se": "Jordánia", "pl": "Jordania", "no": "Jordan", "ja": "ヨルダン", "it": "Giordania", "zh": "约旦", "nl": "Jordanië", "de": "Jordanien", "fr": "Jordanie", "es": "Jordania", "en": "Jordan", "pt_BR": "Jordânia", "sr-Cyrl": "Јордан", "sr-Latn": "Jordan", "zh_TW": "約旦", "tr": "Mavera-i Ürdün", "ro": "Iordania", "ar": "الأردن", "fa": "اردن", "yue": "約旦" }, flag: "🇯🇴", code: "JO", dialCode: "962", minLength: 9, maxLength: 9, ), Country( name: "Kazakhstan", nameTranslations: { "sk": "Kazachstan", "se": "Kasakstan", "pl": "Kazachstan", "no": "Kasakhstan", "ja": "カザフスタン", "it": "Kazakistan", "zh": "哈萨克斯坦", "nl": "Kazachstan", "de": "Kasachstan", "fr": "Kazakhstan", "es": "Kazajistán", "en": "Kazakhstan", "pt_BR": "Cazaquistão", "sr-Cyrl": "Казахстан", "sr-Latn": "Kazahstan", "zh_TW": "哈薩克", "tr": "Kazakistan", "ro": "Kazahstan", "ar": "كازاخستان", "fa": "قزاقستان", "yue": "哈薩克斯坦" }, flag: "🇰🇿", code: "KZ", dialCode: "7", minLength: 10, maxLength: 10, ), Country( name: "Kenya", nameTranslations: { "sk": "Keňa", "se": "Kenia", "pl": "Kenia", "no": "Kenya", "ja": "ケニア", "it": "Kenya", "zh": "肯尼亚", "nl": "Kenia", "de": "Kenia", "fr": "Kenya", "es": "Kenia", "en": "Kenya", "pt_BR": "Quênia", "sr-Cyrl": "Кенија", "sr-Latn": "Kenija", "zh_TW": "肯亞", "tr": "Kenya", "ro": "Kenya", "ar": "كينيا", "fa": "كنيا", "yue": "肯雅" }, flag: "🇰🇪", code: "KE", dialCode: "254", minLength: 10, maxLength: 10, ), Country( name: "Kiribati", nameTranslations: { "sk": "Kiribati", "se": "Kiribati", "pl": "Kiribati", "no": "Kiribati", "ja": "キリバス", "it": "Kiribati", "zh": "基里巴斯", "nl": "Kiribati", "de": "Kiribati", "fr": "Kiribati", "es": "Kiribati", "en": "Kiribati", "pt_BR": "Kiribati", "sr-Cyrl": "Кирибати", "sr-Latn": "Kiribati", "zh_TW": "吉里巴斯", "tr": "Kiribati", "ro": "Kiribati", "ar": "كيريباتي", "fa": "کیریباتی", "yue": "基里巴斯" }, flag: "🇰🇮", code: "KI", dialCode: "686", minLength: 5, maxLength: 5, ), Country( name: "Korea, Democratic People's Republic of Korea", nameTranslations: { "sk": "Severná Kórea", "se": "Davvi-Korea", "pl": "Korea Północna", "no": "Nord-Korea", "ja": "北朝鮮", "it": "Corea del Nord", "zh": "朝鲜", "nl": "Noord-Korea", "de": "Nordkorea", "fr": "Corée du Nord", "es": "Corea del Norte", "en": "North Korea", "pt_BR": "Coreia do Norte", "sr-Cyrl": "Северна Кореја", "sr-Latn": "Severna Koreja", "zh_TW": "北韓", "tr": "Kuzey Kore", "ro": "Coreea de Nord", "ar": "كوريا الشمالية", "fa": "کره شمالی", "yue": "朝鮮(朝鮮民主主義人民共咊囯)" }, flag: "🇰🇵", code: "KP", dialCode: "850", minLength: 10, maxLength: 10, ), Country( name: "Korea, Republic of South Korea", nameTranslations: { "sk": "Južná Kórea", "se": "Mátta-Korea", "pl": "Korea Południowa", "no": "Sør-Korea", "ja": "韓国", "it": "Corea del Sud", "zh": "韩国", "nl": "Zuid-Korea", "de": "Südkorea", "fr": "Corée du Sud", "es": "Corea del Sur", "en": "South Korea", "pt_BR": "Coreia do Sul", "sr-Cyrl": "Јужна Кореја", "sr-Latn": "Južna Koreja", "zh_TW": "南韓", "tr": "Güney Kore", "ro": "Coreea de Sud", "ar": "كوريا الجنوبية", "fa": "کره جنوبی", "yue": "韓國(大韓民國)" }, flag: "🇰🇷", code: "KR", dialCode: "82", minLength: 11, maxLength: 11, ), Country( name: "Kuwait", nameTranslations: { "sk": "Kuvajt", "se": "Kuwait", "pl": "Kuwejt", "no": "Kuwait", "ja": "クウェート", "it": "Kuwait", "zh": "科威特", "nl": "Koeweit", "de": "Kuwait", "fr": "Koweït", "es": "Kuwait", "en": "Kuwait", "pt_BR": "Kuwait", "sr-Cyrl": "Кувајт", "sr-Latn": "Kuvajt", "zh_TW": "科威特", "tr": "Kuveyt", "ro": "Kuweit", "ar": "الكويت", "fa": "کویت", "yue": "科威特" }, flag: "🇰🇼", code: "KW", dialCode: "965", minLength: 8, maxLength: 8, ), Country( name: "Kyrgyzstan", nameTranslations: { "sk": "Kirgizsko", "se": "Kirgisistan", "pl": "Kirgistan", "no": "Kirgisistan", "ja": "キルギス", "it": "Kirghizistan", "zh": "吉尔吉斯斯坦", "nl": "Kirgizië", "de": "Kirgisistan", "fr": "Kirghizistan", "es": "Kirguistán", "en": "Kyrgyzstan", "pt_BR": "Quirguistão", "sr-Cyrl": "Киргистан", "sr-Latn": "Kirgistan", "zh_TW": "吉爾吉斯", "tr": "Kırgızistan", "ro": "Kîrgîzstan", "ar": "قيرغيزستان", "fa": "قرقیزستان", "yue": "吉爾吉斯斯坦" }, flag: "🇰🇬", code: "KG", dialCode: "996", minLength: 9, maxLength: 9, ), Country( name: "Laos", nameTranslations: { "sk": "Laos", "se": "Laos", "pl": "Laos", "no": "Laos", "ja": "ラオス", "it": "Laos", "zh": "老挝", "nl": "Laos", "de": "Laos", "fr": "Laos", "es": "Laos", "en": "Laos", "pt_BR": "Laos", "sr-Cyrl": "Лаос", "sr-Latn": "Laos", "zh_TW": "寮國", "tr": "Laos", "ro": "Laos", "ar": "لاوس", "fa": "لائوس", "yue": "老撾人民民主共和國" }, flag: "🇱🇦", code: "LA", dialCode: "856", minLength: 10, maxLength: 10, ), Country( name: "Latvia", nameTranslations: { "sk": "Lotyšsko", "se": "Látvia", "pl": "Łotwa", "no": "Latvia", "ja": "ラトビア", "it": "Lettonia", "zh": "拉脱维亚", "nl": "Letland", "de": "Lettland", "fr": "Lettonie", "es": "Letonia", "en": "Latvia", "pt_BR": "Letônia", "sr-Cyrl": "Летонија", "sr-Latn": "Letonija", "zh_TW": "拉托維亞", "tr": "Letonya", "ro": "Letonia", "ar": "لاتفيا", "fa": "لتونی", "yue": "拉脫維亞" }, flag: "🇱🇻", code: "LV", dialCode: "371", minLength: 8, maxLength: 8, ), Country( name: "Lebanon", nameTranslations: { "sk": "Libanon", "se": "Libanon", "pl": "Liban", "no": "Libanon", "ja": "レバノン", "it": "Libano", "zh": "黎巴嫩", "nl": "Libanon", "de": "Libanon", "fr": "Liban", "es": "Líbano", "en": "Lebanon", "pt_BR": "Líbano", "sr-Cyrl": "Либан", "sr-Latn": "Liban", "zh_TW": "黎巴嫩", "tr": "Lübnan", "ro": "Liban", "ar": "لبنان", "fa": "لبنان", "yue": "黎巴嫩" }, flag: "🇱🇧", code: "LB", dialCode: "961", minLength: 8, maxLength: 8, ), Country( name: "Lesotho", nameTranslations: { "sk": "Lesotho", "se": "Lesotho", "pl": "Lesotho", "no": "Lesotho", "ja": "レソト", "it": "Lesotho", "zh": "莱索托", "nl": "Lesotho", "de": "Lesotho", "fr": "Lesotho", "es": "Lesoto", "en": "Lesotho", "pt_BR": "Lesoto", "sr-Cyrl": "Лесото", "sr-Latn": "Lesoto", "zh_TW": "賴索托", "tr": "Lesotho", "ro": "Lesotho", "ar": "ليسوتو", "fa": "لسوتو", "yue": "萊索托" }, flag: "🇱🇸", code: "LS", dialCode: "266", minLength: 8, maxLength: 8, ), Country( name: "Liberia", nameTranslations: { "sk": "Libéria", "se": "Liberia", "pl": "Liberia", "no": "Liberia", "ja": "リベリア", "it": "Liberia", "zh": "利比里亚", "nl": "Liberia", "de": "Liberia", "fr": "Libéria", "es": "Liberia", "en": "Liberia", "pt_BR": "Libéria", "sr-Cyrl": "Либерија", "sr-Latn": "Liberija", "zh_TW": "賴比瑞亞", "tr": "Liberya", "ro": "Liberia", "ar": "ليبيريا", "fa": "لیبریا", "yue": "利比里亞" }, flag: "🇱🇷", code: "LR", dialCode: "231", minLength: 8, maxLength: 8, ), Country( name: "Libyan Arab Jamahiriya", nameTranslations: { "sk": "Líbya", "se": "Libya", "pl": "Libia", "no": "Libya", "ja": "リビア", "it": "Libia", "zh": "利比亚", "nl": "Libië", "de": "Libyen", "fr": "Libye", "es": "Libia", "en": "Libya", "pt_BR": "Líbia", "sr-Cyrl": "Либија", "sr-Latn": "Libija", "zh_TW": "利比亞", "tr": "Libya", "ro": "Libia", "ar": "ليبيا", "fa": "لیبی", "yue": "利比亞" }, flag: "🇱🇾", code: "LY", dialCode: "218", minLength: 9, maxLength: 9, ), Country( name: "Liechtenstein", nameTranslations: { "sk": "Lichtenštajnsko", "se": "Liechtenstein", "pl": "Liechtenstein", "no": "Liechtenstein", "ja": "リヒテンシュタイン", "it": "Liechtenstein", "zh": "列支敦士登", "nl": "Liechtenstein", "de": "Liechtenstein", "fr": "Liechtenstein", "es": "Liechtenstein", "en": "Liechtenstein", "pt_BR": "Liechtenstein", "sr-Cyrl": "Лихтенштајн", "sr-Latn": "Lihtenštajn", "zh_TW": "列支敦斯登", "tr": "Lihtenştayn", "ro": "Liechtenstein", "ar": "ليختنشتاين", "fa": "لیختن‌اشتاین", "yue": "列支敦士登" }, flag: "🇱🇮", code: "LI", dialCode: "423", minLength: 9, maxLength: 9, ), Country( name: "Lithuania", nameTranslations: { "sk": "Litva", "se": "Lietuva", "pl": "Litwa", "no": "Litauen", "ja": "リトアニア", "it": "Lituania", "zh": "立陶宛", "nl": "Litouwen", "de": "Litauen", "fr": "Lituanie", "es": "Lituania", "en": "Lithuania", "pt_BR": "Lituânia", "sr-Cyrl": "Литванија", "sr-Latn": "Litvanija", "zh_TW": "立陶宛", "tr": "Litvanya", "ro": "Lituania", "ar": "ليتوانيا", "fa": "لیتوانی", "yue": "立陶宛" }, flag: "🇱🇹", code: "LT", dialCode: "370", minLength: 8, maxLength: 8, ), Country( name: "Luxembourg", nameTranslations: { "sk": "Luxembursko", "se": "Luxembourg", "pl": "Luksemburg", "no": "Luxemburg", "ja": "ルクセンブルク", "it": "Lussemburgo", "zh": "卢森堡", "nl": "Luxemburg", "de": "Luxemburg", "fr": "Luxembourg", "es": "Luxemburgo", "en": "Luxembourg", "pt_BR": "Luxemburgo", "sr-Cyrl": "Луксенбург", "sr-Latn": "Luksenburg", "zh_TW": "盧森堡", "tr": "Lüksemburg", "ro": "Luxemburg", "ar": "لوكسمبورغ", "fa": "لوکزامبورگ", "yue": "盧森堡" }, flag: "🇱🇺", code: "LU", dialCode: "352", minLength: 11, maxLength: 11, ), Country( name: "Macao", nameTranslations: { "sk": "Macao – OAO Číny", "se": "Makáo", "pl": "SRA Makau (Chiny)", "no": "Macao S.A.R. Kina", "ja": "中華人民共和国マカオ特別行政区", "it": "RAS di Macao", "zh": "中国澳门特别行政区", "nl": "Macau SAR van China", "de": "Sonderverwaltungsregion Macau", "fr": "R.A.S. chinoise de Macao", "es": "RAE de Macao (China)", "en": "Macao SAR China", "pt_BR": "RAE de Macau China", "sr-Cyrl": "Макао", "sr-Latn": "Makao", "zh_TW": "澳門", "tr": "Makao", "ro": "Macao", "ar": "ماكاو", "fa": "ماكائو", "yue": "澳門" }, flag: "🇲🇴", code: "MO", dialCode: "853", minLength: 8, maxLength: 8, ), Country( name: "Macedonia", nameTranslations: { "sk": "Severné Macedónsko", "se": "North Macedonia", "pl": "Macedonia Północna", "no": "Nord-Makedonia", "ja": "北マケドニア", "it": "Macedonia del Nord", "zh": "北马其顿", "nl": "Noord-Macedonië", "de": "Nordmazedonien", "fr": "Macédoine du Nord", "es": "Macedonia del Norte", "en": "North Macedonia", "pt_BR": "Macedônia do Norte", "sr-Cyrl": "Северна Македонија", "sr-Latn": "Severna Makedonija", "zh_TW": "北馬其頓", "tr": "Kuzey Makedonya", "ro": "Macedonia de Nord", "ar": "مقدونيا", "fa": "مقدونیه", "yue": "馬其頓(前南斯拉夫共和國)" }, flag: "🇲🇰", code: "MK", dialCode: "389", minLength: 8, maxLength: 8, ), Country( name: "Madagascar", nameTranslations: { "sk": "Madagaskar", "se": "Madagaskar", "pl": "Madagaskar", "no": "Madagaskar", "ja": "マダガスカル", "it": "Madagascar", "zh": "马达加斯加", "nl": "Madagaskar", "de": "Madagaskar", "fr": "Madagascar", "es": "Madagascar", "en": "Madagascar", "pt_BR": "Madagáscar", "sr-Cyrl": "Мадагаскар", "sr-Latn": "Madagaskar", "zh_TW": "馬達加斯加", "tr": "Madagaskar", "ro": "Madagascar", "ar": "مدغشقر", "fa": "ماداگاسکار", "yue": "馬達加斯加" }, flag: "🇲🇬", code: "MG", dialCode: "261", minLength: 10, maxLength: 10, ), Country( name: "Malawi", nameTranslations: { "sk": "Malawi", "se": "Malawi", "pl": "Malawi", "no": "Malawi", "ja": "マラウイ", "it": "Malawi", "zh": "马拉维", "nl": "Malawi", "de": "Malawi", "fr": "Malawi", "es": "Malaui", "en": "Malawi", "pt_BR": "Malawi", "sr-Cyrl": "Малави", "sr-Latn": "Malavi", "zh_TW": "馬拉威", "tr": "Malavi", "ro": "Malawi", "ar": "مالاوي", "fa": "مالاوی", "yue": "馬拉維" }, flag: "🇲🇼", code: "MW", dialCode: "265", minLength: 7, maxLength: 9, ), Country( name: "Malaysia", nameTranslations: { "sk": "Malajzia", "se": "Malesia", "pl": "Malezja", "no": "Malaysia", "ja": "マレーシア", "it": "Malaysia", "zh": "马来西亚", "nl": "Maleisië", "de": "Malaysia", "fr": "Malaisie", "es": "Malasia", "en": "Malaysia", "pt_BR": "Malásia", "sr-Cyrl": "Малезија", "sr-Latn": "Malezija", "zh_TW": "馬來西亞", "tr": "Malezya", "ro": "Malaezia", "ar": "ماليزيا", "fa": "مالزی", "yue": "馬來西亞" }, flag: "🇲🇾", code: "MY", dialCode: "60", minLength: 9, maxLength: 10, ), Country( name: "Maldives", nameTranslations: { "sk": "Maldivy", "se": "Malediivvat", "pl": "Malediwy", "no": "Maldivene", "ja": "モルディブ", "it": "Maldive", "zh": "马尔代夫", "nl": "Maldiven", "de": "Malediven", "fr": "Maldives", "es": "Maldivas", "en": "Maldives", "pt_BR": "Maldivas", "sr-Cyrl": "Малдиви", "sr-Latn": "Maldivi", "zh_TW": "馬爾地夫", "tr": "Maldivler", "ro": "Maldive", "ar": "جزر المالديف", "fa": "مالدیو", "yue": "馬爾代夫" }, flag: "🇲🇻", code: "MV", dialCode: "960", minLength: 7, maxLength: 7, ), Country( name: "Mali", nameTranslations: { "sk": "Mali", "se": "Mali", "pl": "Mali", "no": "Mali", "ja": "マリ", "it": "Mali", "zh": "马里", "nl": "Mali", "de": "Mali", "fr": "Mali", "es": "Mali", "en": "Mali", "pt_BR": "Mali", "sr-Cyrl": "Мали", "sr-Latn": "Mali", "zh_TW": "馬里", "tr": "Mali", "ro": "Mali", "ar": "مالي", "fa": "مالی", "yue": "馬里" }, flag: "🇲🇱", code: "ML", dialCode: "223", minLength: 8, maxLength: 8, ), Country( name: "Malta", nameTranslations: { "sk": "Malta", "se": "Málta", "pl": "Malta", "no": "Malta", "ja": "マルタ", "it": "Malta", "zh": "马耳他", "nl": "Malta", "de": "Malta", "fr": "Malte", "es": "Malta", "en": "Malta", "pt_BR": "Malta", "sr-Cyrl": "Малта", "sr-Latn": "Malta", "zh_TW": "馬爾他", "tr": "Malta", "ro": "Malta", "ar": "مالطا", "fa": "مالت", "yue": "馬耳他" }, flag: "🇲🇹", code: "MT", dialCode: "356", minLength: 8, maxLength: 8, ), Country( name: "Marshall Islands", nameTranslations: { "sk": "Marshallove ostrovy", "se": "Marshallsullot", "pl": "Wyspy Marshalla", "no": "Marshalløyene", "ja": "マーシャル諸島", "it": "Isole Marshall", "zh": "马绍尔群岛", "nl": "Marshalleilanden", "de": "Marshallinseln", "fr": "Îles Marshall", "es": "Islas Marshall", "en": "Marshall Islands", "pt_BR": "Ilhas Marshall", "sr-Cyrl": "Маршалска Острва", "sr-Latn": "Maršalska Ostrva", "zh_TW": "馬紹爾群島", "tr": "Marshall Adaları", "ro": "Insulele Marshall", "ar": "جزر مارشال", "fa": "جزایر مارشال", "yue": "馬紹爾群島" }, flag: "🇲🇭", code: "MH", dialCode: "692", minLength: 7, maxLength: 7, ), Country( name: "Martinique", nameTranslations: { "sk": "Martinik", "se": "Martinique", "pl": "Martynika", "no": "Martinique", "ja": "マルティニーク", "it": "Martinica", "zh": "马提尼克", "nl": "Martinique", "de": "Martinique", "fr": "Martinique", "es": "Martinica", "en": "Martinique", "pt_BR": "Martinica", "sr-Cyrl": "Мартиник", "sr-Latn": "Martinik", "zh_TW": "馬丁尼克", "tr": "Martinique", "ro": "Martinica", "ar": "مارتينيك", "fa": "مارتینیک", "yue": "马提尼克" }, flag: "🇲🇶", code: "MQ", dialCode: "596", minLength: 15, maxLength: 15, ), Country( name: "Mauritania", nameTranslations: { "sk": "Mauritánia", "se": "Mauretánia", "pl": "Mauretania", "no": "Mauritania", "ja": "モーリタニア", "it": "Mauritania", "zh": "毛里塔尼亚", "nl": "Mauritanië", "de": "Mauretanien", "fr": "Mauritanie", "es": "Mauritania", "en": "Mauritania", "pt_BR": "Mauritânia", "sr-Cyrl": "Мауританија", "sr-Latn": "Mauritanija", "zh_TW": "茅利塔尼亞", "tr": "Moritanya", "ro": "Mauritania", "ar": "موريتانيا", "fa": "موریتانی", "yue": "毛里塔尼亞" }, flag: "🇲🇷", code: "MR", dialCode: "222", minLength: 8, maxLength: 8, ), Country( name: "Mauritius", nameTranslations: { "sk": "Maurícius", "se": "Mauritius", "pl": "Mauritius", "no": "Mauritius", "ja": "モーリシャス", "it": "Mauritius", "zh": "毛里求斯", "nl": "Mauritius", "de": "Mauritius", "fr": "Maurice", "es": "Mauricio", "en": "Mauritius", "pt_BR": "Maurício", "sr-Cyrl": "Маурицијус", "sr-Latn": "Mauricijus", "zh_TW": "模里西斯", "tr": "Mauritius", "ro": "Mauritius", "ar": "موريشيوس", "fa": "موریس", "yue": "毛里求斯" }, flag: "🇲🇺", code: "MU", dialCode: "230", minLength: 7, maxLength: 8, ), Country( name: "Mayotte", nameTranslations: { "sk": "Mayotte", "se": "Mayotte", "pl": "Majotta", "no": "Mayotte", "ja": "マヨット", "it": "Mayotte", "zh": "马约特", "nl": "Mayotte", "de": "Mayotte", "fr": "Mayotte", "es": "Mayotte", "en": "Mayotte", "pt_BR": "Mayotte", "sr-Cyrl": "Мајота", "sr-Latn": "Majota", "zh_TW": "馬約特", "tr": "Mayotte", "ro": "Mayotte", "ar": "مايوت", "fa": "مایوت", "yue": "馬約特" }, flag: "🇾🇹", code: "YT", dialCode: "262", minLength: 9, maxLength: 9, ), Country( name: "Mexico", nameTranslations: { "sk": "Mexiko", "se": "Meksiko", "pl": "Meksyk", "no": "Mexico", "ja": "メキシコ", "it": "Messico", "zh": "墨西哥", "nl": "Mexico", "de": "Mexiko", "fr": "Mexique", "es": "México", "en": "Mexico", "pt_BR": "México", "sr-Cyrl": "Мексико", "sr-Latn": "Meksiko", "zh_TW": "墨西哥", "tr": "Meksika", "ro": "Mexic", "ar": "المكسيك", "fa": "مکزیک", "yue": "墨西哥" }, flag: "🇲🇽", code: "MX", dialCode: "52", minLength: 10, maxLength: 10, ), Country( name: "Micronesia, Federated States of Micronesia", nameTranslations: { "sk": "Mikronézia", "se": "Mikronesia", "pl": "Mikronezja", "no": "Mikronesiaføderasjonen", "ja": "ミクロネシア連邦", "it": "Micronesia", "zh": "密克罗尼西亚", "nl": "Micronesia", "de": "Mikronesien", "fr": "États fédérés de Micronésie", "es": "Micronesia", "en": "Micronesia", "pt_BR": "Micronésia", "sr-Cyrl": "Микронезија", "sr-Latn": "Mikronezija", "zh_TW": "密克羅尼西亞", "tr": "Mikronezya", "ro": "Micronezia", "ar": "ولايات ميكرونيسيا المتحدة", "fa": "ایالات فدرال میکرونزی", "yue": "密克罗尼西亚(聯邦)" }, flag: "🇫🇲", code: "FM", dialCode: "691", minLength: 7, maxLength: 7, ), Country( name: "Moldova", nameTranslations: { "sk": "Moldavsko", "se": "Moldávia", "pl": "Mołdawia", "no": "Moldova", "ja": "モルドバ", "it": "Moldavia", "zh": "摩尔多瓦", "nl": "Moldavië", "de": "Republik Moldau", "fr": "Moldavie", "es": "Moldavia", "en": "Moldova", "pt_BR": "Moldova", "sr-Cyrl": "Молдавија", "sr-Latn": "Moldavija", "zh_TW": "摩爾多瓦", "tr": "Moldova", "ro": "Moldova", "ar": "مولدوفا", "fa": "مولداوی", "yue": "摩爾多瓦(共和國)" }, flag: "🇲🇩", code: "MD", dialCode: "373", minLength: 8, maxLength: 8, ), Country( name: "Monaco", nameTranslations: { "sk": "Monako", "se": "Monaco", "pl": "Monako", "no": "Monaco", "ja": "モナコ", "it": "Monaco", "zh": "摩纳哥", "nl": "Monaco", "de": "Monaco", "fr": "Monaco", "es": "Mónaco", "en": "Monaco", "pt_BR": "Mônaco", "sr-Cyrl": "Монако", "sr-Latn": "Monako", "zh_TW": "摩納哥", "tr": "Monako", "ro": "Monaco", "ar": "موناكو", "fa": "موناكو", "yue": "摩納哥" }, flag: "🇲🇨", code: "MC", dialCode: "377", minLength: 9, maxLength: 9, ), Country( name: "Mongolia", nameTranslations: { "sk": "Mongolsko", "se": "Mongolia", "pl": "Mongolia", "no": "Mongolia", "ja": "モンゴル", "it": "Mongolia", "zh": "蒙古", "nl": "Mongolië", "de": "Mongolei", "fr": "Mongolie", "es": "Mongolia", "en": "Mongolia", "pt_BR": "Mongólia", "sr-Cyrl": "Монголија", "sr-Latn": "Mongolija", "zh_TW": "蒙古", "tr": "Moğolistan", "ro": "Mongolia", "ar": "منغوليا", "fa": "مغولستان", "yue": "蒙古" }, flag: "🇲🇳", code: "MN", dialCode: "976", minLength: 8, maxLength: 8, ), Country( name: "Montenegro", nameTranslations: { "sk": "Čierna Hora", "se": "Montenegro", "pl": "Czarnogóra", "no": "Montenegro", "ja": "モンテネグロ", "it": "Montenegro", "zh": "黑山", "nl": "Montenegro", "de": "Montenegro", "fr": "Monténégro", "es": "Montenegro", "en": "Montenegro", "pt_BR": "Montenegro", "sr-Cyrl": "Црна Гора", "sr-Latn": "Crna Gora", "zh_TW": "蒙特內哥羅", "tr": "Karadağ", "ro": "Muntenegru", "ar": "الجبل الأسود", "fa": "مونته‌نگرو", "yue": "黑山" }, flag: "🇲🇪", code: "ME", dialCode: "382", minLength: 12, maxLength: 12, ), Country( name: "Montserrat", nameTranslations: { "sk": "Montserrat", "se": "Montserrat", "pl": "Montserrat", "no": "Montserrat", "ja": "モントセラト", "it": "Montserrat", "zh": "蒙特塞拉特", "nl": "Montserrat", "de": "Montserrat", "fr": "Montserrat", "es": "Montserrat", "en": "Montserrat", "pt_BR": "Montserrat", "sr-Cyrl": "Монтсерат", "sr-Latn": "Montserat", "zh_TW": "蒙哲臘", "tr": "Montserrat", "ro": "Montserrat", "ar": "مونتسرات", "fa": "مونتسرات", "yue": "蒙特塞拉特" }, flag: "🇲🇸", code: "MS", dialCode: "1664", minLength: 7, maxLength: 7, ), Country( name: "Morocco", nameTranslations: { "sk": "Maroko", "se": "Marokko", "pl": "Maroko", "no": "Marokko", "ja": "モロッコ", "it": "Marocco", "zh": "摩洛哥", "nl": "Marokko", "de": "Marokko", "fr": "Maroc", "es": "Marruecos", "en": "Morocco", "pt_BR": "Marrocos", "sr-Cyrl": "Мароко", "sr-Latn": "Maroko", "zh_TW": "摩洛哥", "tr": "Fas", "ro": "Maroc", "ar": "المغرب", "fa": "مراکش", "yue": "摩洛哥" }, flag: "🇲🇦", code: "MA", dialCode: "212", minLength: 9, maxLength: 9, ), Country( name: "Mozambique", nameTranslations: { "sk": "Mozambik", "se": "Mosambik", "pl": "Mozambik", "no": "Mosambik", "ja": "モザンビーク", "it": "Mozambico", "zh": "莫桑比克", "nl": "Mozambique", "de": "Mosambik", "fr": "Mozambique", "es": "Mozambique", "en": "Mozambique", "pt_BR": "Moçambique", "sr-Cyrl": "Мозамбик", "sr-Latn": "Mozambik", "zh_TW": "莫三比克", "tr": "Mozambik", "ro": "Mozambic", "ar": "موزمبيق", "fa": "موزامبیک", "yue": "莫桑比克" }, flag: "🇲🇿", code: "MZ", dialCode: "258", minLength: 9, maxLength: 9, ), Country( name: "Myanmar", nameTranslations: { "sk": "Mjanmarsko", "se": "Burma", "pl": "Mjanma (Birma)", "no": "Myanmar (Burma)", "ja": "ミャンマー (ビルマ)", "it": "Myanmar (Birmania)", "zh": "缅甸", "nl": "Myanmar (Birma)", "de": "Myanmar", "fr": "Myanmar (Birmanie)", "es": "Myanmar (Birmania)", "en": "Myanmar (Burma)", "pt_BR": "Mianmar (Birmânia)", "sr-Cyrl": "Мјанмар (Бурма)", "sr-Latn": "Mjanmar (Burma)", "zh_TW": "緬甸", "tr": "Myanmar", "ro": "Myanmar", "ar": "ميانمار", "fa": "میانمار", "yue": "緬甸" }, flag: "🇲🇲", code: "MM", dialCode: "95", minLength: 9, maxLength: 9, ), Country( name: "Namibia", nameTranslations: { "sk": "Namíbia", "se": "Namibia", "pl": "Namibia", "no": "Namibia", "ja": "ナミビア", "it": "Namibia", "zh": "纳米比亚", "nl": "Namibië", "de": "Namibia", "fr": "Namibie", "es": "Namibia", "en": "Namibia", "pt_BR": "Namibia", "sr-Cyrl": "Намибија", "sr-Latn": "Namibija", "zh_TW": "納米比亞", "tr": "Namibya", "ro": "Namibia", "ar": "ناميبيا", "fa": "نامیبیا", "yue": "納米比亞" }, flag: "🇳🇦", code: "NA", dialCode: "264", minLength: 10, maxLength: 10, ), Country( name: "Nauru", nameTranslations: { "sk": "Nauru", "se": "Nauru", "pl": "Nauru", "no": "Nauru", "ja": "ナウル", "it": "Nauru", "zh": "瑙鲁", "nl": "Nauru", "de": "Nauru", "fr": "Nauru", "es": "Nauru", "en": "Nauru", "pt_BR": "Nauru", "sr-Cyrl": "Науру", "sr-Latn": "Nauru", "zh_TW": "諾魯", "tr": "Nauru", "ro": "Nauru", "ar": "ناورو", "fa": "نائورو", "yue": "瑙魯" }, flag: "🇳🇷", code: "NR", dialCode: "674", minLength: 7, maxLength: 7, ), Country( name: "Nepal", nameTranslations: { "sk": "Nepál", "se": "Nepal", "pl": "Nepal", "no": "Nepal", "ja": "ネパール", "it": "Nepal", "zh": "尼泊尔", "nl": "Nepal", "de": "Nepal", "fr": "Népal", "es": "Nepal", "en": "Nepal", "pt_BR": "Nepal", "sr-Cyrl": "Непал", "sr-Latn": "Nepal", "zh_TW": "尼泊爾", "tr": "Nepal", "ro": "Nepal", "ar": "نيبال", "fa": "نپال", "yue": "尼泊爾" }, flag: "🇳🇵", code: "NP", dialCode: "977", minLength: 10, maxLength: 10, ), Country( name: "Netherlands", nameTranslations: { "sk": "Holandsko", "se": "Vuolleeatnamat", "pl": "Holandia", "no": "Nederland", "ja": "オランダ", "it": "Paesi Bassi", "zh": "荷兰", "nl": "Nederland", "de": "Niederlande", "fr": "Pays-Bas", "es": "Países Bajos", "en": "Netherlands", "pt_BR": "Países Baixos", "sr-Cyrl": "Холандија", "sr-Latn": "Holandija", "zh_TW": "荷蘭", "tr": "Hollanda", "ro": "Olanda", "ar": "هولندا", "fa": "هلند", "yue": "荷蘭" }, flag: "🇳🇱", code: "NL", dialCode: "31", minLength: 9, maxLength: 9, ), Country( name: "New Caledonia", nameTranslations: { "sk": "Nová Kaledónia", "se": "Ođđa-Kaledonia", "pl": "Nowa Kaledonia", "no": "Ny-Caledonia", "ja": "ニューカレドニア", "it": "Nuova Caledonia", "zh": "新喀里多尼亚", "nl": "Nieuw-Caledonië", "de": "Neukaledonien", "fr": "Nouvelle-Calédonie", "es": "Nueva Caledonia", "en": "New Caledonia", "pt_BR": "Nova Caledônia", "sr-Cyrl": "Нова Каледонија", "sr-Latn": "Nova Kaledonija", "zh_TW": "新喀里多尼亞", "tr": "Yeni Kaledonya", "ro": "Noua Caledonie", "ar": "كاليدونيا الجديدة", "fa": "کالدونیای جدید", "yue": "新喀里多尼亚" }, flag: "🇳🇨", code: "NC", dialCode: "687", minLength: 6, maxLength: 6, ), Country( name: "New Zealand", nameTranslations: { "sk": "Nový Zéland", "se": "Ođđa-Selánda", "pl": "Nowa Zelandia", "no": "New Zealand", "ja": "ニュージーランド", "it": "Nuova Zelanda", "zh": "新西兰", "nl": "Nieuw-Zeeland", "de": "Neuseeland", "fr": "Nouvelle-Zélande", "es": "Nueva Zelanda", "en": "New Zealand", "pt_BR": "Nova Zelândia", "sr-Cyrl": "Нови Зеланд", "sr-Latn": "Novi Zeland", "zh_TW": "紐西蘭", "tr": "Yeni Zelanda", "ro": "Noua Zeelandă", "ar": "نيوزيلندا", "fa": "نیوزلند", "yue": "紐西蘭" }, flag: "🇳🇿", code: "NZ", dialCode: "64", minLength: 10, maxLength: 10, ), Country( name: "Nicaragua", nameTranslations: { "sk": "Nikaragua", "se": "Nicaragua", "pl": "Nikaragua", "no": "Nicaragua", "ja": "ニカラグア", "it": "Nicaragua", "zh": "尼加拉瓜", "nl": "Nicaragua", "de": "Nicaragua", "fr": "Nicaragua", "es": "Nicaragua", "en": "Nicaragua", "pt_BR": "Nicarágua", "sr-Cyrl": "Никарагва", "sr-Latn": "Nikaragva", "zh_TW": "尼加拉瓜", "tr": "Nikaragua", "ro": "Nicaragua", "ar": "نيكاراغوا", "fa": "نیکاراگوئه", "yue": "尼加拉瓜" }, flag: "🇳🇮", code: "NI", dialCode: "505", minLength: 8, maxLength: 8, ), Country( name: "Niger", nameTranslations: { "sk": "Niger", "se": "Niger", "pl": "Niger", "no": "Niger", "ja": "ニジェール", "it": "Niger", "zh": "尼日尔", "nl": "Niger", "de": "Niger", "fr": "Niger", "es": "Níger", "en": "Niger", "pt_BR": "Níger", "sr-Cyrl": "Нигер", "sr-Latn": "Niger", "zh_TW": "尼日爾", "tr": "Nijer", "ro": "Niger", "ar": "النيجر", "fa": "نیجر", "yue": "尼日爾" }, flag: "🇳🇪", code: "NE", dialCode: "227", minLength: 8, maxLength: 8, ), Country( name: "Nigeria", nameTranslations: { "sk": "Nigéria", "se": "Nigeria", "pl": "Nigeria", "no": "Nigeria", "ja": "ナイジェリア", "it": "Nigeria", "zh": "尼日利亚", "nl": "Nigeria", "de": "Nigeria", "fr": "Nigéria", "es": "Nigeria", "en": "Nigeria", "pt_BR": "Nigéria", "sr-Cyrl": "Нигерија", "sr-Latn": "Nigerija", "zh_TW": "奈及利亞", "tr": "Nijerya", "ro": "Nigeria", "ar": "نيجيريا", "fa": "نیجریه", "yue": "尼日利亞" }, flag: "🇳🇬", code: "NG", dialCode: "234", minLength: 10, maxLength: 11, ), Country( name: "Niue", nameTranslations: { "sk": "Niue", "se": "Niue", "pl": "Niue", "no": "Niue", "ja": "ニウエ", "it": "Niue", "zh": "纽埃", "nl": "Niue", "de": "Niue", "fr": "Niue", "es": "Niue", "en": "Niue", "pt_BR": "Niue", "sr-Cyrl": "Нијуе", "sr-Latn": "Nijue", "zh_TW": "紐埃", "tr": "Niue", "ro": "Niue", "ar": "نييوي", "fa": "نیووی", "yue": "紐埃" }, flag: "🇳🇺", code: "NU", dialCode: "683", minLength: 4, maxLength: 4, ), Country( name: "Norfolk Island", nameTranslations: { "sk": "Norfolk", "se": "Norfolksullot", "pl": "Norfolk", "no": "Norfolkøya", "ja": "ノーフォーク島", "it": "Isola Norfolk", "zh": "诺福克岛", "nl": "Norfolk", "de": "Norfolkinsel", "fr": "Île Norfolk", "es": "Isla Norfolk", "en": "Norfolk Island", "pt_BR": "Ilha Norfolk", "sr-Cyrl": "Острво Норфок", "sr-Latn": "Ostrvo Norfok", "zh_TW": "諾福克島", "tr": "Norfolk Adası", "ro": "Insulele Norfolk", "ar": "جزيرة نورفولك", "fa": "جزیره نورفک", "yue": "诺福克岛" }, flag: "🇳🇫", code: "NF", dialCode: "672", minLength: 15, maxLength: 15, ), Country( name: "Northern Mariana Islands", nameTranslations: { "sk": "Severné Mariány", "se": "Davvi-Mariánat", "pl": "Mariany Północne", "no": "Nord-Marianene", "ja": "北マリアナ諸島", "it": "Isole Marianne settentrionali", "zh": "北马里亚纳群岛", "nl": "Noordelijke Marianen", "de": "Nördliche Marianen", "fr": "Îles Mariannes du Nord", "es": "Islas Marianas del Norte", "en": "Northern Mariana Islands", "pt_BR": "Ilhas Marianas do Norte", "sr-Cyrl": "Северна Маријанска Острва", "sr-Latn": "Severna Marijanska Ostrva", "zh_TW": "北馬利安納群島", "tr": "Kuzey Mariana Adaları", "ro": "Insulelor Mariane de Nord", "ar": "جزر ماريانا الشمالية", "fa": "جزایر ماریانای شمالی", "yue": "北馬里亞納群島" }, flag: "🇲🇵", code: "MP", dialCode: "1670", minLength: 7, maxLength: 7, ), Country( name: "Norway", nameTranslations: { "sk": "Nórsko", "se": "Norga", "pl": "Norwegia", "no": "Norge", "ja": "ノルウェー", "it": "Norvegia", "zh": "挪威", "nl": "Noorwegen", "de": "Norwegen", "fr": "Norvège", "es": "Noruega", "en": "Norway", "pt_BR": "Noruega", "sr-Cyrl": "Норвешка", "sr-Latn": "Norveška", "zh_TW": "挪威", "tr": "Norveç", "ro": "Norvegia", "ar": "النرويج", "fa": "نروژ", "yue": "挪威" }, flag: "🇳🇴", code: "NO", dialCode: "47", minLength: 8, maxLength: 8, ), Country( name: "Oman", nameTranslations: { "sk": "Omán", "se": "Oman", "pl": "Oman", "no": "Oman", "ja": "オマーン", "it": "Oman", "zh": "阿曼", "nl": "Oman", "de": "Oman", "fr": "Oman", "es": "Omán", "en": "Oman", "pt_BR": "Omã", "sr-Cyrl": "Оман", "sr-Latn": "Oman", "zh_TW": "阿曼", "tr": "Umman", "ro": "Oman", "ar": "عمان", "fa": "عمان", "yue": "阿曼" }, flag: "🇴🇲", code: "OM", dialCode: "968", minLength: 8, maxLength: 8, ), Country( name: "Pakistan", nameTranslations: { "sk": "Pakistan", "se": "Pakistan", "pl": "Pakistan", "no": "Pakistan", "ja": "パキスタン", "it": "Pakistan", "zh": "巴基斯坦", "nl": "Pakistan", "de": "Pakistan", "fr": "Pakistan", "es": "Pakistán", "en": "Pakistan", "pt_BR": "Paquistão", "sr-Cyrl": "Пакистан", "sr-Latn": "Pakistan", "zh_TW": "巴基斯坦", "tr": "Pakistan", "ro": "Pakistan", "ar": "باكستان", "fa": "پاکستان", "yue": "巴基斯坦" }, flag: "🇵🇰", code: "PK", dialCode: "92", minLength: 10, maxLength: 10, ), Country( name: "Palau", nameTranslations: { "sk": "Palau", "se": "Palau", "pl": "Palau", "no": "Palau", "ja": "パラオ", "it": "Palau", "zh": "帕劳", "nl": "Palau", "de": "Palau", "fr": "Palaos", "es": "Palaos", "en": "Palau", "pt_BR": "Palau", "sr-Cyrl": "Палау", "sr-Latn": "Palau", "zh_TW": "帛琉", "tr": "Palau", "ro": "Palau", "ar": "بالاو", "fa": "پالائو", "yue": "帕劳" }, flag: "🇵🇼", code: "PW", dialCode: "680", minLength: 7, maxLength: 7, ), Country( name: "Palestinian Territory, Occupied", nameTranslations: { "sk": "Palestínske územia", "se": "Palestina", "pl": "Terytoria Palestyńskie", "no": "Det palestinske området", "ja": "パレスチナ自治区", "it": "Territori palestinesi", "zh": "巴勒斯坦领土", "nl": "Palestijnse gebieden", "de": "Palästinensische Autonomiegebiete", "fr": "Territoires palestiniens", "es": "Territorios Palestinos", "en": "Palestinian Territories", "pt_BR": "Territórios Palestinos", "sr-Cyrl": "Палестина", "sr-Latn": "Palestina", "zh_TW": "巴勒斯坦", "tr": "Filistin", "ro": "Palestina", "ar": "فلسطين", "fa": "فلسطین", "yue": "巴勒斯坦,国" }, flag: "🇵🇸", code: "PS", dialCode: "970", minLength: 9, maxLength: 9, ), Country( name: "Panama", nameTranslations: { "sk": "Panama", "se": "Panama", "pl": "Panama", "no": "Panama", "ja": "パナマ", "it": "Panamá", "zh": "巴拿马", "nl": "Panama", "de": "Panama", "fr": "Panama", "es": "Panamá", "en": "Panama", "pt_BR": "Panamá", "sr-Cyrl": "Панама", "sr-Latn": "Panama", "zh_TW": "巴拿馬", "tr": "Panama", "ro": "Panama", "ar": "بنما", "fa": "پاناما", "yue": "巴拿馬" }, flag: "🇵🇦", code: "PA", dialCode: "507", minLength: 8, maxLength: 8, ), Country( name: "Papua New Guinea", nameTranslations: { "sk": "Papua-Nová Guinea", "se": "Papua-Ođđa-Guinea", "pl": "Papua-Nowa Gwinea", "no": "Papua Ny-Guinea", "ja": "パプアニューギニア", "it": "Papua Nuova Guinea", "zh": "巴布亚新几内亚", "nl": "Papoea-Nieuw-Guinea", "de": "Papua-Neuguinea", "fr": "Papouasie-Nouvelle-Guinée", "es": "Papúa Nueva Guinea", "en": "Papua New Guinea", "pt_BR": "Papua Nova Guiné", "sr-Cyrl": "Папуа Нова Гвинеја", "sr-Latn": "Papua Nova Gvineja", "zh_TW": "巴布亞新幾內亞", "tr": "Papua Yeni Gine", "ro": "Papua Noua Guinee", "ar": "بابوا غينيا الجديدة", "fa": "پاپوآ گینه نو", "yue": "巴布亚新几内亚" }, flag: "🇵🇬", code: "PG", dialCode: "675", minLength: 11, maxLength: 11, ), Country( name: "Paraguay", nameTranslations: { "sk": "Paraguaj", "se": "Paraguay", "pl": "Paragwaj", "no": "Paraguay", "ja": "パラグアイ", "it": "Paraguay", "zh": "巴拉圭", "nl": "Paraguay", "de": "Paraguay", "fr": "Paraguay", "es": "Paraguay", "en": "Paraguay", "pt_BR": "Paraguai", "sr-Cyrl": "Парагвај", "sr-Latn": "Paragvaj", "zh_TW": "巴拉圭", "tr": "Paraguay", "ro": "Paraguay", "ar": "باراغواي", "fa": "پاراگوئه", "yue": "巴拉圭" }, flag: "🇵🇾", code: "PY", dialCode: "595", minLength: 10, maxLength: 10, ), Country( name: "Peru", nameTranslations: { "sk": "Peru", "se": "Peru", "pl": "Peru", "no": "Peru", "ja": "ペルー", "it": "Perù", "zh": "秘鲁", "nl": "Peru", "de": "Peru", "fr": "Pérou", "es": "Perú", "en": "Peru", "pt_BR": "Peru", "sr-Cyrl": "Перу", "sr-Latn": "Peru", "zh_TW": "秘鲁", "tr": "Peru", "ro": "Peru", "ar": "بيرو", "fa": "پرو", "yue": "秘魯" }, flag: "🇵🇪", code: "PE", dialCode: "51", minLength: 9, maxLength: 9, ), Country( name: "Philippines", nameTranslations: { "sk": "Filipíny", "se": "Filippiinnat", "pl": "Filipiny", "no": "Filippinene", "ja": "フィリピン", "it": "Filippine", "zh": "菲律宾", "nl": "Filipijnen", "de": "Philippinen", "fr": "Philippines", "es": "Filipinas", "en": "Philippines", "pt_BR": "Filipinas", "sr-Cyrl": "Филипини", "sr-Latn": "Filipini", "zh_TW": "菲律賓", "tr": "Filipinler", "ro": "Filipine", "ar": "الفلبين", "fa": "فیلیپین", "yue": "菲律賓" }, flag: "🇵🇭", code: "PH", dialCode: "63", minLength: 10, maxLength: 10, ), Country( name: "Pitcairn", nameTranslations: { "sk": "Pitcairnove ostrovy", "se": "Pitcairn", "pl": "Pitcairn", "no": "Pitcairnøyene", "ja": "ピトケアン諸島", "it": "Isole Pitcairn", "zh": "皮特凯恩群岛", "nl": "Pitcairneilanden", "de": "Pitcairninseln", "fr": "Îles Pitcairn", "es": "Islas Pitcairn", "en": "Pitcairn Islands", "pt_BR": "Ilhas Pitcairn", "sr-Cyrl": "Острва Питкерн", "sr-Latn": "Ostrva Pitkern", "zh_TW": "皮特肯群島", "tr": "Pitcairn Adaları", "ro": "Insulele Pitcairn", "ar": "جزر بيتكيرن", "fa": "جزایر پیت‌کرن", "yue": "皮特凱恩" }, flag: "🇵🇳", code: "PN", dialCode: "64", minLength: 10, maxLength: 10, ), Country( name: "Poland", nameTranslations: { "sk": "Poľsko", "se": "Polen", "pl": "Polska", "no": "Polen", "ja": "ポーランド", "it": "Polonia", "zh": "波兰", "nl": "Polen", "de": "Polen", "fr": "Pologne", "es": "Polonia", "en": "Poland", "pt_BR": "Polônia", "sr-Cyrl": "Пољска", "sr-Latn": "Poljska", "zh_TW": "波蘭", "tr": "Polonya", "ro": "Polonia", "ar": "بولندا", "fa": "لهستان", "yue": "波蘭" }, flag: "🇵🇱", code: "PL", dialCode: "48", minLength: 9, maxLength: 9, ), Country( name: "Portugal", nameTranslations: { "sk": "Portugalsko", "se": "Portugála", "pl": "Portugalia", "no": "Portugal", "ja": "ポルトガル", "it": "Portogallo", "zh": "葡萄牙", "nl": "Portugal", "de": "Portugal", "fr": "Portugal", "es": "Portugal", "en": "Portugal", "pt_BR": "Portugal", "sr-Cyrl": "Португалија", "sr-Latn": "Portugalija", "zh_TW": "葡萄牙", "tr": "Portekiz", "ro": "Portugalia", "ar": "البرتغال", "fa": "پرتغال", "yue": "葡萄牙" }, flag: "🇵🇹", code: "PT", dialCode: "351", minLength: 9, maxLength: 9, ), Country( name: "Puerto Rico", nameTranslations: { "sk": "Portoriko", "se": "Puerto Rico", "pl": "Portoryko", "no": "Puerto Rico", "ja": "プエルトリコ", "it": "Portorico", "zh": "波多黎各", "nl": "Puerto Rico", "de": "Puerto Rico", "fr": "Porto Rico", "es": "Puerto Rico", "en": "Puerto Rico", "pt_BR": "Porto Rico", "sr-Cyrl": "Порто Рико", "sr-Latn": "Porto Riko", "zh_TW": "波多黎各", "tr": "Porto Riko", "ro": "Puerto Rico", "ar": "بورتوريكو", "fa": "پورتوریکو", "yue": "波多黎各" }, flag: "🇵🇷", code: "PR", dialCode: "1939", minLength: 15, maxLength: 15, ), Country( name: "Qatar", nameTranslations: { "sk": "Katar", "se": "Qatar", "pl": "Katar", "no": "Qatar", "ja": "カタール", "it": "Qatar", "zh": "卡塔尔", "nl": "Qatar", "de": "Katar", "fr": "Qatar", "es": "Catar", "en": "Qatar", "pt_BR": "Catar", "sr-Cyrl": "Катар", "sr-Latn": "Katar", "zh_TW": "卡達", "tr": "Katar", "ro": "Qatar", "ar": "قطر", "fa": "قطر", "yue": "卡塔爾" }, flag: "🇶🇦", code: "QA", dialCode: "974", minLength: 8, maxLength: 8, ), Country( name: "Romania", nameTranslations: { "sk": "Rumunsko", "se": "Románia", "pl": "Rumunia", "no": "Romania", "ja": "ルーマニア", "it": "Romania", "zh": "罗马尼亚", "nl": "Roemenië", "de": "Rumänien", "fr": "Roumanie", "es": "Rumanía", "en": "Romania", "pt_BR": "Romênia", "sr-Cyrl": "Румунија", "sr-Latn": "Rumunija", "zh_TW": "羅馬尼亞", "tr": "Romanya", "ro": "România", "ar": "رومانيا", "fa": "رومانی", "yue": "羅馬尼亞" }, flag: "🇷🇴", code: "RO", dialCode: "40", minLength: 9, maxLength: 9, ), Country( name: "Russia", nameTranslations: { "sk": "Rusko", "se": "Ruošša", "pl": "Rosja", "no": "Russland", "ja": "ロシア", "it": "Russia", "zh": "俄罗斯", "nl": "Rusland", "de": "Russland", "fr": "Russie", "es": "Rusia", "en": "Russia", "pt_BR": "Rússia", "sr-Cyrl": "Русија", "sr-Latn": "Rusija", "zh_TW": "俄羅斯", "tr": "Rusya", "ro": "Rusia", "ar": "روسيا", "fa": "روسیه", "yue": "俄儸斯聯邦" }, flag: "🇷🇺", code: "RU", dialCode: "7", minLength: 10, maxLength: 10, ), Country( name: "Rwanda", nameTranslations: { "sk": "Rwanda", "se": "Rwanda", "pl": "Rwanda", "no": "Rwanda", "ja": "ルワンダ", "it": "Ruanda", "zh": "卢旺达", "nl": "Rwanda", "de": "Ruanda", "fr": "Rwanda", "es": "Ruanda", "en": "Rwanda", "pt_BR": "Ruanda", "sr-Cyrl": "Руанда", "sr-Latn": "Ruanda", "zh_TW": "盧安達", "tr": "Ruanda", "ro": "Rwanda", "ar": "رواندا", "fa": "رواندا", "yue": "盧旺達" }, flag: "🇷🇼", code: "RW", dialCode: "250", minLength: 9, maxLength: 9, ), Country( name: "Reunion", nameTranslations: { "sk": "Réunion", "se": "Réunion", "pl": "Reunion", "no": "Réunion", "ja": "レユニオン", "it": "Riunione", "zh": "留尼汪", "nl": "Réunion", "de": "Réunion", "fr": "La Réunion", "es": "Reunión", "en": "Réunion", "pt_BR": "Reunião", "sr-Cyrl": "Реинион", "sr-Latn": "Reinion", "zh_TW": "留尼旺", "tr": "La Réunion", "ro": "La Réunion", "ar": "لا ريونيون", "fa": "رئونیون", "yue": "留尼汪" }, flag: "🇷🇪", code: "RE", dialCode: "262", minLength: 9, maxLength: 9, ), Country( name: "Saint Barthelemy", nameTranslations: { "sk": "Svätý Bartolomej", "se": "Saint Barthélemy", "pl": "Saint-Barthélemy", "no": "Saint-Barthélemy", "ja": "サン・バルテルミー", "it": "Saint-Barthélemy", "zh": "圣巴泰勒米", "nl": "Saint-Barthélemy", "de": "St. Barthélemy", "fr": "Saint-Barthélemy", "es": "San Bartolomé", "en": "St. Barthélemy", "pt_BR": "São Bartolomeu", "sr-Cyrl": "Сент Бартелеми", "sr-Latn": "Sent Bartelemi", "zh_TW": "聖巴瑟米", "tr": "Saint Barthélemy", "ro": "Saint Barthélemy", "ar": "سان بارتيلمي", "fa": "سن بارتلمی", "yue": "聖巴泰勒米" }, flag: "🇧🇱", code: "BL", dialCode: "590", minLength: 9, maxLength: 9, ), Country( name: "Saint Helena, Ascension and Tristan Da Cunha", nameTranslations: { "sk": "Svätá Helena", "se": "Saint Helena", "pl": "Wyspa Świętej Heleny", "no": "St. Helena", "ja": "セントヘレナ", "it": "Sant'Elena", "zh": "圣赫勒拿", "nl": "Sint-Helena", "de": "St. Helena", "fr": "Sainte-Hélène", "es": "Santa Elena", "en": "St. Helena", "pt_BR": "Santa Helena", "sr-Cyrl": "Света Јелена, Асенсион и Тристан да Куња", "sr-Latn": "Sveta Jelena, Asension i Tristan de Kunja", "zh_TW": "聖凱倫拿島", "tr": "Saint Helena", "ro": "Sfânta Elena", "ar": "سانت هيلانة وأسينشين وتريستان دا كونا", "fa": "سنت هلن", "yue": "圣赫勒拿、阿森松同特里斯坦·达库尼亚" }, flag: "🇸🇭", code: "SH", dialCode: "290", minLength: 4, maxLength: 4, ), Country( name: "Saint Kitts and Nevis", nameTranslations: { "sk": "Svätý Krištof a Nevis", "se": "Saint Kitts ja Nevis", "pl": "Saint Kitts i Nevis", "no": "Saint Kitts og Nevis", "ja": "セントクリストファー・ネーヴィス", "it": "Saint Kitts e Nevis", "zh": "圣基茨和尼维斯", "nl": "Saint Kitts en Nevis", "de": "St. Kitts und Nevis", "fr": "Saint-Christophe-et-Niévès", "es": "San Cristóbal y Nieves", "en": "St. Kitts & Nevis", "pt_BR": "São Cristóvão e Nevis", "sr-Cyrl": "Сент Китс и Невис", "sr-Latn": "Sent Kits i Nevis", "zh_TW": "聖克里斯多福及尼維斯", "tr": "Saint Kitts ve Nevis", "ro": "Sfântul Kitts și Nevis", "ar": "سانت كيتس ونيفيس", "fa": "سنت کیتس و نویس", "yue": "圣基茨同尼维斯" }, flag: "🇰🇳", code: "KN", dialCode: "1869", minLength: 7, maxLength: 7, ), Country( name: "Saint Lucia", nameTranslations: { "sk": "Svätá Lucia", "se": "Saint Lucia", "pl": "Saint Lucia", "no": "St. Lucia", "ja": "セントルシア", "it": "Saint Lucia", "zh": "圣卢西亚", "nl": "Saint Lucia", "de": "St. Lucia", "fr": "Sainte-Lucie", "es": "Santa Lucía", "en": "St. Lucia", "pt_BR": "Santa Lúcia", "sr-Cyrl": "Света Луција", "sr-Latn": "Sveta Lucija", "zh_TW": "聖露西亞", "tr": "Saint Lucia", "ro": "Sfânta Elena", "ar": "سانت لوسيا", "fa": "سنت لوسیا", "yue": "聖盧西亞" }, flag: "🇱🇨", code: "LC", dialCode: "1758", minLength: 7, maxLength: 7, ), Country( name: "Saint Martin", nameTranslations: { "sk": "Svätý Martin (fr.)", "se": "Frankriikka Saint Martin", "pl": "Saint-Martin", "no": "Saint-Martin", "ja": "サン・マルタン", "it": "Saint Martin", "zh": "法属圣马丁", "nl": "Saint-Martin", "de": "St. Martin", "fr": "Saint-Martin", "es": "San Martín", "en": "St. Martin", "pt_BR": "São Martinho", "sr-Cyrl": "Свети Мартин", "sr-Latn": "Sveti Martin", "zh_TW": "聖馬丁", "tr": "Saint Martin", "ro": "Sfântul Martin", "ar": "تجمع سان مارتين", "fa": "سن مارتن", "yue": "聖馬丁(法國部分)" }, flag: "🇲🇫", code: "MF", dialCode: "590", minLength: 9, maxLength: 9, ), Country( name: "Saint Pierre and Miquelon", nameTranslations: { "sk": "Saint Pierre a Miquelon", "se": "Saint Pierre ja Miquelon", "pl": "Saint-Pierre i Miquelon", "no": "Saint-Pierre-et-Miquelon", "ja": "サンピエール島・ミクロン島", "it": "Saint-Pierre e Miquelon", "zh": "圣皮埃尔和密克隆群岛", "nl": "Saint-Pierre en Miquelon", "de": "St. Pierre und Miquelon", "fr": "Saint-Pierre-et-Miquelon", "es": "San Pedro y Miquelón", "en": "St. Pierre & Miquelon", "pt_BR": "São Pedro e Miquelon", "sr-Cyrl": "Сен Пјер и Микелон", "sr-Latn": "Sen Pjer i Mikelon", "zh_TW": "聖皮埃與密克隆群島", "tr": "Saint Pierre ve Miquelon", "ro": "Saint Pierre și Miquelon", "ar": "سان بيير وميكلون", "fa": "سن-پیر و میکلون", "yue": "聖皮埃尔同米克隆" }, flag: "🇵🇲", code: "PM", dialCode: "508", minLength: 6, maxLength: 6, ), Country( name: "Saint Vincent and the Grenadines", nameTranslations: { "sk": "Svätý Vincent a Grenadíny", "se": "Saint Vincent ja Grenadine", "pl": "Saint Vincent i Grenadyny", "no": "St. Vincent og Grenadinene", "ja": "セントビンセント及びグレナディーン諸島", "it": "Saint Vincent e Grenadine", "zh": "圣文森特和格林纳丁斯", "nl": "Saint Vincent en de Grenadines", "de": "St. Vincent und die Grenadinen", "fr": "Saint-Vincent-et-les-Grenadines", "es": "San Vicente y las Granadinas", "en": "St. Vincent & Grenadines", "pt_BR": "São Vicente e Granadinas", "sr-Cyrl": "Свети Винсент и Гренадини", "sr-Latn": "Sveti Vinsent i Grenadini", "zh_TW": "聖文森及格瑞那丁", "tr": "Saint Vincent ve Grenadinler", "ro": "Sfântul Vincențiu și Grenadinele", "ar": "سانت فينسنت والغرينادين", "fa": "سنت وینسنت و گرنادین‌ها", "yue": "聖文森特同格林纳丁斯" }, flag: "🇻🇨", code: "VC", dialCode: "1784", minLength: 7, maxLength: 7, ), Country( name: "Samoa", nameTranslations: { "sk": "Samoa", "se": "Samoa", "pl": "Samoa", "no": "Samoa", "ja": "サモア", "it": "Samoa", "zh": "萨摩亚", "nl": "Samoa", "de": "Samoa", "fr": "Samoa", "es": "Samoa", "en": "Samoa", "pt_BR": "Samoa", "sr-Cyrl": "Самоа", "sr-Latn": "Samoa", "zh_TW": "薩摩亞", "tr": "Samoa", "ro": "Samoa", "ar": "ساموا", "fa": "ساموآ", "yue": "薩摩亞" }, flag: "🇼🇸", code: "WS", dialCode: "685", minLength: 7, maxLength: 7, ), Country( name: "San Marino", nameTranslations: { "sk": "San Maríno", "se": "San Marino", "pl": "San Marino", "no": "San Marino", "ja": "サンマリノ", "it": "San Marino", "zh": "圣马力诺", "nl": "San Marino", "de": "San Marino", "fr": "Saint-Marin", "es": "San Marino", "en": "San Marino", "pt_BR": "San Marino", "sr-Cyrl": "Сан Марино", "sr-Latn": "San Marino", "zh_TW": "聖馬利諾", "tr": "San Marino", "ro": "San Marino", "ar": "سان مارينو", "fa": "سان مارینو", "yue": "聖馬力諾" }, flag: "🇸🇲", code: "SM", dialCode: "378", minLength: 10, maxLength: 10, ), Country( name: "Sao Tome and Principe", nameTranslations: { "sk": "Svätý Tomáš a Princov ostrov", "se": "São Tomé ja Príncipe", "pl": "Wyspy Świętego Tomasza i Książęca", "no": "São Tomé og Príncipe", "ja": "サントメ・プリンシペ", "it": "São Tomé e Príncipe", "zh": "圣多美和普林西比", "nl": "Sao Tomé en Principe", "de": "São Tomé und Príncipe", "fr": "Sao Tomé-et-Principe", "es": "Santo Tomé y Príncipe", "en": "São Tomé & Príncipe", "pt_BR": "São Tomé e Príncipe", "sr-Cyrl": "Сао Томе и Принсипе", "sr-Latn": "Sao Tome i Prinsipe", "zh_TW": "聖多美普林西比", "tr": "São Tomé ve Príncipe", "ro": "Sao Tome şi Principe", "ar": "ساو تومي وبرينسيب", "fa": "سائوتومه و پرنسیپ", "yue": "聖多美和普林西比" }, flag: "🇸🇹", code: "ST", dialCode: "239", minLength: 7, maxLength: 7, ), Country( name: "Saudi Arabia", nameTranslations: { "sk": "Saudská Arábia", "se": "Saudi-Arábia", "pl": "Arabia Saudyjska", "no": "Saudi-Arabia", "ja": "サウジアラビア", "it": "Arabia Saudita", "zh": "沙特阿拉伯", "nl": "Saoedi-Arabië", "de": "Saudi-Arabien", "fr": "Arabie saoudite", "es": "Arabia Saudí", "en": "Saudi Arabia", "pt_BR": "Arábia Saudita", "sr-Cyrl": "Саудијска Арабија", "sr-Latn": "Saudijska Arabija", "zh_TW": "沙烏地阿拉", "tr": "Suudi Arabistan", "ro": "Arabia Saudită", "ar": "السعودية", "fa": "عربستان سعودی", "yue": "沙地阿拉伯" }, flag: "🇸🇦", code: "SA", dialCode: "966", minLength: 9, maxLength: 9, ), Country( name: "Senegal", nameTranslations: { "sk": "Senegal", "se": "Senegal", "pl": "Senegal", "no": "Senegal", "ja": "セネガル", "it": "Senegal", "zh": "塞内加尔", "nl": "Senegal", "de": "Senegal", "fr": "Sénégal", "es": "Senegal", "en": "Senegal", "pt_BR": "Senegal", "sr-Cyrl": "Сенегал", "sr-Latn": "Senegal", "zh_TW": "塞內加爾", "tr": "Senegal", "ro": "Senegal", "ar": "السنغال", "fa": "سنگال", "yue": "塞內加爾" }, flag: "🇸🇳", code: "SN", dialCode: "221", minLength: 9, maxLength: 9, ), Country( name: "Serbia", nameTranslations: { "sk": "Srbsko", "se": "Serbia", "pl": "Serbia", "no": "Serbia", "ja": "セルビア", "it": "Serbia", "zh": "塞尔维亚", "nl": "Servië", "de": "Serbien", "fr": "Serbie", "es": "Serbia", "en": "Serbia", "pt_BR": "Sérvia", "sr-Cyrl": "Србија", "sr-Latn": "Srbija", "zh_TW": "塞爾維亞", "tr": "Sırbistan", "ro": "Serbia", "ar": "صربيا", "fa": "صربستان", "yue": "塞爾維亞" }, flag: "🇷🇸", code: "RS", dialCode: "381", minLength: 12, maxLength: 12, ), Country( name: "Seychelles", nameTranslations: { "sk": "Seychely", "se": "Seychellsullot", "pl": "Seszele", "no": "Seychellene", "ja": "セーシェル", "it": "Seychelles", "zh": "塞舌尔", "nl": "Seychellen", "de": "Seychellen", "fr": "Seychelles", "es": "Seychelles", "en": "Seychelles", "pt_BR": "Seychelles", "sr-Cyrl": "Сејшели", "sr-Latn": "Sejšeli", "zh_TW": "塞席爾", "tr": "Seyşeller", "ro": "Seychelles", "ar": "سيشل", "fa": "سیشل", "yue": "塞舌爾" }, flag: "🇸🇨", code: "SC", dialCode: "248", minLength: 6, maxLength: 6, ), Country( name: "Sierra Leone", nameTranslations: { "sk": "Sierra Leone", "se": "Sierra Leone", "pl": "Sierra Leone", "no": "Sierra Leone", "ja": "シエラレオネ", "it": "Sierra Leone", "zh": "塞拉利昂", "nl": "Sierra Leone", "de": "Sierra Leone", "fr": "Sierra Leone", "es": "Sierra Leona", "en": "Sierra Leone", "pt_BR": "Serra Leoa", "sr-Cyrl": "Сијера Леоне", "sr-Latn": "Sijera Leone", "zh_TW": "獅子山", "tr": "Sierra Leone", "ro": "Sierra Leone", "ar": "سيراليون", "fa": "سیرالئون", "yue": "塞拉利昂" }, flag: "🇸🇱", code: "SL", dialCode: "232", minLength: 8, maxLength: 8, ), Country( name: "Singapore", nameTranslations: { "sk": "Singapur", "se": "Singapore", "pl": "Singapur", "no": "Singapore", "ja": "シンガポール", "it": "Singapore", "zh": "新加坡", "nl": "Singapore", "de": "Singapur", "fr": "Singapour", "es": "Singapur", "en": "Singapore", "pt_BR": "Cingapura", "sr-Cyrl": "Сингапур", "sr-Latn": "Singapur", "zh_TW": "新加坡", "tr": "Singapur", "ro": "Singapore", "ar": "سنغافورة", "fa": "سنگاپور", "yue": "星架坡" }, flag: "🇸🇬", code: "SG", dialCode: "65", minLength: 8, maxLength: 8, ), Country( name: "Slovakia", nameTranslations: { "sk": "Slovensko", "se": "Slovákia", "pl": "Słowacja", "no": "Slovakia", "ja": "スロバキア", "it": "Slovacchia", "zh": "斯洛伐克", "nl": "Slowakije", "de": "Slowakei", "fr": "Slovaquie", "es": "Eslovaquia", "en": "Slovakia", "pt_BR": "Eslováquia", "sr-Cyrl": "Словачка", "sr-Latn": "Slovačka", "zh_TW": "斯洛伐克", "tr": "Slovakya", "ro": "Slovacia", "ar": "سلوفاكيا", "fa": "اسلواکی", "yue": "斯洛伐克" }, flag: "🇸🇰", code: "SK", dialCode: "421", minLength: 9, maxLength: 9, ), Country( name: "Slovenia", nameTranslations: { "sk": "Slovinsko", "se": "Slovenia", "pl": "Słowenia", "no": "Slovenia", "ja": "スロベニア", "it": "Slovenia", "zh": "斯洛文尼亚", "nl": "Slovenië", "de": "Slowenien", "fr": "Slovénie", "es": "Eslovenia", "en": "Slovenia", "pt_BR": "Eslovênia", "sr-Cyrl": "Словеније", "sr-Latn": "Slovenija", "zh_TW": "斯洛維尼亞", "tr": "Slovenya", "ro": "Slovenia", "ar": "سلوفينيا", "fa": "اسلوونی", "yue": "斯洛文尼亞" }, flag: "🇸🇮", code: "SI", dialCode: "386", minLength: 8, maxLength: 8, ), Country( name: "Solomon Islands", nameTranslations: { "sk": "Šalamúnove ostrovy", "se": "Salomon-sullot", "pl": "Wyspy Salomona", "no": "Salomonøyene", "ja": "ソロモン諸島", "it": "Isole Salomone", "zh": "所罗门群岛", "nl": "Salomonseilanden", "de": "Salomonen", "fr": "Îles Salomon", "es": "Islas Salomón", "en": "Solomon Islands", "pt_BR": "Ilhas Salomão", "sr-Cyrl": "Соломонска Острва", "sr-Latn": "Solomonska Ostrva", "zh_TW": "所羅門群島", "tr": "Solomon Adaları", "ro": "Insulele Solomon", "ar": "جزر سليمان", "fa": "جزایر سلیمان", "yue": "所羅門群島" }, flag: "🇸🇧", code: "SB", dialCode: "677", minLength: 5, maxLength: 5, ), Country( name: "Somalia", nameTranslations: { "sk": "Somálsko", "se": "Somália", "pl": "Somalia", "no": "Somalia", "ja": "ソマリア", "it": "Somalia", "zh": "索马里", "nl": "Somalië", "de": "Somalia", "fr": "Somalie", "es": "Somalia", "en": "Somalia", "pt_BR": "Somália", "sr-Cyrl": "Сомалија", "sr-Latn": "Somalija", "zh_TW": "索馬利亞", "tr": "Somali", "ro": "Somalia", "ar": "الصومال", "fa": "سومالی", "yue": "索馬里" }, flag: "🇸🇴", code: "SO", dialCode: "252", minLength: 8, maxLength: 8, ), Country( name: "South Africa", nameTranslations: { "sk": "Južná Afrika", "se": "Mátta-Afrihká", "pl": "Republika Południowej Afryki", "no": "Sør-Afrika", "ja": "南アフリカ", "it": "Sudafrica", "zh": "南非", "nl": "Zuid-Afrika", "de": "Südafrika", "fr": "Afrique du Sud", "es": "Sudáfrica", "en": "South Africa", "pt_BR": "África do Sul", "sr-Cyrl": "Јужноафричка Република", "sr-Latn": "Južnoafrička Republika", "zh_TW": "南非", "tr": "Güney Afrika", "ro": "Africa de Sud", "ar": "جنوب أفريقيا", "fa": "آفریقای جنوبی", "yue": "南非" }, flag: "🇿🇦", code: "ZA", dialCode: "27", minLength: 9, maxLength: 9, ), Country( name: "South Sudan", nameTranslations: { "sk": "Južný Sudán", "se": "Máttasudan", "pl": "Sudan Południowy", "no": "Sør-Sudan", "ja": "南スーダン", "it": "Sud Sudan", "zh": "南苏丹", "nl": "Zuid-Soedan", "de": "Südsudan", "fr": "Soudan du Sud", "es": "Sudán del Sur", "en": "South Sudan", "pt_BR": "Sudão do Sul", "sr-Cyrl": "Јужни Судан", "sr-Latn": "Južni Sudan", "zh_TW": "南蘇丹", "tr": "Güney Sudan", "ro": "Sudanul de Sud", "ar": "جنوب السودان", "fa": "سودان جنوبی", "yue": "南蘇丹" }, flag: "🇸🇸", code: "SS", dialCode: "211", minLength: 9, maxLength: 9, ), Country( name: "South Georgia and the South Sandwich Islands", nameTranslations: { "sk": "Južná Georgia a Južné Sandwichove ostrovy", "se": "Lulli Georgia ja Lulli Sandwich-sullot", "pl": "Georgia Południowa i Sandwich Południowy", "no": "Sør-Georgia og Sør-Sandwichøyene", "ja": "サウスジョージア・サウスサンドウィッチ諸島", "it": "Georgia del Sud e Sandwich australi", "zh": "南乔治亚和南桑威奇群岛", "nl": "Zuid-Georgia en Zuidelijke Sandwicheilanden", "de": "Südgeorgien und die Südlichen Sandwichinseln", "fr": "Géorgie du Sud et îles Sandwich du Sud", "es": "Islas Georgia del Sur y Sandwich del Sur", "en": "South Georgia & South Sandwich Islands", "pt_BR": "Geórgia do Sul e Ilhas Sandwich do Sul", "sr-Cyrl": "Јужна Џорџија и Јужна Сендвичка Острва", "sr-Latn": "Južna Džordžija i Južna Sendvička Ostrva", "zh_TW": "南喬治亞與南三明治群島 ", "tr": "Güney Georgia ve Güney Sandwich Adaları", "ro": "Georgia de Sud și Insulele Sandwich de Sud", "ar": "جورجيا الجنوبية وجزر ساندويتش الجنوبية", "fa": "جزایر جورجیای جنوبی و ساندویچ جنوبی", "yue": "南喬治亞州同南桑威奇群島" }, flag: "🇬🇸", code: "GS", dialCode: "500", minLength: 15, maxLength: 15, ), Country( name: "Spain", nameTranslations: { "sk": "Španielsko", "se": "Spánia", "pl": "Hiszpania", "no": "Spania", "ja": "スペイン", "it": "Spagna", "zh": "西班牙", "nl": "Spanje", "de": "Spanien", "fr": "Espagne", "es": "España", "en": "Spain", "pt_BR": "Espanha", "sr-Cyrl": "Шпанија", "sr-Latn": "Španija", "zh_TW": "西班牙", "tr": "İspanya", "ro": "Spania", "ar": "إسبانيا", "fa": "اسپانیا", "yue": "西班牙" }, flag: "🇪🇸", code: "ES", dialCode: "34", minLength: 9, maxLength: 9, ), Country( name: "Sri Lanka", nameTranslations: { "sk": "Srí Lanka", "se": "Sri Lanka", "pl": "Sri Lanka", "no": "Sri Lanka", "ja": "スリランカ", "it": "Sri Lanka", "zh": "斯里兰卡", "nl": "Sri Lanka", "de": "Sri Lanka", "fr": "Sri Lanka", "es": "Sri Lanka", "en": "Sri Lanka", "pt_BR": "Sri Lanka", "sr-Cyrl": "Шри Ланка", "sr-Latn": "Šri Lanka", "zh_TW": "斯里蘭卡", "tr": "Sri Lanka", "ro": "Sri Lanka", "ar": "سريلانكا", "fa": "سریلانکا", "yue": "斯里蘭卡" }, flag: "🇱🇰", code: "LK", dialCode: "94", minLength: 9, maxLength: 9, ), Country( name: "Sudan", nameTranslations: { "sk": "Sudán", "se": "Davvisudan", "pl": "Sudan", "no": "Sudan", "ja": "スーダン", "it": "Sudan", "zh": "苏丹", "nl": "Soedan", "de": "Sudan", "fr": "Soudan", "es": "Sudán", "en": "Sudan", "pt_BR": "Sudão", "sr-Cyrl": "Судан", "sr-Latn": "Sudan", "zh_TW": "蘇丹", "tr": "Sudan", "ro": "Sudan", "ar": "السودان", "fa": "سودان", "yue": "蘇丹" }, flag: "🇸🇩", code: "SD", dialCode: "249", minLength: 9, maxLength: 9, ), Country( name: "Suriname", nameTranslations: { "sk": "Surinam", "se": "Surinam", "pl": "Surinam", "no": "Surinam", "ja": "スリナム", "it": "Suriname", "zh": "苏里南", "nl": "Suriname", "de": "Suriname", "fr": "Suriname", "es": "Surinam", "en": "Suriname", "pt_BR": "Suriname", "sr-Cyrl": "Суринам", "sr-Latn": "Surinam", "zh_TW": "蘇利南", "tr": "Surinam", "ro": "Surinam", "ar": "سورينام", "fa": "سورینام", "yue": "蘇里南" }, flag: "🇸🇷", code: "SR", dialCode: "597", minLength: 7, maxLength: 7, ), Country( name: "Svalbard and Jan Mayen", nameTranslations: { "sk": "Svalbard a Jan Mayen", "se": "Svalbárda ja Jan Mayen", "pl": "Svalbard i Jan Mayen", "no": "Svalbard og Jan Mayen", "ja": "スバールバル諸島・ヤンマイエン島", "it": "Svalbard e Jan Mayen", "zh": "斯瓦尔巴和扬马延", "nl": "Spitsbergen en Jan Mayen", "de": "Spitzbergen und Jan Mayen", "fr": "Svalbard et Jan Mayen", "es": "Svalbard y Jan Mayen", "en": "Svalbard & Jan Mayen", "pt_BR": "Svalbard e Jan Mayen", "sr-Cyrl": "Свалбард", "sr-Latn": "Svalbard", "zh_TW": "斯瓦巴及尖棉", "tr": "Svalbard ve Jan Mayen", "ro": "Svalbard și Jan Mayen", "ar": "سفالبارد ويان ماين", "fa": "سوالبارد و یان ماین", "yue": "斯瓦尔巴德同扬·马延" }, flag: "🇸🇯", code: "SJ", dialCode: "47", minLength: 8, maxLength: 8, ), Country( name: "Eswatini", nameTranslations: { "sk": "Eswatini", "se": "Svazieana", "pl": "Eswatini", "no": "Eswatini", "ja": "エスワティニ", "it": "Swaziland", "zh": "斯威士兰", "nl": "eSwatini", "de": "Eswatini", "fr": "Eswatini", "es": "Esuatini", "en": "Eswatini", "pt_BR": "Eswatini", "sr-Cyrl": "Свазиланд", "sr-Latn": "Svaziland", "zh_TW": "史瓦帝尼", "tr": "Esvatini", "ro": "Eswatini", "ar": "إسواتيني", "fa": "اسواتینی", "yue": "斯威士蘭" }, flag: "🇸🇿", code: "SZ", dialCode: "268", minLength: 8, maxLength: 8, ), Country( name: "Sweden", nameTranslations: { "sk": "Švédsko", "se": "Ruoŧŧa", "pl": "Szwecja", "no": "Sverige", "ja": "スウェーデン", "it": "Svezia", "zh": "瑞典", "nl": "Zweden", "de": "Schweden", "fr": "Suède", "es": "Suecia", "en": "Sweden", "pt_BR": "Suécia", "sr-Cyrl": "Шведска", "sr-Latn": "Švedska", "zh_TW": "瑞典", "tr": "İsveç", "ro": "Suedia", "ar": "السويد", "fa": "سوئد", "yue": "瑞典" }, flag: "🇸🇪", code: "SE", dialCode: "46", minLength: 7, maxLength: 13, ), Country( name: "Switzerland", nameTranslations: { "sk": "Švajčiarsko", "se": "Šveica", "pl": "Szwajcaria", "no": "Sveits", "ja": "スイス", "it": "Svizzera", "zh": "瑞士", "nl": "Zwitserland", "de": "Schweiz", "fr": "Suisse", "es": "Suiza", "en": "Switzerland", "pt_BR": "Suíça", "sr-Cyrl": "Швајцарска", "sr-Latn": "Švajcarska", "zh_TW": "瑞士", "tr": "İsviçre", "ro": "Elveţia", "ar": "سويسرا", "fa": "سوئیس", "yue": "瑞士" }, flag: "🇨🇭", code: "CH", dialCode: "41", minLength: 9, maxLength: 12, ), Country( name: "Syrian Arab Republic", nameTranslations: { "sk": "Sýria", "se": "Syria", "pl": "Syria", "no": "Syria", "ja": "シリア", "it": "Siria", "zh": "叙利亚", "nl": "Syrië", "de": "Syrien", "fr": "Syrie", "es": "Siria", "en": "Syria", "pt_BR": "Síria", "sr-Cyrl": "Сирија", "sr-Latn": "Sirija", "zh_TW": "敘利亞", "tr": "Suriye", "ro": "Siria", "ar": "سوريا", "fa": "سوریه", "yue": "阿拉伯敘利亞共和國" }, flag: "🇸🇾", code: "SY", dialCode: "963", minLength: 9, maxLength: 10, ), Country( name: "Taiwan", nameTranslations: { "sk": "Taiwan", "se": "Taiwan", "pl": "Tajwan", "no": "Taiwan", "ja": "台湾", "it": "Taiwan", "zh": "台湾", "nl": "Taiwan", "de": "Taiwan", "fr": "Taïwan", "es": "Taiwán", "en": "Taiwan", "pt_BR": "Taiwan", "sr-Cyrl": "Тајван", "sr-Latn": "Tajvan", "zh_TW": "台灣", "tr": "Tayvan", "ro": "Taiwan", "ar": "تايوان", "fa": "تایوان", "yue": "台灣" }, flag: "🇹🇼", code: "TW", dialCode: "886", minLength: 9, maxLength: 9, ), Country( name: "Tajikistan", nameTranslations: { "sk": "Tadžikistan", "se": "Tažikistan", "pl": "Tadżykistan", "no": "Tadsjikistan", "ja": "タジキスタン", "it": "Tagikistan", "zh": "塔吉克斯坦", "nl": "Tadzjikistan", "de": "Tadschikistan", "fr": "Tadjikistan", "es": "Tayikistán", "en": "Tajikistan", "pt_BR": "Tajiquistão", "sr-Cyrl": "Таџикистан", "sr-Latn": "Tadžikistan", "zh_TW": "塔吉克", "tr": "Tacikistan", "ro": "Tadiquistão", "ar": "طاجيكستان", "fa": "تاجیکستان", "yue": "塔吉克斯坦" }, flag: "🇹🇯", code: "TJ", dialCode: "992", minLength: 9, maxLength: 9, ), Country( name: "Tanzania, United Republic of Tanzania", nameTranslations: { "sk": "Tanzánia", "se": "Tanzánia", "pl": "Tanzania", "no": "Tanzania", "ja": "タンザニア", "it": "Tanzania", "zh": "坦桑尼亚", "nl": "Tanzania", "de": "Tansania", "fr": "Tanzanie", "es": "Tanzania", "en": "Tanzania", "pt_BR": "Tanzânia", "sr-Cyrl": "Танзанија", "sr-Latn": "Tanzanija", "zh_TW": "坦尚尼亞", "tr": "Tanzanya", "ro": "Tanzania", "ar": "تنزانيا", "fa": "تانزانیا", "yue": "坦桑尼亞,聯合共和國" }, flag: "🇹🇿", code: "TZ", dialCode: "255", minLength: 9, maxLength: 9, ), Country( name: "Thailand", nameTranslations: { "sk": "Thajsko", "se": "Thaieana", "pl": "Tajlandia", "no": "Thailand", "ja": "タイ", "it": "Thailandia", "zh": "泰国", "nl": "Thailand", "de": "Thailand", "fr": "Thaïlande", "es": "Tailandia", "en": "Thailand", "pt_BR": "Tailândia", "sr-Cyrl": "Тајланд", "sr-Latn": "Tajland", "zh_TW": "泰國", "tr": "Tayland", "ro": "Tailanda", "ar": "تايلاند", "fa": "تایلند", "yue": "泰國" }, flag: "🇹🇭", code: "TH", dialCode: "66", minLength: 9, maxLength: 9, ), Country( name: "Timor-Leste", nameTranslations: { "sk": "Východný Timor", "se": "Nuorta-Timor", "pl": "Timor Wschodni", "no": "Øst-Timor", "ja": "東ティモール", "it": "Timor Est", "zh": "东帝汶", "nl": "Oost-Timor", "de": "Timor-Leste", "fr": "Timor oriental", "es": "Timor-Leste", "en": "Timor-Leste", "pt_BR": "Timor-Leste", "sr-Cyrl": "Источни Тимор", "sr-Latn": "Istočni Timor", "zh_TW": "東帝汶", "tr": "Doğu Timor", "ro": "Timorul de Est", "ar": "تيمور الشرقية", "fa": "تیمور شرقی", "yue": "東帝汶" }, flag: "🇹🇱", code: "TL", dialCode: "670", minLength: 7, maxLength: 7, ), Country( name: "Togo", nameTranslations: { "sk": "Togo", "se": "Togo", "pl": "Togo", "no": "Togo", "ja": "トーゴ", "it": "Togo", "zh": "多哥", "nl": "Togo", "de": "Togo", "fr": "Togo", "es": "Togo", "en": "Togo", "pt_BR": "Ir", "sr-Cyrl": "Того", "sr-Latn": "Togo", "zh_TW": "多哥", "tr": "Togo", "ro": "Togo", "ar": "توغو", "fa": "توگو", "yue": "多哥" }, flag: "🇹🇬", code: "TG", dialCode: "228", minLength: 8, maxLength: 8, ), Country( name: "Tokelau", nameTranslations: { "sk": "Tokelau", "se": "Tokelau", "pl": "Tokelau", "no": "Tokelau", "ja": "トケラウ", "it": "Tokelau", "zh": "托克劳", "nl": "Tokelau", "de": "Tokelau", "fr": "Tokelau", "es": "Tokelau", "en": "Tokelau", "pt_BR": "Tokelau", "sr-Cyrl": "Токелау", "sr-Latn": "Tokelau", "zh_TW": "托克勞", "tr": "Tokelau", "ro": "Tokelau", "ar": "توكيلاو", "fa": "توکلائو", "yue": "托克劳" }, flag: "🇹🇰", code: "TK", dialCode: "690", minLength: 4, maxLength: 4, ), Country( name: "Tonga", nameTranslations: { "sk": "Tonga", "se": "Tonga", "pl": "Tonga", "no": "Tonga", "ja": "トンガ", "it": "Tonga", "zh": "汤加", "nl": "Tonga", "de": "Tonga", "fr": "Tonga", "es": "Tonga", "en": "Tonga", "pt_BR": "Tonga", "sr-Cyrl": "Тонга", "sr-Latn": "Tonga", "zh_TW": "東加", "tr": "Tonga", "ro": "Tonga", "ar": "تونغا", "fa": "تونگا", "yue": "湯加" }, flag: "🇹🇴", code: "TO", dialCode: "676", minLength: 7, maxLength: 7, ), Country( name: "Trinidad and Tobago", nameTranslations: { "sk": "Trinidad a Tobago", "se": "Trinidad ja Tobago", "pl": "Trynidad i Tobago", "no": "Trinidad og Tobago", "ja": "トリニダード・トバゴ", "it": "Trinidad e Tobago", "zh": "特立尼达和多巴哥", "nl": "Trinidad en Tobago", "de": "Trinidad und Tobago", "fr": "Trinité-et-Tobago", "es": "Trinidad y Tobago", "en": "Trinidad & Tobago", "pt_BR": "Trinidad e Tobago", "sr-Cyrl": "Тринидад и Тобаго", "sr-Latn": "Trinidad i Tobago", "zh_TW": "千里達及托巴哥", "tr": "Trinidad ve Tobago", "ro": "Trinidad şi Tobago", "ar": "ترينيداد وتوباغو", "fa": "ترینیداد و توباگو", "yue": "特立尼達和多巴哥" }, flag: "🇹🇹", code: "TT", dialCode: "1868", minLength: 7, maxLength: 7, ), Country( name: "Tunisia", nameTranslations: { "sk": "Tunisko", "se": "Tunisia", "pl": "Tunezja", "no": "Tunisia", "ja": "チュニジア", "it": "Tunisia", "zh": "突尼斯", "nl": "Tunesië", "de": "Tunesien", "fr": "Tunisie", "es": "Túnez", "en": "Tunisia", "pt_BR": "Tunísia", "sr-Cyrl": "Тунис", "sr-Latn": "Tunis", "zh_TW": "突尼西亞", "tr": "Tunus", "ro": "Tunisia", "ar": "تونس", "fa": "تونس", "yue": "突尼斯" }, flag: "🇹🇳", code: "TN", dialCode: "216", minLength: 8, maxLength: 8, ), Country( name: "Turkey", nameTranslations: { "sk": "Turecko", "se": "Durka", "pl": "Turcja", "no": "Tyrkia", "ja": "トルコ", "it": "Turchia", "zh": "土耳其", "nl": "Turkije", "de": "Türkei", "fr": "Turquie", "es": "Turquía", "en": "Turkey", "pt_BR": "Peru", "sr-Cyrl": "Турска", "sr-Latn": "Turska", "zh_TW": "土耳其", "tr": "Türkiye", "ro": "Turcia", "ar": "تركيا", "fa": "ترکیه", "yue": "土耳其" }, flag: "🇹🇷", code: "TR", dialCode: "90", minLength: 10, maxLength: 10, ), Country( name: "Turkmenistan", nameTranslations: { "sk": "Turkménsko", "se": "Turkmenistan", "pl": "Turkmenistan", "no": "Turkmenistan", "ja": "トルクメニスタン", "it": "Turkmenistan", "zh": "土库曼斯坦", "nl": "Turkmenistan", "de": "Turkmenistan", "fr": "Turkménistan", "es": "Turkmenistán", "en": "Turkmenistan", "pt_BR": "Turcomenistão", "sr-Cyrl": "Туркменистан", "sr-Latn": "Turkmenistan", "zh_TW": "土庫曼", "tr": "Türkmenistan", "ro": "Turkmenistan", "ar": "تركمانستان", "fa": "ترکمنستان", "yue": "土庫曼斯坦" }, flag: "🇹🇲", code: "TM", dialCode: "993", minLength: 8, maxLength: 8, ), Country( name: "Turks and Caicos Islands", nameTranslations: { "sk": "Turks a Caicos", "se": "Turks ja Caicos-sullot", "pl": "Turks i Caicos", "no": "Turks- og Caicosøyene", "ja": "タークス・カイコス諸島", "it": "Isole Turks e Caicos", "zh": "特克斯和凯科斯群岛", "nl": "Turks- en Caicoseilanden", "de": "Turks- und Caicosinseln", "fr": "Îles Turques-et-Caïques", "es": "Islas Turcas y Caicos", "en": "Turks & Caicos Islands", "pt_BR": "Ilhas Turks e Caicos", "sr-Cyrl": "Туркс и Кајкос", "sr-Latn": "Turks i Kajkos", "zh_TW": "土克斯及開科斯群島", "tr": "Turks ve Caicos Adaları", "ro": "Insulele Turks și Caicos", "ar": "جزر توركس وكايكوس", "fa": "جزایر تورکس و کایکوس", "yue": "特克斯同凯科斯群岛" }, flag: "🇹🇨", code: "TC", dialCode: "1649", minLength: 7, maxLength: 7, ), Country( name: "Tuvalu", nameTranslations: { "sk": "Tuvalu", "se": "Tuvalu", "pl": "Tuvalu", "no": "Tuvalu", "ja": "ツバル", "it": "Tuvalu", "zh": "图瓦卢", "nl": "Tuvalu", "de": "Tuvalu", "fr": "Tuvalu", "es": "Tuvalu", "en": "Tuvalu", "pt_BR": "Tuvalu", "sr-Cyrl": "Тувалу", "sr-Latn": "Tuvalu", "zh_TW": "圖瓦盧", "tr": "Tuvalu", "ro": "Tuvalu", "ar": "توفالو", "fa": "تووالو", "yue": "圖瓦盧" }, flag: "🇹🇻", code: "TV", dialCode: "688", minLength: 6, maxLength: 6, ), Country( name: "Uganda", nameTranslations: { "sk": "Uganda", "se": "Uganda", "pl": "Uganda", "no": "Uganda", "ja": "ウガンダ", "it": "Uganda", "zh": "乌干达", "nl": "Oeganda", "de": "Uganda", "fr": "Ouganda", "es": "Uganda", "en": "Uganda", "pt_BR": "Uganda", "sr-Cyrl": "Уганда", "sr-Latn": "Uganda", "zh_TW": "烏干達", "tr": "Uganda", "ro": "Uganda", "ar": "أوغندا", "fa": "اوگاندا", "yue": "烏干達" }, flag: "🇺🇬", code: "UG", dialCode: "256", minLength: 9, maxLength: 9, ), Country( name: "Ukraine", nameTranslations: { "sk": "Ukrajina", "se": "Ukraina", "pl": "Ukraina", "no": "Ukraina", "ja": "ウクライナ", "it": "Ucraina", "zh": "乌克兰", "nl": "Oekraïne", "de": "Ukraine", "fr": "Ukraine", "es": "Ucrania", "en": "Ukraine", "pt_BR": "Ucrânia", "sr-Cyrl": "Украјина", "sr-Latn": "Ukrajina", "zh_TW": "烏克蘭", "tr": "Ukrayna", "ro": "Ucraína", "ar": "أوكرانيا", "fa": "اوکراین", "yue": "烏克蘭" }, flag: "🇺🇦", code: "UA", dialCode: "380", minLength: 9, maxLength: 9, ), Country( name: "United Arab Emirates", nameTranslations: { "sk": "Spojené arabské emiráty", "se": "Ovttastuvvan Arábaemiráhtat", "pl": "Zjednoczone Emiraty Arabskie", "no": "De forente arabiske emirater", "ja": "アラブ首長国連邦", "it": "Emirati Arabi Uniti", "zh": "阿拉伯联合酋长国", "nl": "Verenigde Arabische Emiraten", "de": "Vereinigte Arabische Emirate", "fr": "Émirats arabes unis", "es": "Emiratos Árabes Unidos", "en": "United Arab Emirates", "pt_BR": "Emirados Árabes Unidos", "sr-Cyrl": "Уједињени Арапски Емирати", "sr-Latn": "Ujedinjeni Arapski Emirati", "zh_TW": "阿拉伯聯合大公國", "tr": "Birleşik Arap Emirlikleri", "ro": "Emiratele Arabe Unite", "ar": "الإمارات العربية المتحدة", "fa": "امارات متحده عربی", "yue": "阿拉伯聯合酋長國" }, flag: "🇦🇪", code: "AE", dialCode: "971", minLength: 9, maxLength: 9, ), Country( name: "United Kingdom", nameTranslations: { "sk": "Spojené kráľovstvo", "se": "Stuorra-Británnia", "pl": "Wielka Brytania", "no": "Storbritannia", "ja": "イギリス", "it": "Regno Unito", "zh": "英国", "nl": "Verenigd Koninkrijk", "de": "Vereinigtes Königreich", "fr": "Royaume-Uni", "es": "Reino Unido", "en": "United Kingdom", "pt_BR": "Reino Unido", "sr-Cyrl": "Уједињено Краљевство", "sr-Latn": "Ujedinjeno Kraljevstvo", "zh_TW": "英國", "tr": "Büyük Britanya ve Kuzey İrlanda Birleşik Krallığ", "ro": "Regatul Unit al Marii Britanii și Irlandei de Nord", "ar": "المملكة المتحدة", "fa": "بریتانیا", "yue": "大不列顛及北愛爾蘭聯合王國" }, flag: "🇬🇧", code: "GB", dialCode: "44", minLength: 10, maxLength: 10, ), Country( name: "United States", nameTranslations: { "sk": "Spojené štáty", "se": "Amerihká ovttastuvvan stáhtat", "pl": "Stany Zjednoczone", "no": "USA", "ja": "アメリカ合衆国", "it": "Stati Uniti", "zh": "美国", "nl": "Verenigde Staten", "de": "Vereinigte Staaten", "fr": "États-Unis", "es": "Estados Unidos", "en": "United States", "pt_BR": "Estados Unidos", "sr-Cyrl": "Сједињене Америчке Државе", "sr-Latn": "Sjedinjene Američke Države", "zh_TW": "美國", "tr": "Amerika Birleşik Devletleri", "ro": "Statele Unite ale Americii", "ar": "الولايات المتحدة", "fa": "ایالات متحده آمریکا", "yue": "美利堅郃眾囯" }, flag: "🇺🇸", code: "US", dialCode: "1", minLength: 10, maxLength: 10, ), Country( name: "Uruguay", nameTranslations: { "sk": "Uruguaj", "se": "Uruguay", "pl": "Urugwaj", "no": "Uruguay", "ja": "ウルグアイ", "it": "Uruguay", "zh": "乌拉圭", "nl": "Uruguay", "de": "Uruguay", "fr": "Uruguay", "es": "Uruguay", "en": "Uruguay", "pt_BR": "Uruguai", "sr-Cyrl": "Уругвај", "sr-Latn": "Urugvaj", "zh_TW": "烏拉圭", "tr": "Uruguay", "ro": "Uruguay", "ar": "الأوروغواي", "fa": "اروگوئه", "yue": "烏拉圭" }, flag: "🇺🇾", code: "UY", dialCode: "598", minLength: 9, maxLength: 9, ), Country( name: "Uzbekistan", nameTranslations: { "sk": "Uzbekistan", "se": "Usbekistan", "pl": "Uzbekistan", "no": "Usbekistan", "ja": "ウズベキスタン", "it": "Uzbekistan", "zh": "乌兹别克斯坦", "nl": "Oezbekistan", "de": "Usbekistan", "fr": "Ouzbékistan", "es": "Uzbekistán", "en": "Uzbekistan", "pt_BR": "Uzbequistão", "sr-Cyrl": "Узбекистан", "sr-Latn": "Uzbekistan", "zh_TW": "烏玆別克", "tr": "Özbekistan", "ro": "Uzbekistan", "ar": "أوزبكستان", "fa": "ازبکستان", "yue": "月即別" }, flag: "🇺🇿", code: "UZ", dialCode: "998", minLength: 9, maxLength: 9, ), Country( name: "Vanuatu", nameTranslations: { "sk": "Vanuatu", "se": "Vanuatu", "pl": "Vanuatu", "no": "Vanuatu", "ja": "バヌアツ", "it": "Vanuatu", "zh": "瓦努阿图", "nl": "Vanuatu", "de": "Vanuatu", "fr": "Vanuatu", "es": "Vanuatu", "en": "Vanuatu", "pt_BR": "Vanuatu", "sr-Cyrl": "Вануату", "sr-Latn": "Vanuatu", "zh_TW": "瓦努阿圖", "tr": "Vanuatu", "ro": "Vanuatu", "ar": "فانواتو", "fa": "وانواتو", "yue": "瓦努阿圖" }, flag: "🇻🇺", code: "VU", dialCode: "678", minLength: 7, maxLength: 7, ), Country( name: "Venezuela, Bolivarian Republic of Venezuela", nameTranslations: { "sk": "Venezuela", "se": "Venezuela", "pl": "Wenezuela", "no": "Venezuela", "ja": "ベネズエラ", "it": "Venezuela", "zh": "委内瑞拉", "nl": "Venezuela", "de": "Venezuela", "fr": "Venezuela", "es": "Venezuela", "en": "Venezuela", "pt_BR": "Venezuela", "sr-Cyrl": "Венецуела", "sr-Latn": "Venecuela", "zh_TW": "委內瑞拉", "tr": "Venezuela", "ro": "Venezuela", "ar": "فنزويلا", "fa": "ونزوئلا", "yue": "委內瑞拉(玻利瓦爾共和國)" }, flag: "🇻🇪", code: "VE", dialCode: "58", minLength: 10, maxLength: 10, ), Country( name: "Vietnam", nameTranslations: { "sk": "Vietnam", "se": "Vietnam", "pl": "Wietnam", "no": "Vietnam", "ja": "ベトナム", "it": "Vietnam", "zh": "越南", "nl": "Vietnam", "de": "Vietnam", "fr": "Vietnam", "es": "Vietnam", "en": "Vietnam", "pt_BR": "Vietnã", "sr-Cyrl": "Вијетнам", "sr-Latn": "Vijetnam", "zh_TW": "越南", "tr": "Vietnam", "ro": "Vietnam", "ar": "فيتنام", "fa": "ویتنام", "yue": "越南" }, flag: "🇻🇳", code: "VN", dialCode: "84", minLength: 11, maxLength: 11, ), Country( name: "Virgin Islands, British", nameTranslations: { "sk": "Britské Panenské ostrovy", "se": "Brittania Virgin-sullot", "pl": "Brytyjskie Wyspy Dziewicze", "no": "De britiske jomfruøyene", "ja": "英領ヴァージン諸島", "it": "Isole Vergini Britanniche", "zh": "英属维尔京群岛", "nl": "Britse Maagdeneilanden", "de": "Britische Jungferninseln", "fr": "Îles Vierges britanniques", "es": "Islas Vírgenes Británicas", "en": "British Virgin Islands", "pt_BR": "Ilhas Virgens Britânicas", "sr-Cyrl": "Британска Девичанска Острва", "sr-Latn": "Britanska Devičanska Ostrva", "zh_TW": "英屬維京群島", "tr": "Britanya Virjin Adaları", "ro": "Insulele Virgine Britanice", "ar": "جزر العذراء البريطانية", "fa": "جزایر ویرجین بریتانیا", "yue": "維爾京群島(英國)" }, flag: "🇻🇬", code: "VG", dialCode: "1284", minLength: 7, maxLength: 7, ), Country( name: "Virgin Islands, U.S.", nameTranslations: { "sk": "Americké Panenské ostrovy", "se": "AOS Virgin-sullot", "pl": "Wyspy Dziewicze Stanów Zjednoczonych", "no": "De amerikanske jomfruøyene", "ja": "米領ヴァージン諸島", "it": "Isole Vergini Americane", "zh": "美属维尔京群岛", "nl": "Amerikaanse Maagdeneilanden", "de": "Amerikanische Jungferninseln", "fr": "Îles Vierges des États-Unis", "es": "Islas Vírgenes de EE. UU.", "en": "U.S. Virgin Islands", "pt_BR": "Ilhas Virgens Americanas", "sr-Cyrl": "Амепичка Девичанска Острва", "sr-Latn": "Američka Devičanska Ostrva", "zh_TW": "美屬維京群島", "tr": "Amerika Birleşik Devletleri Virjin Adaları", "ro": "Insulele Virgine Americane", "ar": "جزر العذراء الأمريكية", "fa": "جزایر ویرجین ایالات متحده آمریکا", "yue": "維爾京群島(美國)" }, flag: "🇻🇮", code: "VI", dialCode: "1340", minLength: 7, maxLength: 7, ), Country( name: "Wallis and Futuna", nameTranslations: { "sk": "Wallis a Futuna", "se": "Wallis ja Futuna", "pl": "Wallis i Futuna", "no": "Wallis og Futuna", "ja": "ウォリス・フツナ", "it": "Wallis e Futuna", "zh": "瓦利斯和富图纳", "nl": "Wallis en Futuna", "de": "Wallis und Futuna", "fr": "Wallis-et-Futuna", "es": "Wallis y Futuna", "en": "Wallis & Futuna", "pt_BR": "Wallis e Futuna", "sr-Cyrl": "Валис и Футуна", "sr-Latn": "Valis i Futuna", "zh_TW": "瓦利斯和富圖那", "tr": "Wallis ve Futuna", "ro": "Wallis și Futuna", "ar": "والس وفوتونا", "fa": "والیس و فوتونا", "yue": "瓦利斯同富图纳" }, flag: "🇼🇫", code: "WF", dialCode: "681", minLength: 6, maxLength: 6, ), Country( name: "Yemen", nameTranslations: { "sk": "Jemen", "se": "Jemen", "pl": "Jemen", "no": "Jemen", "ja": "イエメン", "it": "Yemen", "zh": "也门", "nl": "Jemen", "de": "Jemen", "fr": "Yémen", "es": "Yemen", "en": "Yemen", "pt_BR": "Iémen", "sr-Cyrl": "Јемен", "sr-Latn": "Jemen", "zh_TW": "葉門", "tr": "Yemen", "ro": "Yemen", "ar": "اليمن", "fa": "یمن", "yue": "也門" }, flag: "🇾🇪", code: "YE", dialCode: "967", minLength: 9, maxLength: 9, ), Country( name: "Zambia", nameTranslations: { "sk": "Zambia", "se": "Zambia", "pl": "Zambia", "no": "Zambia", "ja": "ザンビア", "it": "Zambia", "zh": "赞比亚", "nl": "Zambia", "de": "Sambia", "fr": "Zambie", "es": "Zambia", "en": "Zambia", "pt_BR": "Zâmbia", "sr-Cyrl": "Замбија", "sr-Latn": "Zambija", "zh_TW": "贊比亞", "tr": "Zambiya", "ro": "Zambia", "ar": "زامبيا", "fa": "زامبیا", "yue": "贊比亞" }, flag: "🇿🇲", code: "ZM", dialCode: "260", minLength: 9, maxLength: 9, ), Country( name: "Zimbabwe", nameTranslations: { "sk": "Zimbabwe", "se": "Zimbabwe", "pl": "Zimbabwe", "no": "Zimbabwe", "ja": "ジンバブエ", "it": "Zimbabwe", "zh": "津巴布韦", "nl": "Zimbabwe", "de": "Simbabwe", "fr": "Zimbabwe", "es": "Zimbabue", "en": "Zimbabwe", "pt_BR": "Zimbábue", "sr-Cyrl": "Зимбабве", "sr-Latn": "Zimbabve", "zh_TW": "辛巴威", "tr": "Zimbabve", "ro": "Zimbabwe", "ar": "زيمبابوي", "fa": "زیمبابوه", "yue": "津巴布韋" }, flag: "🇿🇼", code: "ZW", dialCode: "263", minLength: 9, maxLength: 9) ]; class Country { final String name; final Map nameTranslations; final String flag; final String code; final String dialCode; final String regionCode; final int minLength; final int maxLength; const Country({ required this.name, required this.flag, required this.code, required this.dialCode, required this.nameTranslations, required this.minLength, required this.maxLength, this.regionCode = "", }); String get fullCountryCode { return dialCode + regionCode; } String get displayCC { if (regionCode != "") { return "$dialCode $regionCode"; } return dialCode; } String localizedName(String languageCode) { return nameTranslations[languageCode] ?? name; } } ================================================== FILE PATH: ./lib/controller/local/phone_intel/phone_number.dart ================================================== import 'countries.dart'; class NumberTooLongException implements Exception {} class NumberTooShortException implements Exception {} class InvalidCharactersException implements Exception {} class PhoneNumber { String countryISOCode; String countryCode; String number; PhoneNumber({ required this.countryISOCode, required this.countryCode, required this.number, }); factory PhoneNumber.fromCompleteNumber({required String completeNumber}) { if (completeNumber == "") { return PhoneNumber(countryISOCode: "", countryCode: "", number: ""); } try { Country country = getCountry(completeNumber); String number; if (completeNumber.startsWith('+')) { number = completeNumber.substring(1 + country.dialCode.length + country.regionCode.length); } else { number = completeNumber.substring(country.dialCode.length + country.regionCode.length); } return PhoneNumber( countryISOCode: country.code, countryCode: country.dialCode + country.regionCode, number: number); } on InvalidCharactersException { rethrow; // ignore: unused_catch_clause } on Exception catch (e) { return PhoneNumber(countryISOCode: "", countryCode: "", number: ""); } } bool isValidNumber() { Country country = getCountry(completeNumber); if (number.length < country.minLength) { throw NumberTooShortException(); } if (number.length > country.maxLength) { throw NumberTooLongException(); } return true; } String get completeNumber { return countryCode + number; } static Country getCountry(String phoneNumber) { if (phoneNumber == "") { throw NumberTooShortException(); } final validPhoneNumber = RegExp(r'^[+0-9]*[0-9]*$'); if (!validPhoneNumber.hasMatch(phoneNumber)) { throw InvalidCharactersException(); } if (phoneNumber.startsWith('+')) { return countries .firstWhere((country) => phoneNumber.substring(1).startsWith(country.dialCode + country.regionCode)); } return countries.firstWhere((country) => phoneNumber.startsWith(country.dialCode + country.regionCode)); } @override String toString() => 'PhoneNumber(countryISOCode: $countryISOCode, countryCode: $countryCode, number: $number)'; } ================================================== FILE PATH: ./lib/controller/firebase/access_token.dart ================================================== import 'dart:convert'; import 'package:googleapis_auth/auth_io.dart'; import '../../print.dart'; class AccessTokenManager { static final AccessTokenManager _instance = AccessTokenManager._internal(); late final String serviceAccountJsonKey; AccessToken? _accessToken; DateTime? _expiryDate; AccessTokenManager._internal(); factory AccessTokenManager(String jsonKey) { if (_instance._isServiceAccountKeyInitialized()) { // Prevent re-initialization return _instance; } _instance.serviceAccountJsonKey = jsonKey; return _instance; } bool _isServiceAccountKeyInitialized() { try { serviceAccountJsonKey; // Access to check if initialized return true; } catch (e) { return false; } } Future getAccessToken() async { if (_accessToken != null && DateTime.now().isBefore(_expiryDate!)) { return _accessToken!.data; } try { final serviceAccountCredentials = ServiceAccountCredentials.fromJson( json.decode(serviceAccountJsonKey)); final client = await clientViaServiceAccount( serviceAccountCredentials, ['https://www.googleapis.com/auth/firebase.messaging'], ); _accessToken = client.credentials.accessToken; _expiryDate = client.credentials.accessToken.expiry; client.close(); // Log.print('_accessToken!.data: ${_accessToken!.data}'); return _accessToken!.data; } catch (e) { throw Exception('Failed to obtain access token'); } } } ================================================== FILE PATH: ./lib/controller/firebase/firbase_messge.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/views/home/Captin/orderCaptin/order_speed_request.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../main.dart'; import '../../print.dart'; import '../../views/auth/captin/criminal_documents_page.dart'; import '../../views/home/Captin/home_captain/home_captin.dart'; import '../../views/home/Captin/orderCaptin/order_request_page.dart'; import '../../views/home/Captin/orderCaptin/vip_order_page.dart'; import '../auth/google_sign.dart'; import '../functions/face_detect.dart'; import 'local_notification.dart'; class FirebaseMessagesController extends GetxController { final fcmToken = FirebaseMessaging.instance; List tokens = []; List dataTokens = []; late String driverID; late String driverToken; NotificationSettings? notificationSettings; NotificationController notificationController = Get.put(NotificationController()); Future getNotificationSettings() async { // Get the current notification settings NotificationSettings? notificationSettings = await FirebaseMessaging.instance.getNotificationSettings(); 'Notification authorization status: ${notificationSettings.authorizationStatus}'; // Call the update function if needed update(); } Future requestFirebaseMessagingPermission() async { FirebaseMessaging messaging = FirebaseMessaging.instance; // Check if the platform is Android if (Platform.isAndroid) { // Request permission for Android await messaging.requestPermission(); } else if (Platform.isIOS) { // Request permission for iOS NotificationSettings settings = await messaging.requestPermission( alert: true, announcement: true, badge: true, carPlay: true, criticalAlert: true, provisional: false, sound: true, ); messaging.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true); } } Future getToken() async { fcmToken.getToken().then((token) { Log.print('token fcm driver: ${token}'); box.write(BoxName.tokenDriver, (token!)); }); // 🔹 الاشتراك في topic await fcmToken.subscribeToTopic("drivers"); // أو "users" حسب نوع المستخدم print("Subscribed to 'drivers' topic ✅"); FirebaseMessaging.onMessage.listen((RemoteMessage message) { // If the app is in the background or terminated, show a system tray message RemoteNotification? notification = message.notification; AndroidNotification? android = notification?.android; // if (notification != null && android != null) { if (message.data.isNotEmpty && message.notification != null) { fireBaseTitles(message); } // if (message.data.isNotEmpty && message.notification != null) { // fireBaseTitles(message); // } }); FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {}); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { if (message.data.isNotEmpty && message.notification != null) { fireBaseTitles(message); } }); } Future fireBaseTitles(RemoteMessage message) async { // [!! تعديل جوهري !!] // اقرأ "النوع" من حمولة البيانات، وليس من العنوان String category = message.data['category'] ?? ''; // اقرأ العنوان والنص (للعرض) String title = message.notification?.title ?? ''; String body = message.notification?.body ?? ''; // استخدم switch لسهولة القراءة والصيانة switch (category) { case 'ORDER': case 'Order': // Handle both cases for backward compatibility if (Platform.isAndroid) { notificationController.showNotification(title, body, 'tone1', ''); } var myListString = message.data['DriverList']; if (myListString != null) { var myList = jsonDecode(myListString) as List; driverToken = myList[14].toString(); Get.put(HomeCaptainController()).changeRideId(); update(); Get.to(() => OrderRequestPage(), arguments: { 'myListString': myListString, 'DriverList': myList, 'body': body }); } break; case 'OrderVIP': var myListString = message.data['DriverList']; if (myListString != null) { var myList = jsonDecode(myListString) as List; if (Platform.isAndroid) { notificationController.showNotification(title, body, 'order', ''); } Get.to(VipOrderPage(), arguments: { 'myListString': myListString, 'DriverList': myList, 'body': body }); } break; case 'Cancel Trip': case 'TRIP_CANCELLED': if (Platform.isAndroid) { notificationController.showNotification( title, 'Passenger Cancel Trip'.tr, 'cancel', ''); } cancelTripDialog(); break; case 'VIP Order Accepted': // This seems to be a notification for the passenger, but if the driver needs to see it: if (Platform.isAndroid) { notificationController.showNotification(title, body, 'order', ''); } // Maybe show a simple snackbar confirmation mySnackbarSuccess('You accepted the VIP order.'.tr); break; case 'message From passenger': case 'MSG_FROM_PASSENGER': if (Platform.isAndroid) { notificationController.showNotification(title, body, 'ding', ''); } MyDialog().getDialog(title, body, () { Get.back(); }); break; case 'token change': case 'TOKEN_CHANGE': GoogleSignInHelper.signOut(); break; case 'face detect': case 'FACE_DETECT': if (Platform.isAndroid) { notificationController.showNotification(title, body, 'tone2', ''); } String result0 = await faceDetector(); var result = jsonDecode(result0); MyDialogContent().getDialog( 'Face Detection Result'.tr, Text( result['similar'].toString() == 'true' ? 'similar'.tr : 'not similar'.tr, style: AppStyle.title, ), () { Get.back(); }, ); update(); break; case 'Hi ,I will go now': case 'PASSENGER_COMING': if (Platform.isAndroid) { notificationController.showNotification(title, body, 'tone2', ''); } update(); break; case 'Criminal Document Required': case 'DOC_REQUIRED': if (Platform.isAndroid) { notificationController.showNotification(title, body, 'tone2', ''); } MyDialog().getDialog(title, 'You should have upload it .'.tr, () { Get.to(() => const CriminalDocumemtPage()); }); break; case 'Order Applied': case 'ORDER_TAKEN': mySnackbarSuccess("The order has been accepted by another driver.".tr); break; default: Log.print('Received unhandled notification category: $category'); // Optionally show a generic notification if (Platform.isAndroid) { notificationController.showNotification(title, body, 'default', ''); } break; } } SnackbarController driverAppliedTripSnakBar() { return Get.snackbar( 'Driver Applied the Ride for You'.tr, '', colorText: AppColor.greenColor, duration: const Duration(seconds: 3), snackPosition: SnackPosition.TOP, titleText: Text( 'Applied'.tr, style: const TextStyle(color: AppColor.redColor), ), messageText: Text( 'Driver Applied the Ride for You'.tr, style: AppStyle.title, ), icon: const Icon(Icons.approval), shouldIconPulse: true, margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(16), ); } Future cancelTripDialog() { return Get.defaultDialog( barrierDismissible: false, title: 'Passenger Cancel Trip'.tr, middleText: '', confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () { box.write(BoxName.rideStatus, 'Cancel'); box.write(BoxName.statusDriverLocation, 'off'); Log.print( 'rideStatus from 347 : ${box.read(BoxName.rideStatus)}'); Get.offAll(HomeCaptain()); })); } Future cancelTripDialog1() { return Get.defaultDialog( barrierDismissible: false, title: 'Passenger Cancel Trip'.tr, middleText: 'Trip Cancelled. The cost of the trip will be added to your wallet.' .tr, confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () { box.write(BoxName.rideStatus, 'Cancel'); Log.print( 'rideStatus from 364 : ${box.read(BoxName.rideStatus)}'); Get.offAll(HomeCaptain()); })); } } class OverlayContent extends StatelessWidget { final String title; final String body; OverlayContent(this.title, this.body); @override Widget build(BuildContext context) { return Material( child: Container( padding: const EdgeInsets.all(16.0), color: Colors.white, child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( title, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), const SizedBox(height: 8.0), Text( body, style: const TextStyle(fontSize: 16), ), ], ), ), ); } } ================================================== FILE PATH: ./lib/controller/firebase/bring_app_foreground.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class AppLifecycleManager { static const platform = MethodChannel('com.sefer_driver/app_lifecycle'); static Future bringAppToForeground() async { try { debugPrint('Attempting to bring app to foreground'); await platform.invokeMethod('bringAppToForeground'); debugPrint('Method invocation completed'); } on PlatformException catch (e) { debugPrint("Failed to bring app to foreground: '${e.message}'."); } catch (e) { debugPrint("Unexpected error: $e"); } } } ================================================== FILE PATH: ./lib/controller/firebase/local_notification.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:sefer_driver/views/home/Captin/orderCaptin/order_request_page.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; import '../../constant/box_name.dart'; import '../../main.dart'; import '../../print.dart'; import '../../views/notification/notification_captain.dart'; import '../home/captin/home_captain_controller.dart'; class NotificationController extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future initNotifications() async { const AndroidInitializationSettings android = AndroidInitializationSettings('@mipmap/launcher_icon'); DarwinInitializationSettings ios = DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, // onDidReceiveLocalNotification: // (int id, String? title, String? body, String? payload) async {}, ); InitializationSettings initializationSettings = InitializationSettings(android: android, iOS: ios); tz.initializeTimeZones(); print('Notifications initialized'); await _flutterLocalNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: onDidReceiveNotificationResponse, onDidReceiveBackgroundNotificationResponse: notificationTapBackground, ); // Create a notification channel const AndroidNotificationChannel channel = AndroidNotificationChannel( 'high_importance_channel', // Use the same ID as in strings.xml 'High Importance Notifications', description: 'This channel is used for important notifications.', importance: Importance.high, ); // Register the channel with the system await _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); } // Displays a notification with the given title and message void showNotification( String title, String message, String tone, String payLoad) async { BigTextStyleInformation bigTextStyleInformation = BigTextStyleInformation( message, contentTitle: title.tr, htmlFormatContent: true, htmlFormatContentTitle: true, ); AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, sound: RawResourceAndroidNotificationSound(tone), ); DarwinNotificationDetails ios = const DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); NotificationDetails details = NotificationDetails(android: android, iOS: ios); await _flutterLocalNotificationsPlugin.show(0, title, message, details, payload: jsonEncode({'title': title, 'data': payLoad})); } void scheduleNotificationAtSpecificTime( String title, String message, String tone, int hour, int minute) async { // Initialize and set Cairo time zone tz.initializeTimeZones(); var cairoLocation; if (box.read(BoxName.countryCode).toString() == 'Egypt') { cairoLocation = tz.getLocation('Africa/Cairo'); } else {} // todo get for location country final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); final now = tz.TZDateTime.now(cairoLocation); // Use Cairo timezone for current time tz.TZDateTime scheduledTime = tz.TZDateTime( cairoLocation, now.year, now.month, now.day, hour, minute); // If the scheduled time has already passed for today, schedule it for the next day if (scheduledTime.isBefore(now)) { scheduledTime = scheduledTime.add(const Duration(days: 1)); } if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } print('Current time: $now'); print('Scheduling notification for: $scheduledTime'); await _flutterLocalNotificationsPlugin.zonedSchedule( 0, title, message, scheduledTime, details, // androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, androidScheduleMode: AndroidScheduleMode.alarmClock, // Triggers daily at the same time ); print('Notification scheduled successfully'); } void scheduleNotificationAfter1Minute( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); // Schedule the notification to be shown after 1 minute Timer.periodic(const Duration(seconds: 15), (timer) async { final now = tz.TZDateTime.now(tz.local); final scheduledTime = now.add(const Duration(seconds: 10)); Log.print('scheduledTime: ${scheduledTime}'); if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } print('Scheduling notification for: $scheduledTime'); await _flutterLocalNotificationsPlugin.zonedSchedule( 0, title, message, scheduledTime, details, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, androidScheduleMode: AndroidScheduleMode.alarmClock, ); print('Notification scheduled successfully'); }); } void scheduleNotificationsForSevenDays( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); // Check for the exact alarm permission on Android 12 and above if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } // Schedule notifications for the next 7 days for (int day = 0; day < 7; day++) { // List of notification times final notificationTimes = [ {'hour': 8, 'minute': 0, 'id': day * 1000 + 1}, // 8:00 AM {'hour': 15, 'minute': 0, 'id': day * 1000 + 2}, // 3:00 PM {'hour': 20, 'minute': 0, 'id': day * 1000 + 3}, // 8:00 PM ]; for (var time in notificationTimes) { final notificationId = time['id'] as int; // Check if this notification ID is already stored bool isScheduled = box.read('notification_$notificationId') ?? false; if (!isScheduled) { // Schedule the notification if not already scheduled await _scheduleNotificationForTime( day, time['hour'] as int, time['minute'] as int, title, message, details, notificationId, ); // Mark this notification ID as scheduled in GetStorage box.write('notification_$notificationId', true); } else { print('Notification with ID $notificationId is already scheduled.'); } } } print('Notifications scheduled successfully for the next 7 days'); } Future _scheduleNotificationForTime( int dayOffset, int hour, int minute, String title, String message, NotificationDetails details, int notificationId, ) async { // Initialize and set Cairo timezone tz.initializeTimeZones(); var cairoLocation = tz.getLocation('Africa/Cairo'); final now = tz.TZDateTime.now(cairoLocation); tz.TZDateTime scheduledDate = tz.TZDateTime( cairoLocation, now.year, now.month, now.day + dayOffset, // Add offset to schedule for the next days hour, minute, ); // If the scheduled time is in the past, move it to the next day if (scheduledDate.isBefore(now)) { scheduledDate = scheduledDate.add(Duration(days: 1)); } print('Current time (Cairo): $now'); print('Scheduling notification for: $scheduledDate'); await _flutterLocalNotificationsPlugin.zonedSchedule( notificationId, // Unique ID for each notification title, message, scheduledDate, details, androidScheduleMode: AndroidScheduleMode.exact, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: null, // Don't repeat automatically; we handle 7 days manually ); print('Notification scheduled successfully for: $scheduledDate'); } void scheduleNotificationEvery10Hours( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound(tone), ); const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } Timer.periodic(const Duration(hours: 10), (timer) async { final now = tz.TZDateTime.now(tz.local); final scheduledTime = now.add(const Duration(minutes: 10)); print('Scheduling notification for: $scheduledTime'); await _flutterLocalNotificationsPlugin.zonedSchedule( 0, title.tr, message.tr, scheduledTime, details, // androidAllowWhileIdle: true, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.time, androidScheduleMode: AndroidScheduleMode.alarmClock, ); }); print('Notifications scheduled every 5 seconds'); } void showTimerNotification(String title, String message, String tone) async { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // Setup Android notification final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', 'High Importance Notifications', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound( tone), // tone without the file extension ); // Setup iOS notification const DarwinNotificationDetails ios = DarwinNotificationDetails( sound: 'default', presentAlert: true, presentBadge: true, presentSound: true, ); final NotificationDetails details = NotificationDetails(android: android, iOS: ios); // Request permission on Android if (Platform.isAndroid) { if (await Permission.scheduleExactAlarm.isDenied) { if (await Permission.scheduleExactAlarm.request().isGranted) { print('SCHEDULE_EXACT_ALARM permission granted'); } else { print('SCHEDULE_EXACT_ALARM permission denied'); return; } } } // Timer duration (e.g., 120 seconds countdown) int countdown = 12; // Display the notification initially with the full countdown time // Timer to update the notification every second Timer.periodic(const Duration(seconds: 1), (timer) async { // if (countdown > 0) { // Update the existing notification with the updated countdown // Decrease the countdown by 1 countdown--; // } else { // // Cancel the timer when the countdown reaches zero // timer.cancel(); // } }); await flutterLocalNotificationsPlugin.show( 0, title, '$message Remaining: $countdown seconds', // Initial message details, ); print('Notification will update every second'); } // Callback when the notification is tapped void onDidReceiveNotificationResponse(NotificationResponse response) { handleNotificationResponse(response); } // Callback when the notification is tapped while the app is in the background void onDidReceiveBackgroundNotificationResponse( NotificationResponse response) { handleNotificationResponse(response); } // Handle notification response for both foreground and background void handleNotificationResponse(NotificationResponse response) { print('Notification tapped!'); Log.print('response.payload: ${response.payload}'); if (response.payload != null) { print('Notification payload: ${response.payload}'); var payloadData = jsonDecode(response.payload.toString()); if (payloadData is Map) { String title = payloadData['title']; var data = payloadData['data']; switch (title) { case 'Order': _handleOrderNotification(data); break; case 'OrderSpeed': _handleOrderSpeedNotification(data); break; case 'ADS': _handleADSNotification(); break; default: Log.print('Unknown notification type'); } } else { Log.print('Invalid payload format'); } } else { Log.print('Payload is null'); } } void _handleOrderNotification(dynamic data) { if (data is String) { var orderData = jsonDecode(data); if (orderData is List && orderData.length == 34) { //closeOverLay(); Get.put(HomeCaptainController()).changeRideId(); Get.to(() => OrderRequestPage(), arguments: {'myListString': data}); } else { Log.print('Invalid order data'); } } else { Log.print('Invalid order payload'); } } void _handleOrderSpeedNotification(dynamic data) { if (data is String) { var orderData = jsonDecode(data); if (orderData is List && orderData.length == 34) { //closeOverLay(); Get.put(HomeCaptainController()).changeRideId(); Get.to(() => OrderRequestPage(), arguments: {'myListString': data}); } else { Log.print('Invalid order data'); } } else { Log.print('Invalid order payload'); } } void _handleADSNotification() { // var orderData = jsonDecode(data); //closeOverLay(); Get.to( () => const NotificationCaptain(), ); } void onDidReceiveLocalNotification( int id, String? title, String? body, String? payload) async { // display a dialog with the notification details, tap ok to go to another page } } class NotificationController1 extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // Initializes the local notifications plugin Future initNotifications() async { const AndroidInitializationSettings android = AndroidInitializationSettings('@mipmap/launcher_icon'); const InitializationSettings initializationSettings = InitializationSettings(android: android); await _flutterLocalNotificationsPlugin.initialize(initializationSettings); } // Displays a notification with the given title and message void showNotification( String title, String message, String tone, String payLoad) async { AndroidNotificationDetails android = AndroidNotificationDetails( 'your channel id', 'your channel name', importance: Importance.max, priority: Priority.high, showWhen: false, sound: RawResourceAndroidNotificationSound(tone)); NotificationDetails details = NotificationDetails(android: android); await _flutterLocalNotificationsPlugin.show(0, title, message, details); } } ================================================== FILE PATH: ./lib/controller/firebase/order_lay.dart ================================================== import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:flutter/material.dart'; class OverlayContent1 extends StatelessWidget { @override Widget build(BuildContext context) { return Material( child: Container( padding: EdgeInsets.all(16.0), color: Colors.white, child: MyElevatedButton( title: 'go to order', onPressed: () async { var res = await CRUD().post( link: AppLink.addFeedBack, payload: { "passengerId": 'dddddd', "feedBack": "eeeee", }, ); print(res); if (res != 'failure') { Navigator.push( context, MaterialPageRoute(builder: (cont) => HomeCaptain())); // Get.to(OrderRequestPage()); } }, ), ), ); } } ================================================== FILE PATH: ./lib/controller/firebase/notification_service.dart ================================================== import 'dart:convert'; import 'package:http/http.dart' as http; import '../../print.dart'; class NotificationService { // تأكد من أن هذا هو الرابط الصحيح لملف الإرسال static const String _serverUrl = 'https://syria.intaleq.xyz/intaleq/fcm/send_fcm.php'; static Future sendNotification({ required String target, required String title, required String body, required String? category, // <-- [الإضافة الأولى] String? tone, List? driverList, bool isTopic = false, }) async { try { final Map payload = { 'target': target, 'title': title, 'body': body, 'isTopic': isTopic, }; if (category != null) { payload['category'] = category; // <-- [الإضافة الثانية] } if (tone != null) { payload['tone'] = tone; } if (driverList != null) { // [مهم] تطبيق السائق يرسل passengerList payload['passengerList'] = jsonEncode(driverList); } final response = await http.post( Uri.parse(_serverUrl), headers: { 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(payload), ); if (response.statusCode == 200) { print('✅ Notification sent successfully.'); } else { print( '❌ Failed to send notification. Status code: ${response.statusCode}'); } } catch (e) { print('❌ An error occurred while sending notification: $e'); } } } ================================================== FILE PATH: ./lib/controller/profile/setting_controller.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:get/get.dart'; class SettingController extends GetxController { bool isGoogleMapsEnabled = false; void onChangMapApp() { if (!isGoogleMapsEnabled) { isGoogleMapsEnabled = true; box.write(BoxName.googlaMapApp, true); update(); } else { isGoogleMapsEnabled = false; box.write(BoxName.googlaMapApp, false); update(); } } @override void onInit() { if (box.read(BoxName.googlaMapApp) != null) { isGoogleMapsEnabled = box.read(BoxName.googlaMapApp); } update(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/profile/profile_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import '../../views/widgets/elevated_btn.dart'; class ProfileController extends GetxController { bool isloading = false; Map prfoileData = {}; TextEditingController txtController = TextEditingController(); List genders = ['Male', 'Female', 'Non-binary']; String gender = 'Male'; void setGender(String value) { gender = value; } String? selectedDegree; void setDegree(String? degree) { selectedDegree = degree; update(); } String? selectedCountry; void setCountry(String? country) { selectedCountry = country; // box.write(BoxName.countryCode, country); update(); } updateColumn(Map payload) async { isloading = true; update(); await CRUD().post(link: AppLink.updateprofile, payload: payload); await getProfile(); isloading = false; update(); } updatField(String columnName, TextInputType type) async { Get.defaultDialog( title: '${'Update'.tr} $columnName', content: Column( children: [ SizedBox( width: Get.width * .7, child: MyTextForm( controller: txtController, label: 'type here'.tr, hint: 'type here', type: type) // TextField( // controller: txtController, // decoration: const InputDecoration( // border: OutlineInputBorder(), hintText: 'type here'), // ), ), MyElevatedButton( title: 'Update'.tr, onPressed: () { updateColumn({ 'id': box.read(BoxName.passengerID), columnName: txtController.text, }); if (columnName == 'first_name') { box.write(BoxName.name, txtController.text); } Get.back(); txtController.clear(); }, ) ], ), ); } getProfile() async { isloading = true; update(); var res = await CRUD().get(link: AppLink.getprofile, payload: { 'id': box.read(BoxName.passengerID).toString(), }); if (res.toString() == 'failure') { // Get.snackbar('failure', 'message'); isloading = false; update(); } else { var jsonDecoded = jsonDecode(res); prfoileData = jsonDecoded['data']; isloading = false; update(); } } @override void onInit() { getProfile(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/profile/captain_profile_controller.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import '../../views/widgets/error_snakbar.dart'; class CaptainProfileController extends GetxController { bool isLoading = false; TextEditingController vin = TextEditingController(); TextEditingController color = TextEditingController(); TextEditingController make = TextEditingController(); TextEditingController model = TextEditingController(); TextEditingController year = TextEditingController(); TextEditingController expirationDate = TextEditingController(); final TextEditingController emailController = TextEditingController(); updateEmail() async { var payload = { 'id': box.read(BoxName.driverID).toString(), 'email': emailController.text, }; var res = await CRUD().post(link: AppLink.updateDriverEmail, payload: payload); if ((res)['status'] == 'success') { box.write(BoxName.emailDriver, emailController.text); update(); Get.back(); } else { mySnackeBarError((res)['message']); } } Future updateFields() async { var payload = { 'driverID': box.read(BoxName.driverID).toString(), }; if (vin.text.isNotEmpty) { payload['vin'] = vin.text; } if (color.text.isNotEmpty) { payload['color'] = color.text; } if (model.text.isNotEmpty) { payload['model'] = model.text; } if (make.text.isNotEmpty) { payload['make'] = make.text; } if (year.text.isNotEmpty) { payload['year'] = year.text; } if (expirationDate.text.isNotEmpty) { payload['expiration_date'] = expirationDate.text; } var res = await CRUD().post(link: AppLink.updateRegisrationCar, payload: payload); if (jsonDecode(res)['status'] == 'success') { box.write(BoxName.vin, vin.text); box.write(BoxName.color, color.text); box.write(BoxName.model, model.text); box.write(BoxName.make, make.text); box.write(BoxName.year, year.text); box.write(BoxName.expirationDate, expirationDate.text); update(); Get.back(); } } Map captainProfileData = {}; Future getProfileData() async { isLoading = true; update(); var res = await CRUD().get( link: AppLink.getCaptainProfile, payload: {'id': box.read(BoxName.driverID)}); if (res != 'failure') { var d = jsonDecode(res); captainProfileData = d['message']; update(); box.write(BoxName.sexDriver, d['message']['gender']); box.write(BoxName.dobDriver, d['message']['birthdate']); box.write(BoxName.vin, d['message']['vin']); box.write(BoxName.color, d['message']['color']); box.write(BoxName.model, d['message']['model']); box.write(BoxName.carPlate, d['message']['car_plate']); box.write(BoxName.make, d['message']['make']); box.write(BoxName.year, d['message']['year']); box.write(BoxName.expirationDate, d['message']['expiration_date']); // box.write(BoxName.acc, d['message']['accountBank']); isLoading = false; update(); } } @override void onInit() { // if (box.read(BoxName.dobDriver) == null) { getProfileData(); // } super.onInit(); } } ================================================== FILE PATH: ./lib/controller/packages/lingo/lingo_hunter.dart ================================================== import 'dart:io'; import 'dart:convert'; import '../../../print.dart'; abstract class LingoHunter { /// Extracts translatable strings... static Future extractAndCreateTranslationFiles({ required String baseLang, required List langs, String? projectDirectory, String? outputDirectory, bool translateBaseLang = true, List? additionalRegExps, bool overrideRegExps = false, List fileExtensions = const ['.dart'], }) async { // 1. Find project root (improved logic) String projectRoot; if (projectDirectory != null) { // Use provided directory, but check if it's valid if (!await Directory(projectDirectory).exists()) { throw ArgumentError( "The provided projectDirectory '$projectDirectory' does not exist."); } projectRoot = projectDirectory; } else { projectRoot = await _findProjectRoot(); // Use the corrected function } // 2. Use the project root as output directory if not specified final String outputDir = outputDirectory ?? projectRoot; // 3. Output Directory Verification (Create if necessary) final Directory outputDirObj = Directory(outputDir); if (!await outputDirObj.exists()) { try { await outputDirObj.create(recursive: true); } catch (e) { throw Exception( "Failed to create output directory: $outputDir. Error: $e"); } } print("Project root directory: $projectRoot"); print("Output directory: $outputDir"); // 4. Extract translatable strings final Set strings = await extractStringsFromFlutterProject( directory: projectRoot, // Use the validated projectRoot additionalRegExps: additionalRegExps, overrideRegExps: overrideRegExps, fileExtensions: fileExtensions, ); // 5. Generate translation files await _createTranslationFiles( strings: strings, outputDirectory: outputDir, baseLang: baseLang, langs: langs, translateBaseLang: translateBaseLang, ); print("Successfully extracted strings and generated translation files."); } /// Finds the project's root directory (corrected) static Future _findProjectRoot() async { Directory current = Directory.current; int maxIterations = 10; // Prevent infinite loop int count = 0; while (count < maxIterations) { if (await File('${current.path}/pubspec.yaml').exists()) { return current.path; // Return the directory *containing* pubspec.yaml } if (current.path == current.parent.path) { break; // Reached root, stop searching } current = current.parent; count++; } // If `pubspec.yaml` was not found, throw an exception throw Exception( "`pubspec.yaml` not found in the current directory or its parents."); } /// Extracts translatable strings (no changes needed here) static Future> extractStringsFromFlutterProject({ required String directory, List? additionalRegExps, bool overrideRegExps = false, List fileExtensions = const ['.dart'], }) async { // ... (rest of the function remains the same) ... final List defaultPatterns = [ RegExp(r'"([^"]+)"\.tr\(\)'), // "string".tr() RegExp(r"'([^']+)'\.tr\(\)"), // 'string'.tr() RegExp(r'"([^"]+)"\.tr'), // "string".tr RegExp(r"'([^']+)'\.tr"), // 'string'.tr RegExp(r'"([^"]+)"\.tr\(\w+\)'), // "string".tr(context) RegExp(r"'([^']+)'\.tr\(\w+\)"), // 'string'.tr(context) RegExp(r'context\.tr\("([^"]+)"\)'), // context.tr("string") RegExp(r"context\.tr\('([^']+)'\)"), // context.tr('string') RegExp(r'tr\(\w+, "([^"]+)"\)'), // tr(context, "string") RegExp(r"tr\(\w+, '([^']+)'\)"), // tr(context, 'string') RegExp(r'tr\("([^"]+)"\)'), // tr("string") RegExp(r"tr\('([^']+)'\)"), // tr('string') RegExp(r'"([^"]+)"\.tr\(args: \[.*?\]\)'), // "string".tr(args: []) RegExp(r'"([^"]+)"\.plural\(\d+\)'), // "string".plural(3) //Intl Package Patterns RegExp(r'AppLocalizations\.of\(context\)!\.translate\("([^"]+)"\)'), ]; // Determine the patterns to use List patterns; if (overrideRegExps && additionalRegExps != null) { patterns = additionalRegExps; } else { patterns = [...defaultPatterns]; if (additionalRegExps != null) { patterns.addAll(additionalRegExps); } } final Set strings = {}; final Directory projectDirObj = Directory(directory); // Check if the directory exists *before* listing if (!await projectDirObj.exists()) { throw ArgumentError("The directory '$directory' does not exist."); } final List entities = await projectDirObj.list(recursive: true).toList(); // Filter files by the specified extensions final List filteredFiles = entities .whereType() .where((file) => fileExtensions.any((ext) => file.path.endsWith(ext))) .toList(); // Extract strings from files for (final File file in filteredFiles) { final String content = await file.readAsString(); for (final RegExp pattern in patterns) { final Iterable matches = pattern.allMatches(content); for (final RegExpMatch match in matches) { if (match.groupCount >= 1 && match.group(1) != null) { strings.add(match.group(1)!); } } } } return strings; } /// Creates translation files (no changes needed) static Future _createTranslationFiles({ required Set strings, required String outputDirectory, required String baseLang, required List langs, bool translateBaseLang = true, }) async { // ... (rest of the function remains the same) ... final Directory outputDir = Directory(outputDirectory); if (!await outputDir.exists()) { Log.print('outputDir: ${outputDir}'); await outputDir.create(recursive: true); } // Always create the base language file, even if `translateBaseLang` is false final String baseFilePath = '$outputDirectory/translations_$baseLang.json'; final Map baseStrings = { for (final string in strings) string: translateBaseLang ? string : "" }; await _writeTranslationFile(baseFilePath, baseStrings); for (final String lang in langs) { final String langFilePath = '$outputDirectory/translations_$lang.json'; final Map langStrings = { for (final string in strings) string: "" }; await _writeTranslationFile(langFilePath, langStrings); } } /// Writes a translation file (no changes needed) static Future _writeTranslationFile( String filePath, Map strings) async { // ... (rest of the function remains the same) ... final File file = File(filePath); final StringBuffer content = StringBuffer(); content.writeln('{'); int index = 0; for (final MapEntry entry in strings.entries) { final String comma = (index < strings.length - 1) ? ',' : ''; final String key = jsonEncode(entry.key).substring(1, jsonEncode(entry.key).length - 1); final String value = entry.value.isEmpty ? "" : jsonEncode(entry.value) .substring(1, jsonEncode(entry.value).length - 1); content.writeln(' "$key": "$value"$comma'); index++; } content.writeln('}'); await file.writeAsString(content.toString()); } } ================================================== FILE PATH: ./lib/controller/functions/add_error.dart ================================================== import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../main.dart'; import 'crud.dart'; addError1(String error, String details, String where) async { try { // Get user information for the error log final userId = box.read(BoxName.driverID) ?? box.read(BoxName.passengerID); final userType = box.read(BoxName.driverID) != null ? 'Driver' : 'passenger'; final phone = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); // Send the error data to the server // Note: This is a fire-and-forget call. We don't await it or handle its response // to prevent an infinite loop if the addError endpoint itself is failing. CRUD().post( link: AppLink.addError, payload: { 'error': error.toString(), 'userId': userId.toString(), 'userType': userType, 'phone': phone.toString(), 'device': where, // The location of the error 'details': details, // The detailed stack trace or context }, ); } catch (e) { // If logging the error itself fails, print to the console to avoid infinite loops. print("Failed to log error to server: $e"); } } ================================================== FILE PATH: ./lib/controller/functions/overlay_permisssion.dart ================================================== import 'dart:io'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:flutter_confetti/flutter_confetti.dart'; import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:get/get.dart'; import 'package:location/location.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; import '../auth/captin/login_captin_controller.dart'; import '../home/payment/captain_wallet_controller.dart'; Future getPermissionOverlay() async { if (Platform.isAndroid) { final bool status = await FlutterOverlayWindow.isPermissionGranted(); if (status == false) { MyDialog().getDialog( 'Allow overlay permission'.tr, 'To display orders instantly, please grant permission to draw over other apps.' .tr, () async { Get.back(); await FlutterOverlayWindow.requestPermission(); }, ); } } } Future showDriverGiftClaim(BuildContext context) async { if (box.read(BoxName.is_claimed).toString() == '0' || box.read(BoxName.is_claimed) == null) { MyDialog().getDialog( 'You have gift 30000 SYP'.tr, 'This for new registration'.tr, () async { Get.back(); var res = await CRUD().post(link: AppLink.updateDriverClaim, payload: { 'driverId': box.read(BoxName.driverID), }); if (res != 'failure') { Get.find() .addDriverWallet('new driver', '30000', '30000'); Confetti.launch( context, options: const ConfettiOptions(particleCount: 100, spread: 70, y: 0.6), ); box.write(BoxName.is_claimed, '1'); } }); } } Future closeOverlayIfFound() async { if (Platform.isAndroid) { bool isOverlayActive = await FlutterOverlayWindow.isActive(); if (isOverlayActive) { await FlutterOverlayWindow.closeOverlay(); } } } final location = Location(); Future getLocationPermission() async { bool serviceEnabled; PermissionStatus permissionGranted; // Check if location services are enabled serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) { // Location services are still not enabled, handle the error return; } } // Check if the app has permission to access location permissionGranted = await location.hasPermission(); if (permissionGranted == PermissionStatus.denied) { permissionGranted = await location.requestPermission(); if (permissionGranted != PermissionStatus.granted) { // Location permission is still not granted, handle the error permissionGranted = await location.requestPermission(); return; } } if (permissionGranted.toString() == 'PermissionStatus.granted') { box.write(BoxName.locationPermission, 'true'); Get.find().update(); } // update(); } Future getOverLay(String myListString) async { bool isOverlayActive = await FlutterOverlayWindow.isActive(); if (isOverlayActive) { await FlutterOverlayWindow.closeOverlay(); } await FlutterOverlayWindow.showOverlay( enableDrag: true, flag: OverlayFlag.focusPointer, visibility: NotificationVisibility.visibilityPublic, positionGravity: PositionGravity.auto, height: 700, width: WindowSize.matchParent, startPosition: const OverlayPosition(0, -150), ); await FlutterOverlayWindow.shareData(myListString); } ================================================== FILE PATH: ./lib/controller/functions/twilio_service.dart ================================================== // import 'package:ride/constant/credential.dart'; // import 'package:twilio_flutter/twilio_flutter.dart'; // // class TwilioSMS { // TwilioFlutter twilioFlutter = TwilioFlutter( // accountSid: AppCredintials.accountSIDTwillo, // authToken: AppCredintials.authTokenTwillo, // twilioNumber: '+962 7 9858 3052'); // // Future sendSMS({ // required String recipientPhoneNumber, // required String message, // }) async { // try { // await twilioFlutter.sendSMS( // toNumber: recipientPhoneNumber, // messageBody: message, // ); // } catch (e) { // } // } // } ================================================== FILE PATH: ./lib/controller/functions/launch.dart ================================================== import 'package:url_launcher/url_launcher.dart'; import 'dart:io'; void showInBrowser(String url) async { if (await canLaunchUrl(Uri.parse(url))) { launchUrl(Uri.parse(url)); } else {} } Future makePhoneCall(String phoneNumber) async { // 1. Clean the number String formattedNumber = phoneNumber.replaceAll(RegExp(r'\s+'), ''); // 2. Format logic (Syria/International) if (formattedNumber.length > 6) { if (formattedNumber.startsWith('09')) { formattedNumber = '+963${formattedNumber.substring(1)}'; } else if (!formattedNumber.startsWith('+')) { formattedNumber = '+$formattedNumber'; } } // 3. Create URI final Uri launchUri = Uri( scheme: 'tel', path: formattedNumber, ); // 4. Execute with externalApplication mode try { // Attempt to launch directly without checking canLaunchUrl first // (Sometimes canLaunchUrl returns false on some devices even if it works) if (!await launchUrl(launchUri, mode: LaunchMode.externalApplication)) { throw 'Could not launch $launchUri'; } } catch (e) { // Fallback: Try checking canLaunchUrl if the direct launch fails if (await canLaunchUrl(launchUri)) { await launchUrl(launchUri); } else { print("Cannot launch url: $launchUri"); } } } void launchCommunication( String method, String contactInfo, String message) async { String url; if (Platform.isIOS) { switch (method) { case 'phone': url = 'tel:$contactInfo'; break; case 'sms': url = 'sms:$contactInfo?body=${Uri.encodeComponent(message)}'; break; case 'whatsapp': url = 'https://api.whatsapp.com/send?phone=$contactInfo&text=${Uri.encodeComponent(message)}'; break; case 'email': url = 'mailto:$contactInfo?subject=Subject&body=${Uri.encodeComponent(message)}'; break; default: return; } } else if (Platform.isAndroid) { switch (method) { case 'phone': url = 'tel:$contactInfo'; break; case 'sms': url = 'sms:$contactInfo?body=${Uri.encodeComponent(message)}'; break; case 'whatsapp': // Check if WhatsApp is installed final bool whatsappInstalled = await canLaunchUrl(Uri.parse('whatsapp://')); if (whatsappInstalled) { url = 'whatsapp://send?phone=$contactInfo&text=${Uri.encodeComponent(message)}'; } else { // Provide an alternative action, such as opening the WhatsApp Web API url = 'https://api.whatsapp.com/send?phone=$contactInfo&text=${Uri.encodeComponent(message)}'; } break; case 'email': url = 'mailto:$contactInfo?subject=Subject&body=${Uri.encodeComponent(message)}'; break; default: return; } } else { return; } if (await canLaunchUrl(Uri.parse(url))) { await launchUrl(Uri.parse(url)); } else {} } ================================================== FILE PATH: ./lib/controller/functions/device_info.dart ================================================== import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:get_storage/get_storage.dart'; import '../../constant/box_name.dart'; class DeviceInfo { final String? manufacturer; final String? model; final String? deviceId; final String? osVersion; final String? platform; final String? deviceName; final bool? isPhysicalDevice; DeviceInfo({ this.manufacturer, this.model, this.deviceId, this.osVersion, this.platform, this.deviceName, this.isPhysicalDevice, }); Map toJson() => { 'manufacturer': manufacturer, 'model': model, 'deviceId': deviceId, 'osVersion': osVersion, 'platform': platform, 'deviceName': deviceName, 'isPhysicalDevice': isPhysicalDevice, }; } class DeviceController { final box = GetStorage(); final _deviceInfo = DeviceInfoPlugin(); Future getDeviceInfo() async { if (Platform.isAndroid) { return await _getAndroidDeviceInfo(); } else if (Platform.isIOS) { return await _getIosDeviceInfo(); } throw UnsupportedError('Unsupported platform'); } Future _getAndroidDeviceInfo() async { final androidInfo = await _deviceInfo.androidInfo; final deviceInfo = DeviceInfo( manufacturer: androidInfo.manufacturer, model: androidInfo.model, deviceId: androidInfo.serialNumber, osVersion: androidInfo.version.release, platform: 'Android', deviceName: androidInfo.device, isPhysicalDevice: androidInfo.isPhysicalDevice, ); box.write(BoxName.deviceInfo, deviceInfo.toJson()); return deviceInfo; } Future _getIosDeviceInfo() async { final iosInfo = await _deviceInfo.iosInfo; final deviceInfo = DeviceInfo( manufacturer: 'Apple', model: iosInfo.model, deviceId: iosInfo.identifierForVendor, osVersion: iosInfo.systemVersion, platform: 'iOS', deviceName: iosInfo.name, isPhysicalDevice: iosInfo.isPhysicalDevice, ); box.write(BoxName.deviceInfo, deviceInfo.toJson()); return deviceInfo; } } ================================================== FILE PATH: ./lib/controller/functions/ocr_controller.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:http/http.dart' as http; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/info.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/constant/table_names.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../auth/captin/register_captin_controller.dart'; import 'launch.dart'; // // class TextExtractionController extends GetxController { // String extractedText = ''; // bool isloading = false; // File? _scannedImage; // // Convert the extracted text to JSON // // Convert the extracted text to JSON // String getTextAsJSON(String text) { // final lines = text.split('\n'); // final jsonList = lines.map((line) { // return { // 'line_text': line, // 'num_words': line.trim().split(' ').length, // }; // }).toList(); // // final json = { // 'lines': jsonList, // 'num_lines': lines.length, // }; // // return jsonEncode(json); // } // // // Convert the extracted text to blocks by line // List getTextBlocks(String text) { // return text.split('\n'); // } // // // Future pickAndExtractText() async { // // final pickedImage = await ImagePicker().pickImage( // // source: ImageSource.camera, // // preferredCameraDevice: CameraDevice.rear, // // maxHeight: Get.height * .3, // // maxWidth: Get.width * .8, // // imageQuality: 99, // // ); // // if (pickedImage != null) { // // isloading = true; // // update(); // // final imagePath = pickedImage.path; // // final languages = [ // // 'eng', // // 'ara' // // ]; // Specify the languages you want to use for text extraction // // // try { // // final text = await FlutterTesseractOcr.extractText(imagePath, // // language: // // languages.join('+'), // Combine multiple languages with '+' // // args: { // // "psm": "4", // // "preserve_interword_spaces": "1", // // // "rectangle": const Rect.fromLTWH(100, 100, 200, 200), // // } // Additional options if needed // // ); // // isloading = false; // // final jsonText = getTextAsJSON(text); // // final textBlocks = getTextBlocks(text); // // update(); // // extractedText = // // textBlocks.toString(); // Convert the extracted text to JSON. // // // // Print the JSON to the console. // // update(); // // } catch (e) { // // extractedText = ''; // // } // // } // // } // } // class TextMLGoogleRecognizerController extends GetxController { // @override // void onInit() { // scanText(); // super.onInit(); // } // // // The ImagePicker instance // final ImagePicker _imagePicker = ImagePicker(); // // // The GoogleMlKit TextRecognizer instance // final TextRecognizer _textRecognizer = TextRecognizer(); // // // The scanned text // String? scannedText; // String? jsonOutput; // final List> lines = []; // // Map decode = {}; // // Future scanText() async { // // Pick an image from the camera or gallery // final XFile? image = // await _imagePicker.pickImage(source: ImageSource.gallery); // // // If no image was picked, return // if (image == null) { // return; // } // // // Convert the XFile object to an InputImage object // final InputImage inputImage = InputImage.fromFile(File(image.path)); // // // Recognize the text in the image // final RecognizedText recognizedText = // await _textRecognizer.processImage(inputImage); // scannedText = recognizedText.text; // Map extractedData = {}; // // Extract the scanned text line by line // for (var i = 0; i < recognizedText.blocks.length; i++) { // final block = recognizedText.blocks[i]; // for (final line in block.lines) { // final lineText = line.text; // // if (lineText.contains('DL')) { // final dlNumber = lineText.split('DL')[1].trim(); // extractedData['dl_number'] = dlNumber; // } // if (lineText.contains('USA')) { // final usa = lineText.split('USA')[1].trim(); // extractedData['USA'] = usa; // } // if (lineText.contains('DRIVER LICENSE')) { // final driverl = lineText; // extractedData['DRIVER_LICENSE'] = driverl; // } // // if (lineText.contains('EXP')) { // final expiryDate = lineText.split('EXP')[1].trim(); // extractedData['expiry_date'] = expiryDate; // } // // if (lineText.contains('DOB')) { // final dob = lineText.split('DOB')[1].trim(); // extractedData['dob'] = dob; // } // // if (lineText.contains("LN")) { // if ((lineText.indexOf("LN") == 0)) { // final lastName = lineText.split('LN')[1].trim(); // extractedData['lastName'] = lastName; // } // } // if (lineText.contains("FN")) { // final firstName = lineText.split('FN')[1].trim(); // extractedData['firstName'] = firstName; // } // if (lineText.contains("RSTR")) { // final rstr = lineText.split('RSTR')[1].trim(); // extractedData['rstr'] = rstr; // } // if (lineText.contains("CLASS")) { // final class1 = lineText.split('CLASS')[1].trim(); // extractedData['class'] = class1; // } // if (lineText.contains("END")) { // final end = lineText.split('END')[1].trim(); // extractedData['end'] = end; // } // if (lineText.contains("DD")) { // final dd = lineText.split('DD')[1].trim(); // extractedData['dd'] = dd; // } // if (lineText.contains("EYES")) { // final eyes = lineText.split('EYES')[1].trim(); // extractedData['eyes'] = eyes; // } // if (lineText.contains("SEX")) { // final parts = lineText.split("SEX ")[1]; // extractedData['sex'] = parts[0]; // } // if (lineText.contains("HAIR")) { // final hair = lineText.split('HAIR')[1].trim(); // extractedData['hair'] = hair; // } // // if (lineText.contains('STREET') || lineText.contains(',')) { // final address = lineText; // extractedData['address'] = address; // } // // // Repeat this process for other relevant data fields // } // } // // // Convert the list of lines to a JSON string // jsonOutput = jsonEncode(extractedData); // decode = jsonDecode(jsonOutput!); // // update(); // } // } class ScanDocumentsByApi extends GetxController { bool isLoading = false; Map responseMap = {}; final ImagePicker imagePicker = ImagePicker(); late Uint8List imagePortrait; late Uint8List imageSignature; late Uint8List imageDocumentFrontSide; XFile? image; XFile? imagePortraitFile; XFile? imageFace; late File tempFile; late String imagePath; DateTime now = DateTime.now(); late String name; late String licenseClass; late String documentNo; late String address; late String stateCode; late String height; late String sex; late String postalCode; late String dob; late String expireDate; // /////////////////////// // late CameraController cameraController; // late List cameras; // bool isCameraInitialized = false; // // final TextRecognizer _textRecognizer = TextRecognizer(); // String? scannedText; // Future initializeCamera(int cameraID) async { // try { // cameras = await availableCameras(); // //update(); // cameraController = CameraController( // cameras[cameraID], // ResolutionPreset.medium, // enableAudio: false, // ); // await cameraController.initialize(); // isCameraInitialized = true; // update(); // } catch (e) { // if (e is CameraException) { // switch (e.code) { // case 'CameraAccessDenied': // Get.defaultDialog( // title: 'Camera Access Denied.'.tr, // middleText: '', // confirm: // MyElevatedButton(title: 'Open Settings', onPressed: () {}), // ); // break; // default: // // Handle other errors here. // break; // } // } // } // } /// Future scanDocumentsByApi() async { // String? visionApi = await storage.read(key: BoxName.visionApi); // String? visionApi = AK.visionApi; // Pick an image from the camera or gallery image = await imagePicker.pickImage(source: ImageSource.camera); // // If no image was picked, return if (image == null) { return; } isLoading = true; update(); var headers = {'X-BLOBR-KEY': AK.visionApi}; var request = http.MultipartRequest('POST', Uri.parse('https://api.faceonlive.com/j2y3q25y1b6maif1/api/iddoc')); request.files.add(await http.MultipartFile.fromPath('image', image!.path)); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { String responseString = await response.stream.bytesToString(); responseMap = jsonDecode(responseString); var ocrData = responseMap['data']['ocr']; name = ocrData['name'].toString(); licenseClass = ocrData['dlClass'].toString(); documentNo = ocrData['documentNumber'].toString(); address = ocrData['address'].toString(); height = ocrData['height'].toString(); postalCode = ocrData['addressPostalCode'].toString(); sex = ocrData['sex'].toString(); stateCode = ocrData['addressJurisdictionCode'].toString(); expireDate = ocrData['dateOfExpiry'].toString(); dob = ocrData['dateOfBirth'].toString(); if (responseMap['data'] != null && responseMap['data']['image'] != null && responseMap['data']['image']['portrait'] != null) { imagePortrait = base64Decode(responseMap['data']['image']['portrait']); String tempPath = Directory.systemTemp.path; tempFile = File('$tempPath/image.jpg'); await tempFile.writeAsBytes(imagePortrait); imagePath = tempFile.path; // imagePortraitFile=File(imagePath) ; update(); } else { // Handle error or provide a default value } if (responseMap['data']['image']['signature'] != null) { imageSignature = base64Decode(responseMap['data']['image']['signature']); } else { imageSignature = imagePortrait; // Handle error or provide a default value } if (responseMap['data'] != null && responseMap['data']['image'] != null && responseMap['data']['image']['documentFrontSide'] != null) { imageDocumentFrontSide = base64Decode(responseMap['data']['image']['documentFrontSide']); } else { // Handle error or provide a default value } isLoading = false; update(); } else {} } late int times; Future checkMatchFaceApi() async { sql.getAllData(TableName.faceDetectTimes).then((value) { if (value.isEmpty || value == null) { sql.insertData({'faceDetectTimes': 1}, TableName.faceDetectTimes); sql.getAllData(TableName.faceDetectTimes).then((value) { times = value[0]['faceDetectTimes']; update(); }); } else { if (times < 4) { times++; matchFaceApi(); sql.updateData( {'faceDetectTimes': times}, TableName.faceDetectTimes, 1); } else { Get.defaultDialog( barrierDismissible: false, title: 'You have finished all times '.tr, titleStyle: AppStyle.title, middleText: 'if you want help you can email us here'.tr, middleTextStyle: AppStyle.title, cancel: MyElevatedButton( title: 'Thanks'.tr, kolor: AppColor.greenColor, onPressed: () => Get.back(), ), confirm: MyElevatedButton( title: 'Email Us'.tr, kolor: AppColor.yellowColor, // onPressed: () { launchCommunication('email', 'support@mobile-app.store', '${'Hi'.tr} ${AppInformation.appName}\n${'I cant register in your app in face detection '.tr}'); Get.back(); }, )); } } }); } Map res = {}; Future matchFaceApi() async { // String? visionApi = await storage.read(key: BoxName.visionApi); imageFace = await imagePicker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.front, ); // If no image was picked, return if (image == null) { return; } final imageFile = File(imageFace!.path); // Uint8List imageBytes = await imageFile.readAsBytes(); var headers = {'X-BLOBR-KEY': AK.visionApi}; var request = http.MultipartRequest( 'POST', Uri.parse( 'https://api.faceonlive.com/sntzbspfsdupgid1/api/face_compare')); request.files .add(await http.MultipartFile.fromPath('image1', imageFile.path)); request.files.add(await http.MultipartFile.fromPath('image2', imagePath)); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { res = jsonDecode(await response.stream.bytesToString()); update(); res['data']['result'].toString().contains('No face detected in image') ? Get.defaultDialog( barrierDismissible: false, title: 'No face detected'.tr, middleText: ''.tr, titleStyle: AppStyle.title, confirm: MyElevatedButton( kolor: AppColor.yellowColor, title: 'Back'.tr, onPressed: () { Get.back(); }, )) // : Get.defaultDialog( // barrierDismissible: false, title: 'Image detecting result is '.tr, titleStyle: AppStyle.title, content: Column( children: [ Text( res['data']['result'].toString(), style: res['data']['result'].toString() == 'Different' ? AppStyle.title.copyWith(color: AppColor.redColor) : AppStyle.title.copyWith(color: AppColor.greenColor), ), res['data']['result'].toString() == 'Different' ? Text( '${'Be sure for take accurate images please\nYou have'.tr} $times ${'from 3 times Take Attention'.tr}', style: AppStyle.title, ) : Text( 'image verified'.tr, style: AppStyle.title, ) ], ), confirm: res['data']['result'].toString() == 'Different' ? MyElevatedButton( title: 'Back'.tr, onPressed: () => Get.back(), kolor: AppColor.redColor, ) : MyElevatedButton( title: 'Next'.tr, onPressed: () async { RegisterCaptainController registerCaptainController = Get.put(RegisterCaptainController()); await registerCaptainController.register(); await registerCaptainController.addLisence(); await uploadImagePortrate(); // Get.to(() => CarLicensePage()); }, // { // await uploadImage( // tempFile, AppLink.uploadImagePortrate); // Get.to(() => CarLicensePage()); // }, kolor: AppColor.greenColor, )); } else {} } // Todo upload images and fields Future uploadImagePortrate() async { isLoading = true; update(); var request = http.MultipartRequest( 'POST', Uri.parse(AppLink.uploadImagePortrate), ); request.files.add( http.MultipartFile.fromBytes('image', imagePortrait), ); request.headers.addAll({ "Content-Type": "multipart/form-data", 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }); request.fields['driverID'] = box.read(BoxName.driverID).toString(); var response = await request.send(); var responseData = await response.stream.toBytes(); var responseString = String.fromCharCodes(responseData); isLoading = false; update(); // Print the response string return responseString; } @override void onInit() { // scanDocumentsByApi(); // initializeCamera(0); sql.getAllData(TableName.faceDetectTimes).then((value) { if (value.isEmpty) { times = 0; update(); // sql.insertData({'faceDetectTimes': 1}, TableName.faceDetectTimes); } else { times = value[0]['faceDetectTimes']; } }); super.onInit(); } } // class PassportDataExtractor extends GetxController { // @override // void onInit() { // extractPassportData(); // super.onInit(); // } // // final ImagePicker _imagePicker = ImagePicker(); // late final XFile? image; // final TextRecognizer _textRecognizer = TextRecognizer(); // // Future> extractPassportData() async { // image = await _imagePicker.pickImage(source: ImageSource.gallery); // update(); // if (image == null) { // throw Exception('No image picked'); // } // // final InputImage inputImage = InputImage.fromFile(File(image!.path)); // final RecognizedText recognisedText = // await _textRecognizer.processImage(inputImage); // // final Map extractedData = {}; // final List> extractedTextWithCoordinates = []; // // for (TextBlock block in recognisedText.blocks) { // for (TextLine line in block.lines) { // final String lineText = line.text; // final Rect lineBoundingBox = line.boundingBox!; // // extractedTextWithCoordinates.add({ // 'text': lineText, // 'boundingBox': { // 'left': lineBoundingBox.left, // 'top': lineBoundingBox.top, // 'width': lineBoundingBox.width, // 'height': lineBoundingBox.height, // }, // }); // // // if (lineText.contains('Passport Number')) { // // final String passportNumber = // // lineText.split('Passport Number')[1].trim(); // // extractedData['passportNumber'] = passportNumber; // // } // // if (lineText.contains('Given Names')) { // // final String givenNames = lineText.split('Given Names')[1].trim(); // // extractedData['givenNames'] = givenNames; // // } // // if (lineText.contains('Surname')) { // // final String surname = lineText.split('Surname')[1].trim(); // // extractedData['surname'] = surname; // // } // // if (lineText.contains('Nationality')) { // // final String nationality = lineText.split('Nationality')[1].trim(); // // extractedData['nationality'] = nationality; // // } // // if (lineText.contains('Date of Birth')) { // // final String dob = lineText.split('Date of Birth')[1].trim(); // // extractedData['dateOfBirth'] = dob; // // } // // Add more field extraction conditions as needed // } // } // // extractedData['extractedTextWithCoordinates'] = // extractedTextWithCoordinates; // return extractedData; // } // } // // class PassportDataController extends GetxController { // PassportDataExtractor passportDataExtractor = PassportDataExtractor(); // List> extractedTextWithCoordinates = []; // // Future extractDataAndDrawBoundingBoxes() async { // try { // Map extractedData = // await passportDataExtractor.extractPassportData(); // extractedTextWithCoordinates = // extractedData['extractedTextWithCoordinates']; // update(); // Notify GetX that the state has changed // } catch (e) { // } // } // } // // class BoundingBoxPainter extends CustomPainter { // final List> boundingBoxes; // // BoundingBoxPainter(this.boundingBoxes); // // @override // void paint(Canvas canvas, Size size) { // final Paint paint = Paint() // ..color = Colors.red // ..style = PaintingStyle.stroke // ..strokeWidth = 2.0; // // for (Map boundingBox in boundingBoxes) { // double left = boundingBox['left']; // double top = boundingBox['top']; // double width = boundingBox['width']; // double height = boundingBox['height']; // // Rect rect = Rect.fromLTWH(left, top, width, height); // canvas.drawRect(rect, paint); // } // } // // @override // bool shouldRepaint(covariant CustomPainter oldDelegate) { // return false; // } // } ================================================== FILE PATH: ./lib/controller/functions/document_scanner.dart ================================================== // import 'dart:io'; // // import 'package:get/get.dart'; // import 'package:image_picker/image_picker.dart'; // import 'package:google_ml_kit/google_ml_kit.dart'; // // class ImagePickerController extends GetxController { // RxBool textScanning = false.obs; // RxString scannedText = ''.obs; // // Future getImage(ImageSource source) async { // try { // final pickedImage = await ImagePicker().pickImage(source: source); // if (pickedImage != null) { // textScanning.value = true; // final imageFile = File(pickedImage.path); // getRecognisedText(imageFile); // } // } catch (e) { // textScanning.value = false; // scannedText.value = "Error occurred while scanning"; // } // } // // Future getRecognisedText(File image) async { // final inputImage = InputImage.fromFilePath(image.path); // final textDetector = GoogleMlKit.vision.textRecognizer(); // final RecognizedText recognisedText = // await textDetector.processImage(inputImage); // await textDetector.close(); // // scannedText.value = ''; // for (TextBlock block in recognisedText.blocks) { // for (TextLine line in block.lines) { // scannedText.value += line.text + '\n'; // } // } // // textScanning.value = false; // } // } ================================================== FILE PATH: ./lib/controller/functions/secure_storage.dart ================================================== import 'dart:convert'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart'; import '../../constant/box_name.dart'; import '../../constant/char_map.dart'; import '../../constant/info.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../../print.dart'; import 'crud.dart'; class SecureStorage { final FlutterSecureStorage _storage = const FlutterSecureStorage(); void saveData(String key, value) async { await _storage.write(key: key, value: value); } Future readData(String boxName) async { final String? value = await _storage.read(key: boxName); return value; } } const List keysToFetch = [ 'serverPHP', 'seferAlexandriaServer', 'seferPaymentServer', 'seferCairoServer', 'seferGizaServer', ]; class AppInitializer { List> links = []; Future initializeApp() async { if (box.read(BoxName.jwt) == null) { await LoginDriverController().getJWT(); } else { bool isTokenExpired = JwtDecoder.isExpired(X .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) .toString() .split(AppInformation.addd)[0]); if (isTokenExpired) { await LoginDriverController().getJWT(); } } // await getKey(); } Future getAIKey(String key1) async { var res = await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1}); if (res != 'failure') { var d = jsonDecode(res)['message']; final rawValue = d[key1].toString(); // ✅ اكتبها في storage await storage.write(key: key1, value: rawValue); await Future.delayed(Duration.zero); } } Future getKey() async { try { var res = await CRUD().get(link: AppLink.getLocationAreaLinks, payload: {}); if (res != 'failure') { links = List>.from(jsonDecode(res)['message']); await box.write(BoxName.locationName, links); await box.write(BoxName.basicLink, (links[0]['server_link'])); await box.write(links[2]['name'], (links[2]['server_link'])); await box.write(links[1]['name'], (links[3]['server_link'])); await box.write(links[3]['name'], (links[1]['server_link'])); await box.write(BoxName.paymentLink, (links[4]['server_link'])); } } catch (e) {} } } ================================================== FILE PATH: ./lib/controller/functions/camer_controller.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:camera/camera.dart'; import 'package:get/get.dart'; // import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import 'package:path/path.dart' as path; import 'package:http/http.dart' as http; import '../../main.dart'; class CameraClassController extends GetxController { late CameraController cameraController; late List cameras; bool isCameraInitialized = false; // final TextRecognizer _textRecognizer = TextRecognizer(); String? scannedText; bool isloading = false; @override void onInit() { super.onInit(); initializeCamera(); } Future initializeCamera() async { try { cameras = await availableCameras(); //update(); cameraController = CameraController( cameras[0], ResolutionPreset.medium, enableAudio: false, ); await cameraController.initialize(); isCameraInitialized = true; update(); } catch (e) { if (e is CameraException) { switch (e.code) { case 'CameraAccessDenied': Get.defaultDialog( title: 'Camera Access Denied.'.tr, middleText: '', confirm: MyElevatedButton(title: 'Open Settings'.tr, onPressed: () {}), ); break; default: // Handle other errors here. break; } } } } var imgUrl = ''; Future extractCardId() async { // Construct the path for the image file final directory = await path_provider.getTemporaryDirectory(); final imagePath = path.join(directory.path, '${box.read(BoxName.driverID)}.png'); // Capture the image and save it to the specified path final XFile capturedImage = await cameraController.takePicture(); // Move the captured image to the desired path await capturedImage.saveTo(imagePath); await uploadImage(File(capturedImage.path)); extractByAPI('${AppLink.server}/card_image/' + box.read(BoxName.driverID)); } Future extractByAPI(String imgUrl) async { var headers = {'apikey': 'K89368168788957'}; var request = http.MultipartRequest( 'POST', Uri.parse('https://api.ocr.space/parse/image')); request.fields.addAll({ 'language': 'ara', 'isOverlayRequired': 'false', 'url': imgUrl, 'iscreatesearchablepdf': 'false', 'issearchablepdfhidetextlayer': 'false' }); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { } else {} } Future uploadImage(File imageFile) async { String? basicAuthCredentials = await storage.read(key: BoxName.basicAuthCredentials); var request = http.MultipartRequest( 'POST', Uri.parse(AppLink.uploadImage), ); // Attach the image file to the request request.files.add( await http.MultipartFile.fromPath('image', imageFile.path), ); // Add the headers to the request request.headers.addAll({ "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Basic ${base64Encode(utf8.encode(basicAuthCredentials.toString()))}', }); // Add the driverID to the request request.fields['driverID'] = box.read(BoxName.driverID); // Send the request var response = await request.send(); // Read the response var responseData = await response.stream.toBytes(); var responseString = String.fromCharCodes(responseData); scannedText = responseString; update(); // Return the link received from the server return responseString; } // Future takePictureAndMLGoogleScan() async { // try { // // Construct the path for the image file // final directory = await path_provider.getTemporaryDirectory(); // final imagePath = // path.join(directory.path, '${box.read(BoxName.driverID)}.png'); // // Capture the image and save it to the specified path // final XFile capturedImage = await cameraController.takePicture(); // // Move the captured image to the desired path // await capturedImage.saveTo(imagePath); // // Recognize the text in the image // final InputImage inputImage = // InputImage.fromFile(File(capturedImage.path)); // final RecognizedText recognizedText = // await _textRecognizer.processImage(inputImage); // scannedText = recognizedText.text; // // Extract the scanned text line by line // final List> lines = []; // for (var i = 0; i < recognizedText.blocks.length; i++) { // lines.add({ // 'line_number': i, // 'text': recognizedText.blocks[i].text, // }); // } // // Convert the list of lines to a JSON string // final String jsonOutput = jsonEncode(lines); // update(); // // Print the JSON output // // Get.back(); // } catch (e) {} // } String getTextAsJSON(String text) { final lines = text.split('\n'); final jsonList = lines.map((line) { return { 'line_text': line, 'num_words': line.trim().split(' ').length, }; }).toList(); final json = { 'lines': jsonList, 'num_lines': lines.length, }; return jsonEncode(json); } List getTextBlocks(String text) { return text.split('\n'); } // Future takePictureAndTesseractScan() async { // try { // // Construct the path for the image file // final directory = await path_provider.getTemporaryDirectory(); // final imagePath = // path.join(directory.path, '${box.read(BoxName.driverID)}.png'); // // Capture the image and save it to the specified path // final XFile capturedImage = await cameraController.takePicture(); // // Move the captured image to the desired path // await capturedImage.saveTo(imagePath); // // Recognize the text in the image // final languages = [ // 'eng', // 'ara' // ]; // Specify the languages you want to use for text extraction // final text = await FlutterTesseractOcr.extractText(imagePath, // language: languages.join('+'), // Combine multiple languages with '+' // args: { // "psm": "4", // "preserve_interword_spaces": "1", // // "rectangle": const Rect.fromLTWH(100, 100, 200, 200), // } // Additional options if needed // ); // isloading = false; // final jsonText = getTextAsJSON(text); // final textBlocks = getTextBlocks(text); // update(); // scannedText = // textBlocks.toString(); // Convert the extracted text to JSON. // // Print the JSON to the console. // update(); // } catch (e) { // scannedText = ''; // } // } @override void onClose() { cameraController.dispose(); super.onClose(); } } ================================================== FILE PATH: ./lib/controller/functions/vibrate.dart ================================================== import 'package:get/get.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; class HomePageController extends GetxController { late bool isVibrate = box.read(BoxName.isvibrate) ?? true; void changeVibrateOption(bool value) { isVibrate = box.read(BoxName.isvibrate) ?? true; isVibrate = value; box.write(BoxName.isvibrate, value); update(); } } ================================================== FILE PATH: ./lib/controller/functions/audio_controller.dart ================================================== import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; import 'package:get/get.dart'; class AudioController extends GetxController { final AudioPlayer _audioPlayer = AudioPlayer(); Future playAudio() async { // Check if the platform is Android if (Theme.of(Get.context!).platform == TargetPlatform.android) { try { // Load the audio file from the raw resources await _audioPlayer.setAsset( 'assets/order1.wav'); // Adjust the path based on your project structure _audioPlayer.play(); } catch (e) { // Handle errors, such as file not found print('Error playing audio: $e'); } } } Future playAudio1(String path) async { // Check if the platform is Android // if (Theme.of(Get.context!).platform == TargetPlatform.android) { try { // Load the audio file from the raw resources await _audioPlayer .setAsset(path); // Adjust the path based on your project structure _audioPlayer.play(); } catch (e) { // Handle errors, such as file not found print('Error playing audio: $e'); } // } } @override void onClose() { // Release resources when done _audioPlayer.dispose(); super.onClose(); } } ================================================== FILE PATH: ./lib/controller/functions/llama_ai.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/functions/gemeni.dart'; class LlamaAi { Future getCarRegistrationData(String input, prompt) async { Map exrtatDataFinal = {}; String oneLine = input.replaceAll('\n', ' '); // var res = await CRUD().getLlama(link: AppLink.gemini, payload: oneLine); var res = await CRUD() .getLlama(link: AppLink.llama, payload: oneLine, prompt: prompt); var decod = jsonDecode(res.toString()); // exrtatDataFinal = jsonDecode(extractDataFromJsonString(decod['choices'])); extractDataFromJsonString(decod['choices'][0]['message']['content']); return exrtatDataFinal; } String extractDataFromJsonString(String jsonString) { // Remove any leading or trailing whitespace from the string jsonString = jsonString.trim(); // Extract the JSON substring from the given string final startIndex = jsonString.indexOf('{'); final endIndex = jsonString.lastIndexOf('}'); final jsonSubstring = jsonString.substring(startIndex, endIndex + 1); // Parse the JSON substring into a Map final jsonData = jsonDecode(jsonSubstring); // Return the extracted data return jsonEncode(jsonData); } } ================================================== FILE PATH: ./lib/controller/functions/location_permission.dart ================================================== import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; import '../../print.dart'; import '../../views/widgets/mydialoug.dart'; import '../auth/captin/login_captin_controller.dart'; class LocationPermissions { // late Location location; // Future locationPermissions() async { // location = Location(); // var permissionStatus = await location.requestPermission(); // if (permissionStatus == PermissionStatus.denied) { // // The user denied the location permission. // Get.defaultDialog(title: 'GPS Required Allow !.'.tr, middleText: ''); // return null; // } // } } Future getPermissionLocation() async { final PermissionStatus status = await Permission.locationAlways.status; if (!await Permission.locationAlways.serviceStatus.isEnabled) { Log.print('status.isGranted: ${status.isGranted}'); // box.write(BoxName.locationPermission, 'true'); await Permission.locationAlways.request(); Get.put(LoginDriverController()).update(); MyDialog().getDialog( 'Enable Location Permission'.tr, // {en:ar} 'Allowing location access will help us display orders near you. Please enable it now.' .tr, // {en:ar} () async { Get.back(); box.write(BoxName.locationPermission, 'true'); await Permission.locationAlways.request(); }, ); } } Future getPermissionLocation1() async { PermissionStatus status = await Permission.locationWhenInUse.request(); if (status.isGranted) { // After granting when in use, request "always" location permission status = await Permission.locationAlways.request(); if (status.isGranted) { print("Background location permission granted"); } else { print("Background location permission denied"); } } else { print("Location permission denied"); await openAppSettings(); } } ================================================== FILE PATH: ./lib/controller/functions/location_controller.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:math'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:location/location.dart'; import 'package:battery_plus/battery_plus.dart'; // **إضافة جديدة:** للتعامل مع حالة البطارية import 'package:sefer_driver/constant/table_names.dart'; import '../../constant/box_name.dart'; import '../../constant/links.dart'; import '../../main.dart'; import '../../print.dart'; import '../home/captin/home_captain_controller.dart'; import '../home/payment/captain_wallet_controller.dart'; import 'crud.dart'; /// LocationController - النسخة النهائية المتكاملة مع وضع توفير الطاقة /// /// تم تصميم هذا المتحكم ليكون المحرك الجديد لإدارة الموقع في تطبيقك. /// يجمع بين الكفاءة العالية، المنطق الذكي، والتوافق الكامل مع بنية الكود الحالية. class LocationController extends GetxController { // =================================================================== // ====== Tunables / المتغيرات القابلة للتعديل ====== // =================================================================== // -- Normal Mode -- static const double onMoveMetersNormal = 15.0; static const double offMoveMetersNormal = 200.0; static const Duration trackInsertEveryNormal = Duration(minutes: 1); static const Duration heartbeatEveryNormal = Duration(minutes: 2); // -- Power Saving Mode -- static const double onMoveMetersPowerSave = 75.0; static const double offMoveMetersPowerSave = 500.0; static const Duration trackInsertEveryPowerSave = Duration(minutes: 2); static const Duration heartbeatEveryPowerSave = Duration(minutes: 5); static const double lowWalletThreshold = -300; static const int powerSaveTriggerLevel = 20; // نسبة البطارية لتفعيل وضع التوفير static const int powerSaveExitLevel = 25; // نسبة البطارية للخروج من وضع التوفير // -- الوضع الطبيعي -- // تسجيل نقطة في الذاكرة كل 3 ثواني (دقة عالية جداً) static const Duration recordIntervalNormal = Duration(seconds: 3); // رفع البيانات للسيرفر كل دقيقتين static const Duration uploadIntervalNormal = Duration(minutes: 2); // -- وضع توفير الطاقة -- // تسجيل نقطة كل 6 ثواني (نقلل الدقة قليلاً) static const Duration recordIntervalPowerSave = Duration(seconds: 6); // رفع البيانات كل 4 دقائق static const Duration uploadIntervalPowerSave = Duration(minutes: 4); // =================================================================== // ====== Services & Subscriptions (الخدمات والاشتراكات) ====== // =================================================================== late final Location location = Location(); final Battery _battery = Battery(); // **إضافة جديدة:** للتعامل مع البطارية StreamSubscription? _locSub; StreamSubscription? _batterySub; Timer? _trackInsertTimer; Timer? _heartbeatTimer; // =================================================================== // ====== Cached Controllers (لتجنب Get.find المتكرر) ====== // =================================================================== late final HomeCaptainController _homeCtrl; late final CaptainWalletController _walletCtrl; // =================================================================== // ====== Public state (لواجهة المستخدم والكلاسات الأخرى) ====== // =================================================================== LatLng myLocation = const LatLng(0, 0); double heading = 0.0; double speed = 0.0; double totalDistance = 0.0; // =================================================================== // ====== Internal state (للمنطق الداخلي) ====== // =================================================================== bool _isReady = false; bool _isPowerSavingMode = false; // **إضافة جديدة:** لتتبع وضع توفير الطاقة LatLng? _lastSentLoc; String? _lastSentStatus; DateTime? _lastSentAt; LatLng? _lastPosForDistance; // =================================================================== // ====== المتغيرات الجديدة لنظام الباتش ====== // =================================================================== // هذه القائمة هي "الصندوق" الذي نجمع فيه النقاط قبل الإرسال final List> _trackBuffer = []; Timer? _recordTimer; // مؤقت التسجيل السريع Timer? _uploadTimer; // مؤقت الرفع البطيء // **إضافة جديدة:** متغيرات لحساب سلوك السائق LatLng? _lastSqlLoc; double? _lastSpeed; DateTime? _lastSpeedAt; @override Future onInit() async { super.onInit(); print('LocationController onInit started...'); bool dependenciesReady = await _awaitDependencies(); if (!dependenciesReady) { print( "❌ CRITICAL ERROR: Dependencies not found. Location services will not start."); return; } _isReady = true; await _initLocationSettings(); await startLocationUpdates(); _listenToBatteryChanges(); // **إضافة جديدة:** بدء الاستماع لتغيرات البطارية print('✅ LocationController is ready and initialized.'); } @override void onClose() { print('🛑 Closing LocationController...'); stopLocationUpdates(); _batterySub?.cancel(); // إيقاف الاستماع للبطارية super.onClose(); } Future _awaitDependencies() async { // ... (الكود لم يتغير) int attempts = 0; while (attempts < 10) { if (Get.isRegistered() && Get.isRegistered()) { _homeCtrl = Get.find(); _walletCtrl = Get.find(); print("✅ Dependencies found and controllers are cached."); return true; } await Future.delayed(const Duration(milliseconds: 500)); attempts++; } return false; } // =================================================================== // ====== Public Control Methods (دوال التحكم العامة) ====== // =================================================================== Future startLocationUpdates() async { // ... (الكود لم يتغير) if (!_isReady) { print("Cannot start updates: LocationController is not ready."); return; } final points = _walletCtrl.totalPoints; if (double.parse(points) <= lowWalletThreshold) { print('❌ Blocked: low wallet balance ($points)'); stopLocationUpdates(); return; } if (_locSub != null) { print('Location updates are already active.'); return; } if (await _ensureServiceAndPermission()) { _subscribeLocationStream(); _startTimers(); } } void _startTimers() { // نلغي المؤقتات القديمة إن وجدت _recordTimer?.cancel(); _uploadTimer?.cancel(); _heartbeatTimer ?.cancel(); // الهارت بيت يبقى كما هو إذا أردت إبقاء السائق "متصلاً" // تحديد المدة بناء على وضع البطارية final recordDuration = _isPowerSavingMode ? recordIntervalPowerSave : recordIntervalNormal; final uploadDuration = _isPowerSavingMode ? uploadIntervalPowerSave : uploadIntervalNormal; // 1. مؤقت التسجيل السريع (يخزن في الرام فقط) _recordTimer = Timer.periodic(recordDuration, (_) => _recordCurrentLocationToBuffer()); // 2. مؤقت الرفع (يأخذ ما في الرام ويرفعه للسيرفر) _uploadTimer = Timer.periodic(uploadDuration, (_) => _flushBufferToServer()); // 3. الهارت بيت (اختياري: لتحديث حالة الأونلاين في جدول السائقين فقط وليس التراكات) // سنجعله يعمل كل فترة لتحديث created_at في جدول update.php _heartbeatTimer = Timer.periodic( const Duration(minutes: 2), (_) => _sendStationaryHeartbeat()); print( '⏱️ Batch Tracking Started: Record every ${recordDuration.inSeconds}s, Upload every ${uploadDuration.inMinutes}m'); } /// هذه الدالة تعمل كل 3 ثواني: تخزن المكان الحالي في القائمة // متغير لحفظ آخر مكان حقيقي تم اعتماده (وليس مجرد آخر قراءة) LatLng? _lastRecordedRealLoc; // متغير لحفظ وقت آخر تسجيل فعلي DateTime? _lastRecordedTime; void _recordCurrentLocationToBuffer() { if (!_isReady) return; if (myLocation.latitude == 0 && myLocation.longitude == 0) return; final String driverStatus = (box.read(BoxName.statusDriverLocation) ?? 'off').toString(); final DateTime now = DateTime.now(); double distFromLast = 0.0; if (_lastRecordedRealLoc != null) { distFromLast = _haversineMeters(_lastRecordedRealLoc!, myLocation); } // ============================================================ // 🚦 الفلتر المتوازن (Balanced Filter) // ============================================================ // 1. هل تحرك مسافة مقبولة؟ (خفضناها لـ 10 متر بدل 20) bool movedEnough = distFromLast > 10.0; // 2. هل السرعة تشير إلى حركة؟ (أكثر من 3 كم/س) bool isMoving = speed > 0.8; // 3. 🔥 التعديل الهام: هل مر وقت طويل دون تسجيل؟ (30 ثانية) // هذا يضمن وجود نقاط حتى لو السائق عالق في زحمة أو واقف bool timeForced = false; if (_lastRecordedTime != null) { if (now.difference(_lastRecordedTime!).inSeconds >= 30) { timeForced = true; } } else { timeForced = true; // أول مرة دائماً نسجل } // القرار النهائي: نسجل إذا تحرك مسافة جيدة، أو إذا مر وقت طويل bool shouldRecord = (movedEnough && isMoving) || timeForced; // ============================================================ if (shouldRecord) { _lastRecordedRealLoc = myLocation; _lastRecordedTime = now; // تحديث وقت آخر تسجيل // نزيد المسافة التراكمية فقط إذا كانت حركة مكانية (وليس تسجيل زمني وهو واقف) if (movedEnough) { totalDistance += distFromLast; } final Map point = { 'lat': double.parse(myLocation.latitude.toStringAsFixed(6)), 'lng': double.parse(myLocation.longitude.toStringAsFixed(6)), 'spd': double.parse(speed.toStringAsFixed(1)), 'head': int.parse(heading.toStringAsFixed(0)), // نرسل المسافة المقطوعة في هذه الخطوة (0 إذا كان واقفاً وتم التسجيل بسبب الوقت) 'dst': movedEnough ? double.parse(distFromLast.toStringAsFixed(1)) : 0.0, 'st': driverStatus, 'ts': now.toIso8601String(), }; _trackBuffer.add(point); // جملة طباعة لتتأكد أن الكود يجمع نقاط print( '✅ Buffer Add: List Size is now ${_trackBuffer.length} (Forced: $timeForced)'); } } /// هذه الدالة تعمل كل دقيقتين: ترفع القائمة للسيرفر وتفرغها Future _flushBufferToServer() async { if (_trackBuffer.isEmpty) return; // نأخذ نسخة من البيانات ونفرغ القائمة الأصلية فوراً عشان المؤقت السريع يكمل شغل List> batchToSend = List.from(_trackBuffer); _trackBuffer.clear(); final String driverId = (box.read(BoxName.driverID) ?? '').toString(); print('🚀 Uploading Batch: ${batchToSend.length} points...'); try { // نحول القائمة لنص JSON final String jsonPayload = jsonEncode(batchToSend); await CRUD().post( link: '${AppLink.locationServer}/add_batch.php', // 👈 ملف PHP الجديد payload: { 'driver_id': driverId, 'batch_data': jsonPayload, // نرسل البيانات كـ JSON String }, ); print('✅ Batch uploaded successfully.'); } catch (e) { print('❌ FAILED to upload batch: $e'); // (خيار متقدم): في حالة الفشل، يمكن إرجاع البيانات للقائمة لرفعها المحاولة القادمة // _trackBuffer.insertAll(0, batchToSend); } } void stopLocationUpdates() { // ... (الكود لم يتغير) _locSub?.cancel(); _locSub = null; _trackInsertTimer?.cancel(); _trackInsertTimer = null; _heartbeatTimer?.cancel(); _heartbeatTimer = null; print('Location updates and timers stopped.'); } Future getLocation() async { // ... (الكود لم يتغير) try { if (await _ensureServiceAndPermission()) { return await location.getLocation(); } } catch (e) { print('❌ FAILED to get single location: $e'); } return null; } // =================================================================== // ====== Core Logic (المنطق الأساسي) ====== // =================================================================== Future _initLocationSettings() async { // ... (الكود لم يتغير) await location.changeSettings( accuracy: LocationAccuracy.high, interval: 5000, distanceFilter: 0, ); await location.enableBackgroundMode(enable: true); } Future _ensureServiceAndPermission() async { // ... (الكود لم يتغير) bool serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) return false; } var perm = await location.hasPermission(); if (perm == PermissionStatus.denied) { perm = await location.requestPermission(); if (perm != PermissionStatus.granted) return false; } return true; } void _subscribeLocationStream() { _locSub?.cancel(); _locSub = location.onLocationChanged.listen( (loc) async { if (!_isReady) return; try { if (loc.latitude == null || loc.longitude == null) return; final now = DateTime.now(); final pos = LatLng(loc.latitude!, loc.longitude!); myLocation = pos; speed = loc.speed ?? 0.0; heading = loc.heading ?? 0.0; if (_lastPosForDistance != null) { final d = _haversineMeters(_lastPosForDistance!, pos); if (d > 2.0) totalDistance += d; } _lastPosForDistance = pos; // ✅ تحديث الكاميرا // _homeCtrl.mapHomeCaptainController?.animateCamera( // CameraUpdate.newCameraPosition( // CameraPosition( // bearing: Get.find().heading, // target: myLocation, // zoom: 17, // Adjust zoom level as needed // ), // ), // ); update(); // تحديث الواجهة الرسومية بالبيانات الجديدة await _smartSend(pos, loc); // **إضافة جديدة:** حفظ سلوك السائق في قاعدة البيانات المحلية await _saveBehaviorIfMoved(pos, now, currentSpeed: speed); } catch (e) { print('Error in onLocationChanged: $e'); } }, onError: (e) => print('Location stream error: $e'), ); print('📡 Subscribed to location stream.'); } // void _startTimers() { // _trackInsertTimer?.cancel(); // _heartbeatTimer?.cancel(); // final trackDuration = // _isPowerSavingMode ? trackInsertEveryPowerSave : trackInsertEveryNormal; // final heartbeatDuration = // _isPowerSavingMode ? heartbeatEveryPowerSave : heartbeatEveryNormal; // _trackInsertTimer = // Timer.periodic(trackDuration, (_) => _addSingleTrackPoint()); // _heartbeatTimer = // Timer.periodic(heartbeatDuration, (_) => _sendStationaryHeartbeat()); // print('⏱️ Background timers started (Power Save: $_isPowerSavingMode).'); // } Future _smartSend(LatLng pos, LocationData loc) async { final String driverStatus = box.read(BoxName.statusDriverLocation) ?? 'off'; final distSinceSent = (_lastSentLoc == null) ? 999.0 : _haversineMeters(_lastSentLoc!, pos); final onMoveThreshold = _isPowerSavingMode ? onMoveMetersPowerSave : onMoveMetersNormal; final offMoveThreshold = _isPowerSavingMode ? offMoveMetersPowerSave : offMoveMetersNormal; bool shouldSend = false; if (driverStatus != _lastSentStatus) { shouldSend = true; if (driverStatus == 'on') { totalDistance = 0.0; _lastPosForDistance = pos; } print( 'Status changed: ${_lastSentStatus ?? '-'} -> $driverStatus. Sending...'); } else if (driverStatus == 'on') { if (distSinceSent >= onMoveThreshold) { shouldSend = true; } } else { // driverStatus == 'off' if (distSinceSent >= offMoveThreshold) { shouldSend = true; } } if (!shouldSend) return; await _sendUpdate(pos, driverStatus, loc); } // =================================================================== // ====== Battery Logic (منطق البطارية) ====== // =================================================================== void _listenToBatteryChanges() async { _checkBatteryLevel(await _battery.batteryLevel); _batterySub = _battery.onBatteryStateChanged.listen((BatteryState state) async { _checkBatteryLevel(await _battery.batteryLevel); }); } void _checkBatteryLevel(int level) { final bool wasInPowerSaveMode = _isPowerSavingMode; if (level <= powerSaveTriggerLevel) { _isPowerSavingMode = true; } else if (level >= powerSaveExitLevel) { _isPowerSavingMode = false; } if (_isPowerSavingMode != wasInPowerSaveMode) { if (_isPowerSavingMode) { Get.snackbar( "وضع توفير الطاقة مُفعّل", "البطارية منخفضة. سنقلل تحديثات الموقع للحفاظ على طاقتك.", snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.primaryColor.withOpacity(0.9), colorText: Get.theme.colorScheme.onPrimary, duration: const Duration(seconds: 7), ); } else { Get.snackbar( "العودة للوضع الطبيعي", "تم شحن البطارية. عادت تحديثات الموقع لوضعها الطبيعي.", snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.secondary.withOpacity(0.9), colorText: Get.theme.colorScheme.onSecondary, duration: const Duration(seconds: 5), ); } _startTimers(); } } // =================================================================== // ====== API Communication & Helpers (التواصل مع السيرفر والدوال المساعدة) ====== // =================================================================== Future _sendUpdate(LatLng pos, String status, LocationData loc) async { final payload = _buildPayload(pos, status, loc); try { await CRUD().post( link: '${AppLink.locationServer}/update.php', payload: payload, ); _lastSentLoc = pos; _lastSentStatus = status; _lastSentAt = DateTime.now(); print('✅ Sent to update.php [$status]'); } catch (e) { print('❌ FAILED to send to update.php: $e'); } } Future _addSingleTrackPoint() async { if (!_isReady) return; final String driverStatus = (box.read(BoxName.statusDriverLocation) ?? 'off').toString(); if (myLocation.latitude == 0 && myLocation.longitude == 0) return; if (_lastSentLoc == null) return; // حماية إضافية // قيَم رقمية آمنة final double safeHeading = (heading is num) ? (heading as num).toDouble() : 0.0; final double safeSpeed = (speed is num) ? (speed as num).toDouble() : 0.0; final double safeDistKm = (totalDistance is num) ? (totalDistance as num).toDouble() / 1000.0 : 0.0; final String driverId = (box.read(BoxName.driverID) ?? '').toString().trim(); if (driverId.isEmpty) return; // لا ترسل بدون DriverID final String deviceTimestamp = DateTime.now().toIso8601String(); // ✅ كل شيء Strings فقط final Map payload = { 'driver_id': driverId, 'latitude': _lastSentLoc!.latitude.toStringAsFixed(6), 'longitude': _lastSentLoc!.longitude.toStringAsFixed(6), 'heading': safeHeading.toStringAsFixed(1), 'speed': (safeSpeed < 0.5 ? 0.0 : safeSpeed) .toString(), // أو toStringAsFixed(2) 'distance': safeDistKm.toStringAsFixed(2), 'status': driverStatus, 'carType': (box.read(BoxName.carType) ?? 'default').toString(), 'device_timestamp': deviceTimestamp, }; try { print('⏱️ Adding a single point to car_track... $payload'); await CRUD().post( link: '${AppLink.locationServer}/add.php', payload: payload, // ← الآن Map ); } catch (e) { print('❌ FAILED to send single track point: $e'); } } Future _sendStationaryHeartbeat() async { if (!_isReady) return; if (_lastSentLoc == null || _lastSentAt == null) return; if (DateTime.now().difference(_lastSentAt!).inSeconds < 90) return; final distSinceSent = _haversineMeters(_lastSentLoc!, myLocation); if (distSinceSent >= onMoveMetersNormal) return; print('🫀 Driver is stationary, sending heartbeat...'); final String driverStatus = (box.read(BoxName.statusDriverLocation) ?? 'off').toString(); // ✅ كل شيء Strings final Map payload = { 'driver_id': (box.read(BoxName.driverID) ?? '').toString(), 'latitude': _lastSentLoc!.latitude.toStringAsFixed(6), 'longitude': _lastSentLoc!.longitude.toStringAsFixed(6), 'heading': heading.toStringAsFixed(1), // ملاحظة: هنا السرعة تبقى بالمتر/ث بعد التحويل أدناه؛ وحّدتّها لكتابة String 'speed': ((speed < 0.5) ? 0.0 : speed).toString(), 'distance': (totalDistance / 1000).toStringAsFixed(2), 'status': driverStatus, 'carType': (box.read(BoxName.carType) ?? 'default').toString(), // 'hb': '1' }; try { await CRUD().post( link: '${AppLink.locationServer}/update.php', payload: payload, ); _lastSentAt = DateTime.now(); } catch (e) { print('❌ FAILED to send Heartbeat: $e'); } } Map _buildPayload( LatLng pos, String status, LocationData loc) { return { 'driver_id': (box.read(BoxName.driverID) ?? '').toString(), 'latitude': pos.latitude.toStringAsFixed(6), 'longitude': pos.longitude.toStringAsFixed(6), 'heading': (loc.heading ?? heading).toStringAsFixed(1), // هنا أنت بتحوّل السرعة إلى كم/س (×3.6) — ممتاز 'speed': ((loc.speed ?? speed) * 3.6).toStringAsFixed(1), 'status': status, 'distance': (totalDistance / 1000).toStringAsFixed(2), 'carType': (box.read(BoxName.carType) ?? 'default').toString(), // 👈 }; } double _haversineMeters(LatLng a, LatLng b) { const p = 0.017453292519943295; final h = 0.5 - cos((b.latitude - a.latitude) * p) / 2 + cos(a.latitude * p) * cos(b.latitude * p) * (1 - cos((b.longitude - a.longitude) * p)) / 2; return 12742 * 1000 * asin(sqrt(h)); } // **إضافة جديدة:** دوال لحفظ سلوك السائق محلياً /// يحسب التسارع بالمتر/ثانية^2 double? _calcAcceleration(double currentSpeed, DateTime now) { if (_lastSpeed != null && _lastSpeedAt != null) { final dt = now.difference(_lastSpeedAt!).inMilliseconds / 1000.0; if (dt > 0.5) { // لتجنب القيم الشاذة في الفترات الزمنية الصغيرة جداً final a = (currentSpeed - _lastSpeed!) / dt; _lastSpeed = currentSpeed; _lastSpeedAt = now; return a; } } _lastSpeed = currentSpeed; _lastSpeedAt = now; return null; } /// يحفظ سلوك السائق (الموقع، التسارع) في قاعدة بيانات SQLite المحلية Future _saveBehaviorIfMoved(LatLng pos, DateTime now, {required double currentSpeed}) async { final dist = (_lastSqlLoc == null) ? 999.0 : _haversineMeters(_lastSqlLoc!, pos); if (dist < 15.0) return; // الحفظ فقط عند التحرك لمسافة 15 متر على الأقل final accel = _calcAcceleration(currentSpeed, now) ?? 0.0; try { final now = DateTime.now(); final double lat = double.parse(pos.latitude.toStringAsFixed(6)); // دقة 6 أرقام final double lon = double.parse(pos.longitude.toStringAsFixed(6)); // دقة 6 أرقام final double acc = double.parse( (accel is num ? accel as num : 0).toStringAsFixed(2)); // دقة منزلتين await sql.insertData({ 'driver_id': (box.read(BoxName.driverID) ?? '').toString(), // TEXT 'latitude': lat, // REAL 'longitude': lon, // REAL 'acceleration': acc, // REAL 'created_at': now.toIso8601String(), // TEXT 'updated_at': now.toIso8601String(), // TEXT }, TableName.behavior); _lastSqlLoc = pos; } catch (e) { print('❌ FAILED to insert to SQLite (behavior): $e'); } } } ================================================== FILE PATH: ./lib/controller/functions/location_background_controller.dart ================================================== // import 'dart:async'; // import 'package:background_location/background_location.dart'; // import 'package:get/get.dart'; // import 'package:permission_handler/permission_handler.dart'; // class LocationBackgroundController extends GetxController { // @override // void onInit() { // super.onInit(); // requestLocationPermission(); // configureBackgroundLocation(); // } // Future requestLocationPermission() async { // var status = await Permission.locationAlways.status; // if (!status.isGranted) { // await Permission.locationAlways.request(); // } // } // Future configureBackgroundLocation() async { // await BackgroundLocation.setAndroidNotification( // title: 'Location Tracking Active'.tr, // message: 'Your location is being tracked in the background.'.tr, // icon: '@mipmap/launcher_icon', // ); // BackgroundLocation.setAndroidConfiguration(3000); // BackgroundLocation.startLocationService(); // BackgroundLocation.getLocationUpdates((location) { // // Handle location updates here // }); // } // startBackLocation() async { // Timer.periodic(const Duration(seconds: 3), (timer) { // getBackgroundLocation(); // }); // } // getBackgroundLocation() async { // var status = await Permission.locationAlways.status; // if (status.isGranted) { // await BackgroundLocation.startLocationService( // distanceFilter: 20, forceAndroidLocationManager: true); // BackgroundLocation.setAndroidConfiguration( // Duration.microsecondsPerSecond); // Set interval to 5 seconds // BackgroundLocation.getLocationUpdates((location1) {}); // } else { // await Permission.locationAlways.request(); // } // } // } ================================================== FILE PATH: ./lib/controller/functions/gemeni.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:convert'; import 'package:crypto/crypto.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/info.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/controller/firebase/firbase_messge.dart'; import 'package:sefer_driver/controller/firebase/local_notification.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/env/env.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:http/http.dart' as http; import 'package:image/image.dart' as img; import 'package:path_provider/path_provider.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/api_key.dart'; import '../../constant/char_map.dart'; import '../../constant/colors.dart'; import '../../print.dart'; import '../firebase/notification_service.dart'; import 'encrypt_decrypt.dart'; import 'tts.dart'; import 'upload_image.dart'; enum LicenseSide { front, back, unknown, } enum DocumentType { carLicenseFront, carLicenseBack, idCardFront, nonIdCardFront, nonIdCardBack, idCardBack, driverLicense, unknown, } class AI extends GetxController { bool approved = false; bool isDriverSaved = false; bool isCarSaved = false; bool isInviteDriverFound = false; final invitationCodeController = TextEditingController(); final formKey = GlobalKey(); bool isTimerComplete = false; double progressValue = 1.0; int remainingSeconds = 30; void startTimer() { Timer.periodic(const Duration(seconds: 1), (timer) { if (remainingSeconds == 0) { timer.cancel(); isTimerComplete = true; update(); // Notify the UI } else { remainingSeconds--; progressValue = remainingSeconds / 30.0; // Update progress update(); // Notify the UI } }); } void resetTimer() { isTimerComplete = false; progressValue = 1.0; remainingSeconds = 40; update(); // Notify the UI startTimer(); // Restart the timer } void setApproved() { approved = true; update(); } Future updateInvitationCodeFromRegister() async { var res = await CRUD().post( link: AppLink.updateDriverInvitationDirectly, payload: { "inviterDriverPhone": box.read(BoxName.phoneDriver).toString(), "driverId": box.read(BoxName.driverID).toString(), }, ); if (res != 'failure') { isInviteDriverFound = true; update(); // mySnackbarSuccess("Code approved".tr); // Localized success message box.write(BoxName.isInstall, '1'); NotificationController().showNotification( "Code approved".tr, "Code approved".tr, 'tone2', ''); // Notification text with dynamic token // Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP( // 'You have received a gift token!'.tr, // 'for '.tr + box.read(BoxName.phoneDriver).toString(), // jsonDecode(res)['message'][0]['token'].toString(), // [], // 'tone2', // Type of notification // ); NotificationService.sendNotification( target: (res)['message'][0]['token'].toString(), title: 'You have received a gift token!'.tr, body: 'for '.tr + box.read(BoxName.phoneDriver).toString(), isTopic: false, // Important: this is a token tone: 'tone2', driverList: [], category: 'You have received a gift token!', ); } else { // mySnackeBarError( // "You dont have invitation code".tr); // Localized error message } } Future updatePassengersInvitation() async { if (formKey.currentState!.validate()) { var res = await CRUD().post( link: AppLink.updatePassengersInvitation, payload: {"inviteCode": invitationCodeController.text}); if (res != 'failure') { isInviteDriverFound = true; update(); mySnackbarSuccess("Code approved".tr); } else { mySnackeBarError("Code not approved".tr); } } } final today = DateTime.now(); Future addDriverAndCarEgypt() async { final today = DateTime.now(); // رخصة القيادة final drvExpiry = DateTime.tryParse(licenceBackSy['expiry_date'] ?? ''); final drvExpired = drvExpiry != null && drvExpiry.isBefore(today); // فحص السيارة + الضرائب final inspDate = DateTime.tryParse(vehicleFrontSy['inspection_date'] ?? ''); final taxExpiry = DateTime.tryParse(vehicleBackSy['tax_expiry'] ?? ''); final inspExpired = inspDate != null && inspDate.isBefore(today); final taxExpired = taxExpiry != null && taxExpiry.isBefore(today); // تطابق تاريخَي ميلاد الهوية غير المصرية final birthFront = DateTime.tryParse(responseNonIdCardFront['birthdate'] ?? ''); final birthBack = DateTime.tryParse(responseNonIdCardBack['birthDate'] ?? ''); final birthMismatch = (birthFront != null && birthBack != null && birthFront != birthBack); /* ـــــــ ❷ تحذيرات المستخدم ـــــــ */ if (!isEgypt && birthMismatch) { await _showWarnDialog( title: 'Birthdate Mismatch'.tr, text: 'Birthdate on ID front and back does not match.'.tr, ); return; } if (drvExpired) { await _showWarnDialog( title: 'Expired Driver’s License'.tr, text: 'Your driver’s license has expired. Please renew it.'.tr, ); return; } else { await addDriverEgypt(); await addRegistrationCarEgypt(); if (isCarSaved && isDriverSaved) { // DeviceController().getDeviceSerialNumber(); box.write(BoxName.phoneVerified, true); Get.find().loginWithGoogleCredential( box.read(BoxName.driverID).toString(), box.read(BoxName.emailDriver).toString(), ); } } } String extractDOB(String nationalNumber) { if (nationalNumber.length != 14) { throw ArgumentError('National number must be 14 digits long.'); } // Extract the first digit to determine the century String firstDigit = nationalNumber[0]; // Extract year, month, and day parts String yearPart = nationalNumber.substring(1, 3); String monthPart = nationalNumber.substring(3, 5); String dayPart = nationalNumber.substring(5, 7); // Determine the year based on the first digit int yearPrefix; if (firstDigit == '2') { yearPrefix = 1900; } else if (firstDigit == '3') { yearPrefix = 2000; } else { throw ArgumentError('Invalid first digit in national number.'); } // Construct the full year int year = yearPrefix + int.parse(yearPart); // Format the date as YYYY-MM-DD String dob = '$year-${monthPart.padLeft(2, '0')}-${dayPart.padLeft(2, '0')}'; return dob; } Future _showWarnDialog( {required String title, required String text}) async { await Get.defaultDialog( title: title, content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.warning, size: 48, color: Colors.red), const SizedBox(height: 16), Text(text, textAlign: TextAlign.center, style: AppStyle.title), const SizedBox(height: 16), IconButton( icon: const Icon(Icons.volume_up), onPressed: () async => await Get.find().speakText(text), ) ], ), actions: [ TextButton(onPressed: Get.back, child: const Text('OK')), ], ); } String shortHash(String password) { var bytes = utf8.encode(password); var digest = sha256.convert(bytes); return base64UrlEncode(digest.bytes); } Future addDriverEgypt() async { isLoading = true; update(); final loginDriverController = Get.put(LoginDriverController()); var pass = loginDriverController.passwordController.text.isEmpty ? '${box.read(BoxName.emailDriver)}${box.read(BoxName.driverID)}' : '${loginDriverController.emailController.text.toString()}${box.read(BoxName.driverID)}'; String hashedPassword = shortHash(pass); var payload = { 'first_name': (idFrontSy['full_name'].toString().split(' ')[0]) ?? 'Not specified', 'last_name': (idFrontSy['full_name'].toString().split(' ')[1]) ?? 'Not specified', 'email': 'Not specified', 'phone': box.read(BoxName.phoneDriver)?.toString(), 'id': box.read(BoxName.driverID)?.toString(), 'password': hashedPassword.toString(), 'gender': (idBackSy['gender'].toString()) ?? 'Not specified', 'license_type': (licenceBackSy['license_number'].toString()) ?? 'Not specified', 'national_number': (licenceFrontSy['national_number'].toString()) ?? 'Not specified', 'name_arabic': (licenceFrontSy['name_arabic'].toString()), 'issue_date': licenceBackSy['issue_date']?.toString() ?? 'Not specified', 'expiry_date': licenceBackSy['expiry_date']?.toString() ?? 'Not specified', 'license_categories': licenceBackSy['license_categories'] ?? 'Not specified', 'address': (idBackSy['address'].toString()) ?? 'Not specified', 'licenseIssueDate': licenceBackSy['issue_date'].toString() ?? 'Not specified', 'status': 'yet', 'birthdate': idFrontSy['dob'].toString(), 'maritalStatus': 'Not specified', 'site': (idBackSy['address'].toString()) ?? 'Not specified', 'employmentType': 'Not specified', }; try { var res = await CRUD().post(link: AppLink.signUpCaptin, payload: payload); // Check if response is valid JSON isLoading = false; update(); if (res['status'] == 'success') { isDriverSaved = true; box.write(BoxName.emailDriver, '${box.read(BoxName.phoneDriver)}${Env.email}'); mySnackbarSuccess('Driver data saved successfully'); } else { mySnackeBarError('${'Failed to save driver data'.tr}: }'); } } catch (e) { isLoading = false; update(); mySnackeBarError( 'An error occurred while saving driver data'.tr, ); } } addCriminalDocuments() async { var res = await CRUD().post(link: AppLink.addCriminalDocuments, payload: { "driverId": box.read(BoxName.driverID), "IssueDate": responseCriminalRecordEgypt['IssueDate'], "InspectionResult": (responseCriminalRecordEgypt['InspectionResult']), }); if (res != 'failure') { mySnackbarSuccess('uploaded sucssefuly'.tr); } } Future addRegistrationCarEgypt() async { try { isLoading = true; update(); var payload = { 'driverID': box.read(BoxName.driverID), 'vin': vehicleBackSy['chassis'].toString(), 'car_plate': (vehicleFrontSy['car_plate'].toString()), 'make': (vehicleBackSy['make'].toString()), 'model': (vehicleBackSy['model']), 'year': vehicleBackSy['year'].toString(), 'expiration_date': vehicleFrontSy['inspection_date'].toString(), 'color': vehicleFrontSy['color'], 'owner': (vehicleFrontSy['owner']), 'color_hex': vehicleFrontSy['colorHex'].toString(), 'fuel': vehicleBackSy['fuel'].toString(), }; var res = await CRUD().post(link: AppLink.addRegisrationCar, payload: payload); isLoading = false; update(); var status = (res); if (status['status'] == 'success') { isCarSaved = true; mySnackbarSuccess(''); } } catch (e) {} } final picker = ImagePicker(); Map responseMap = {}; Map responseCarLicenseMapJordan = {}; Map responseBackCarLicenseMap = {}; Map responseIdCardMap = {}; Map responseIdCardDriverEgyptBack = {}; Map responseForComplaint = {}; Map responseIdCardDriverEgyptFront = {}; Map responseIdEgyptFront = {}; Map responseNonIdCardFront = {}; Map responseNonIdCardBack = {}; Map responseCriminalRecordEgypt = {}; Map responseIdEgyptBack = {}; Map responseIdEgyptDriverLicense = {}; String? responseIdCardDriverEgypt1; bool isloading = false; bool isLoading = false; bool isEgypt = true; var image; CroppedFile? croppedFile; DateTime now = DateTime.now(); changeNationality() { isEgypt = !isEgypt; update(); } Future pickImage() async { final pickedImage = await picker.pickImage(source: ImageSource.gallery); if (pickedImage != null) { image = File(pickedImage.path); // Crop the image croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false), IOSUiSettings( title: 'Cropper'.tr, ), ], ); // image = croppedFile; // Resize the image final rawImage = img.decodeImage(File(croppedFile!.path).readAsBytesSync()); final resizedImage = img.copyResize(rawImage!, width: 800); // Adjust the width as needed final appDir = await getTemporaryDirectory(); final resizedImagePath = '${appDir.path}/resized_image.jpg'; final resizedImageFile = File(resizedImagePath); resizedImageFile.writeAsBytesSync( img.encodeJpg(resizedImage)); // Save the resized image as JPEG image = resizedImageFile; update(); } } DocumentType checkDocumentType(String text) { // Convert text to lowercase and remove all spaces and new lines text = text.toLowerCase().replaceAll(RegExp(r'\s+'), ''); // Keywords for each document type final Map> keywords = { DocumentType.carLicenseBack: ['شاسيه', 'موتور', 'سم٣'], DocumentType.carLicenseFront: ['وزارةالداخلية', 'رخصةتسيير'], DocumentType.idCardFront: [ 'بطاقةتحقيقالشخصية', 'بطاقة تحقيق الشخصية', 'تحقيق' ], DocumentType.idCardBack: ['البطاقةساريةحتى'], DocumentType.driverLicense: ['قيادةخاصة', 'خاصه', 'قيادة'], DocumentType.nonIdCardFront: ['Foreign Residence Card', 'أجنبي', 'جواز'], DocumentType.nonIdCardBack: [ 'نوع الإقامة', 'الإقامة', 'Cardexpiresbyendofresidencepermit' ], }; // Check each document type for (var entry in keywords.entries) { if (entry.value.any((keyword) => text.contains(keyword))) { return entry.key; } } // If no match is found return DocumentType.unknown; } // تحفّظ كل استجابة على حدة Map idFrontSy = {}; Map idBackSy = {}; Map licenceFrontSy = {}; Map licenceBackSy = {}; Map vehicleFrontSy = {}; Map vehicleBackSy = {}; bool isLoadingidFrontSy = false; bool isLoadingidBackSy = false; bool isLoadingLicenceFrontSy = false; bool isLoadingLicenceBackSy = false; bool isLoadingVehicleFrontSy = false; bool isLoadingVehicleBackSy = false; Future sendToAI(String type, {required File imageFile}) async { final headers = { 'Authorization': 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', }; final driverID = box.read(BoxName.driverID) ?? 'eddfdfdgfd'; if (driverID == null) { MyDialog() .getDialog("Error".tr, "User not logged in".tr, () => Get.back()); return; } try { isloading = true; update(); final uri = Uri.parse(AppLink.uploadImageToAi); // سكربتك الجديد final request = http.MultipartRequest("POST", uri); request.headers.addAll(headers); request.files .add(await http.MultipartFile.fromPath("image", imageFile.path)); request.fields['driver_id'] = driverID; request.fields['type'] = type; final response = await request.send(); final result = await http.Response.fromStream(response); if (result.statusCode == 200) { final responseData = jsonDecode(result.body); if (responseData['message'] != null && responseData['message']['data'] != null) { // final imageUrl = responseData['message']['image_url']; final data = responseData['message']['data']; switch (type) { case 'id_front_sy': idFrontSy = data; isLoadingidFrontSy = false; update(); break; case 'id_back_sy': idBackSy = data; isLoadingidBackSy = false; update(); break; case 'driving_license_sy_front': licenceFrontSy = data; isLoadingLicenceFrontSy = false; update(); break; case 'driving_license_sy_back': licenceBackSy = data; isLoadingLicenceBackSy = false; update(); break; case 'vehicle_license_sy_front': vehicleFrontSy = data; isLoadingVehicleFrontSy = false; update(); break; case 'vehicle_license_sy_back': vehicleBackSy = data; isLoadingVehicleBackSy = false; update(); break; } isloading = false; update(); } else { MyDialog().getDialog( "Error".tr, "AI failed to extract info".tr, () => Get.back()); } } else { MyDialog() .getDialog("Error".tr, "Upload or AI failed".tr, () => Get.back()); } } catch (e) { isloading = false; update(); MyDialog().getDialog("Error".tr, e.toString(), () => Get.back()); } } Future pickAndSendImage(String type) async { final picker = ImagePicker(); final pickedImage = await picker.pickImage(source: ImageSource.camera); if (pickedImage != null) { image = File(pickedImage.path); // Crop the image croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.accentColor, toolbarWidgetColor: AppColor.redColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false), IOSUiSettings( title: 'Cropper'.tr, ), ], ); // image = croppedFile; // Resize the image final rawImage = img.decodeImage(File(croppedFile!.path).readAsBytesSync()); final resizedImage = img.copyResize(rawImage!, width: 800); // Adjust the width as needed final appDir = await getTemporaryDirectory(); final resizedImagePath = '${appDir.path}/resized_image.jpg'; final resizedImageFile = File(resizedImagePath); resizedImageFile.writeAsBytesSync( img.encodeJpg(resizedImage)); // Save the resized image as JPEG image = resizedImageFile; update(); await sendToAI(type, imageFile: File(image.path)); } } Future allMethodForAI( String prompt, String linkPHP, String imagePath) async { isLoading = true; update(); try { await ImageController().choosImage(linkPHP, imagePath); // if (imagePath == 'driver_license') { // await ImageController().choosFaceFromDriverLicense(linkPHP, 'face'); // } await Future.delayed(const Duration(seconds: 2)); var extractedString = await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath); var json = jsonDecode(extractedString); var textValues = CRUD().extractTextFromLines(json); DocumentType detectedType = checkDocumentType(textValues); String expectedDocument = getExpectedDocument(imagePath); String detectedDocument = getDetectedDocument(detectedType); bool isCorrectDocument = (detectedType == getExpectedType(imagePath)); if (!isCorrectDocument) { MyDialog().getDialog('incorrect_document_title'.tr, '${'expected'.tr}: $expectedDocument\n${'detected'.tr}: $detectedDocument', () { Get.back(); }); } else { // Process the correct document await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); } } catch (e) { MyDialog().getDialog('error'.tr, 'error_processing_document'.tr, () { Get.back(); }); } finally { isLoading = false; update(); } } Future allMethodForAINewCar( String prompt, String linkPHP, String imagePath, String carID) async { isLoading = true; update(); try { await ImageController().choosImageNewCAr(linkPHP, imagePath); // if (imagePath == 'driver_license') { // await ImageController().choosFaceFromDriverLicense(linkPHP, 'face'); // } await Future.delayed(const Duration(seconds: 2)); var extractedString = await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath); var json = jsonDecode(extractedString); var textValues = CRUD().extractTextFromLines(json); DocumentType detectedType = checkDocumentType(textValues); String expectedDocument = getExpectedDocument(imagePath); String detectedDocument = getDetectedDocument(detectedType); bool isCorrectDocument = (detectedType == getExpectedType(imagePath)); if (!isCorrectDocument) { MyDialog().getDialog('incorrect_document_title'.tr, '${'expected'.tr}: $expectedDocument\n${'detected'.tr}: $detectedDocument', () { Get.back(); }); } else { // Process the correct document await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); } } catch (e) { MyDialog().getDialog('error'.tr, 'error_processing_document'.tr, () { Get.back(); }); } finally { isLoading = false; update(); } } String getExpectedDocument(String imagePath) { switch (imagePath) { case 'car_front': return 'car_license_front'.tr; case 'car_back': return 'car_license_back'.tr; case 'id_back': return 'id_card_back'.tr; case 'id_front': return 'id_card_front'.tr; case 'driver_license': return 'driver_license'.tr; default: return 'unknown_document'.tr; } } DocumentType getExpectedType(String imagePath) { switch (imagePath) { case 'car_front': return DocumentType.carLicenseFront; case 'car_back': return DocumentType.carLicenseBack; case 'id_back': return DocumentType.idCardBack; case 'id_front': return DocumentType.idCardFront; case 'driver_license': return DocumentType.driverLicense; default: return DocumentType.unknown; } } String getDetectedDocument(DocumentType type) { switch (type) { case DocumentType.carLicenseFront: return 'car_license_front'.tr; case DocumentType.carLicenseBack: return 'car_license_back'.tr; case DocumentType.idCardFront: return 'id_card_front'.tr; case DocumentType.idCardBack: return 'id_card_back'.tr; case DocumentType.nonIdCardFront: return 'non_id_card_front'.tr; case DocumentType.nonIdCardBack: return 'non_id_card_back'.tr; case DocumentType.driverLicense: return 'driver_license'.tr; default: return 'unknown_document'.tr; } } Future generateContent() async { await pickImage(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': 'write json for all data as first name ,last name,dob,licenseID,expiration date,issued date asdress class type ,output json type', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); } else {} // Rest of your code... } else {} } else {} } Future getComplaintDataToAI() async { var res = await CRUD().get( link: AppLink.getComplaintAllDataForDriver, payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); if (res != 'failure') { var d = jsonDecode(res)['message']; return d; } else { return [ {'data': 'no data'} ]; } } Future anthropicAIForComplaint() async { var dataComplaint = await getComplaintDataToAI(); var messagesData = [ { "role": "user", "content": [ { "type": "text", "text": "$dataComplaint ${AppInformation.complaintPrompt} " } ] } ]; var requestBody = jsonEncode({ "model": "claude-3-haiku-20240307", "max_tokens": 1024, "temperature": 0, "system": "Json output only without any additional ", "messages": messagesData, }); final response = await http.post( Uri.parse('https://api.anthropic.com/v1/messages'), headers: { 'x-api-key': AK.anthropicAIkeySeferNew, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' }, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(utf8.decode(response.bodyBytes)); // Process the responseData as needed responseForComplaint = jsonDecode(responseData['content'][0]['text']); } } Future anthropicAI( String payload, String prompt, String idType) async { var messagesData = [ { "role": "user", "content": [ {"type": "text", "text": "$payload $prompt"} ] } ]; var k = X.r(X.r(X.r(await getAIKey('CLAUDAISEFER'), cn), cC), cs); var requestBody = jsonEncode({ "model": "claude-3-haiku-20240307", "max_tokens": 1024, "temperature": 0, "system": "Json output only without any additional ", "messages": messagesData, }); final response = await http.post( Uri.parse('https://api.anthropic.com/v1/messages'), headers: { 'x-api-key': k, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' }, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(utf8.decode(response.bodyBytes)); // Process the responseData as needed if (idType == 'car_back') { responseIdCardDriverEgyptBack = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'car_front') { responseIdCardDriverEgyptFront = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'id_front') { responseIdEgyptFront = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'id_back') { responseIdEgyptBack = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'driver_license') { responseIdEgyptDriverLicense = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'criminalRecord') { responseCriminalRecordEgypt = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'non_id_front') { responseNonIdCardFront = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'non_id_back') { responseNonIdCardBack = jsonDecode(responseData['content'][0]['text']); } update(); return responseData.toString(); } return responseIdCardDriverEgyptBack.toString(); } Future geminiAiExtraction(String prompt, payload, String idType) async { var requestBody = jsonEncode({ "contents": [ { "parts": [ {"text": "$payload $prompt"} ] } ], "generationConfig": { "temperature": 1, "topK": 64, "topP": 0.95, "maxOutputTokens": 8192, "stopSequences": [] }, "safetySettings": [ { "category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }, { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" } ] }); final response = await http.post( Uri.parse( // 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), // 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=${AK.geminiApi}'), 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); if (idType == 'car_back') { responseIdCardDriverEgyptBack = jsonDecode(jsonString); } else if (idType == 'car_front') { responseIdCardDriverEgyptFront = jsonDecode(jsonString); } else if (idType == 'id_front') { responseIdEgyptFront = jsonDecode(jsonString); } else if (idType == 'id_back') { responseIdEgyptBack = jsonDecode(jsonString); } else if (idType == 'driver_license') { responseIdEgyptDriverLicense = jsonDecode(jsonString); } else if (idType == 'non_id_front') { responseNonIdCardFront = jsonDecode(responseData['content'][0]['text']); } else if (idType == 'non_id_back') { responseNonIdCardBack = jsonDecode(responseData['content'][0]['text']); } update(); } else { mySnackeBarError("JSON string not found"); } // Rest of your code... } else {} } Future getDriverLicenseJordanContent() async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': 'write json for all data as first name ,last name,dob,id ,expiration date,issued date asdress class type,age in years ,output json type in arabic value and stay engish key and make date format like YYYY-MM-DD , for name please extract name in arabic in Name in json plus first_name ', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseMap = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future getCarLicenseJordanContent() async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': '''Extract the following information from the front face of the Jordanian ID card: Name National ID number Gender Date of birth Output the extracted information in the following JSON format''', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( // 'https://${API_ENDPOINT}/v1/projects/${PROJECT_ID}/locations/${LOCATION_ID}/publishers/google/models/${MODEL_ID}:streamGenerateContent'), 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseCarLicenseMapJordan = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future jordanID() async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': '''Extract the following information from the front face of the Jordanian ID card: Name National ID number Gender Date of birth Output the extracted information in the following JSON format''', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseCarLicenseMapJordan = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future carLicenseJordan() async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': '''Extract the following information from the front face of the car license card in Jordan: * name * Address * Vehicle type * car_kind * car_color * Vehicle category * car_year * car_plate * Registration type * Usage type * expire_date_of_license Output the extracted information in the following JSON formate and make date format like YYYY-MM-DD''', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-vision-latest:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseCarLicenseMapJordan = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future getTextFromCard(String prompt) async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': prompt, }, ], }, ], 'generationConfig': { "temperature": 1, "topK": 32, "topP": 0.1, "maxOutputTokens": 4096, "stopSequences": [] }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-vision-latest:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseBackCarLicenseMap = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future generateBackCarLicenseJordanContent() async { await pickImage(); isloading = true; update(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': 'write json output from extracting car license back face for these key ,vin,fuelType,passengerType,curbWeight,insuranceCompany,policyNumber,notes,insuranceType and output it json .dont add data else this image', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 343, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); isloading = false; update(); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseBackCarLicenseMap = jsonDecode(jsonString); } else {} // Rest of your code... } else {} } else {} } Future getFromCarRegistration() async { await pickImage(); if (image != null) { final imageBytes = await image.readAsBytes(); final imageData = base64Encode(imageBytes); var requestBody = jsonEncode({ 'contents': [ { 'parts': [ { 'inlineData': { 'mimeType': 'image/jpeg', 'data': imageData, }, }, { 'text': 'write output json from image for[ vin, make, model, year, expiration_date, color, owner, registration_date ],output json type ', }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safetySettings': [ { 'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, { 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', }, ], }); final response = await http.post( Uri.parse( 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); } else {} // Rest of your code... } else {} } else {} } List prompts = []; getPrompt() async { var res = await CRUD() .get(link: AppLink.getPromptDriverDocumentsEgypt, payload: {}); if (res != 'failure') { var d = jsonDecode(res)['message']; prompts = d; } else {} } getAIKey(String key) async { var res = await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key}); if (res != 'failure') { var d = jsonDecode(res)['message']; return d[key].toString(); } else {} } @override void onInit() { getPrompt(); super.onInit(); } } ================================================== FILE PATH: ./lib/controller/functions/face_detect.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:http/http.dart' as http; import 'package:http/io_client.dart'; import '../../constant/links.dart'; import 'encrypt_decrypt.dart'; import 'upload_image.dart'; Future faceDetector() async { await ImageController().choosFace(AppLink.uploadEgypt, 'face_detect'); await Future.delayed(const Duration(seconds: 2)); var headers = { // 'Authorization': 'Basic ${AK.basicCompareFaces}', 'Authorization': 'Basic hamza:12345678', 'Content-Type': 'application/json' }; // var request = http.Request('POST', Uri.parse(//Todo // 'https://face-detect-f6924392c4c7.herokuapp.com/compare_faces')); var request = http.Request( 'POST', Uri.parse('https://mohkh.online:5000/compare_faces')); request.body = json.encode({ "url1": "${AppLink.seferCairoServer}/card_image/id_front-${(box.read(BoxName.driverID))}.jpg", "url2": "https://api.sefer.live/sefer/card_image/face_detect-${(box.read(BoxName.driverID))}.jpg" }); print('request.body: ${request.body}'); request.headers.addAll(headers); try { http.Client client = await createHttpClient(); http.StreamedResponse response = await client.send(request); // http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { String result = await response.stream.bytesToString(); print('result: ${result}'); return result; } else { print('Error: ${response.reasonPhrase}'); return 'Error: ${response.reasonPhrase}'; } } catch (e) { print('Exception occurred: $e'); return 'Error: $e'; } } Future createHttpClient() async { final SecurityContext securityContext = SecurityContext(); HttpClient httpClient = HttpClient(context: securityContext); httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) => true; // Bypass SSL return IOClient(httpClient); } Future faceDetector2(String url1, String url2) async { var headers = { 'Authorization': 'Basic hamza:12345678', 'Content-Type': 'application/json' }; var request = http.Request( 'POST', Uri.parse('https://mohkh.online:5000/compare_faces')); request.body = json.encode({"url1": url1, "url2": url2}); request.headers.addAll(headers); try { http.Client client = await createHttpClient(); // Use custom client DateTime startTime = DateTime.now(); http.StreamedResponse response = await client.send(request); DateTime endTime = DateTime.now(); Duration duration = endTime.difference(startTime); if (response.statusCode == 200) { print(await response.stream.bytesToString()); print(duration.inSeconds); return await response.stream.bytesToString(); } else { print(await response.stream.bytesToString()); return 'Error: ${response.reasonPhrase}'; } } catch (e) { return 'Exception: $e'; } } ================================================== FILE PATH: ./lib/controller/functions/scan_id_card.dart ================================================== // import 'package:credit_card_scanner/credit_card_scanner.dart'; // import 'package:get/get.dart'; // // class ScanIdCard extends GetxController { // CardDetails? _cardDetails; // CardScanOptions scanOptions = const CardScanOptions( // scanCardHolderName: true, // enableDebugLogs: true, // validCardsToScanBeforeFinishingScan: 5, // possibleCardHolderNamePositions: [ // CardHolderNameScanPosition.aboveCardNumber, // ], // ); // // Future scanCard() async { // final CardDetails? cardDetails = // await CardScanner.scanCard(scanOptions: scanOptions); // if (cardDetails == null) { // return; // } // // _cardDetails = cardDetails; // update(); // } // } ================================================== FILE PATH: ./lib/controller/functions/sms_egypt_controller.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/info.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/auth/captin/register_captin_controller.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import '../auth/captin/login_captin_controller.dart'; import 'encrypt_decrypt.dart'; class SmsEgyptController extends GetxController { var headers = {'Content-Type': 'application/json'}; Future getSender() async { var res = await CRUD().get(link: AppLink.getSender, payload: {}); if (res != 'failure') { var d = jsonDecode(res)['message'][0]['senderId'].toString(); return d; } else { return "Sefer Egy"; } } Future sendSmsEgypt(String phone) async { String sender = await getSender(); var body = jsonEncode({"receiver": "2$phone"}); var res = await http.post( Uri.parse(AppLink.sendSms), body: body, headers: headers, ); if (jsonDecode(res.body)['message'].toString() != "Success") { await CRUD().post(link: AppLink.updatePhoneInvalidSMS, payload: { "phone_number": ('+2${Get.find().phoneController.text}') }); box.write(BoxName.phoneDriver, ('+2${Get.find().phoneController.text}')); box.write(BoxName.phoneVerified, '1'); await Get.put(LoginDriverController()).loginWithGoogleCredential( box.read(BoxName.driverID).toString(), (box.read(BoxName.emailDriver).toString()), ); } else { Get.defaultDialog( title: 'You will receive code in sms message'.tr, middleText: '', confirm: MyElevatedButton( title: 'OK'.tr, onPressed: () { Get.back(); })); } } Future checkCredit(String phone, otp) async { var res = await http.post( Uri.parse(AppLink.checkCredit), body: { "username": AppInformation.appName, "password": AK.smsPasswordEgypt, }, headers: headers, ); } Future sendSmsWithValidaty(String phone, otp) async { var res = await http.post( Uri.parse(AppLink.checkCredit), body: { "username": 'Sefer', "password": AK.smsPasswordEgypt, "message": "This is an example SMS message.", "language": box.read(BoxName.lang) == 'en' ? "e" : 'r', "sender": "Sefer", //"Kazumi", // todo add sefer sender name "receiver": "2$phone", "validity": "10", "StartTime": DateTime.now().toString() // "1/1/2024 10:00:00" }, headers: headers, ); } Future sendSmsStatus(String smsid) async { var res = await http.post( Uri.parse(AppLink.checkCredit), body: { "username": AppInformation.appName, "password": AK.smsPasswordEgypt, "smsid": smsid //"00b77dfc-5b8f-474d-9def-9f0158b70f98" }, headers: headers, ); } } ================================================== FILE PATH: ./lib/controller/functions/device_analyzer.dart ================================================== import 'dart:async'; import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'performance_test.dart'; // Make sure this path is correct /// Analyzes various device hardware and software aspects to generate a compatibility score. /// This class provides a standardized output for the UI to consume easily. class DeviceAnalyzer { final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin(); /// Reads the total RAM from the system's meminfo file. /// Returns the value in Megabytes (MB). Future _readTotalRamMB() async { try { final file = File('/proc/meminfo'); if (!await file.exists()) return 0.0; final lines = await file.readAsLines(); for (var line in lines) { if (line.startsWith('MemTotal')) { // Extracts the numeric value from the line. final kb = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? '0') ?? 0; return kb / 1024.0; // Convert from Kilobytes to Megabytes } } } catch (e) { print('❌ Error reading total RAM: $e'); } return 0.0; } /// Reads the current RAM usage percentage from the system's meminfo file. Future _readUsedRamPercent() async { try { final file = File('/proc/meminfo'); if (!await file.exists()) return 0.0; final lines = await file.readAsLines(); int? total, available; for (var line in lines) { if (line.startsWith('MemTotal')) { total = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? ''); } else if (line.startsWith('MemAvailable')) { available = int.tryParse(RegExp(r'\d+').stringMatch(line) ?? ''); } } if (total != null && available != null && total > 0) { final used = total - available; return (used / total) * 100.0; } } catch (e) { print('❌ Error reading used RAM: $e'); } return 0.0; } /// The main analysis function that runs all checks. Future> analyzeDevice() async { List> details = []; if (!Platform.isAndroid) { return { 'score': 0, 'details': [ { 'label': 'النظام غير مدعوم', 'status': false, 'achieved_score': 0, 'max_score': 100 } ] }; } final info = await _deviceInfo.androidInfo; final data = info.data; final features = List.from(data['systemFeatures'] ?? []); // 1. Android Version (Max: 10 points) final version = int.tryParse(info.version.release?.split('.').first ?? '0') ?? 0; final int androidScore = version >= 9 ? 10 : 0; details.add({ 'label': 'إصدار أندرويد ${info.version.release}', 'status': androidScore > 0, 'achieved_score': androidScore, 'max_score': 10, }); // 2. Total RAM (Max: 10 points) final totalRam = await _readTotalRamMB(); int ramScore; if (totalRam >= 8000) { ramScore = 10; } else if (totalRam >= 4000) { ramScore = 5; } else if (totalRam >= 3000) { ramScore = 3; } else { ramScore = 0; } details.add({ 'label': 'إجمالي الرام ${totalRam.toStringAsFixed(0)} ميجابايت', 'status': ramScore >= 5, 'achieved_score': ramScore, 'max_score': 10, }); // 3. CPU Cores (Max: 10 points) final cores = Platform.numberOfProcessors; int coreScore = cores >= 6 ? 10 : (cores >= 4 ? 5 : 0); details.add({ 'label': 'أنوية المعالج ($cores)', 'status': coreScore >= 5, 'achieved_score': coreScore, 'max_score': 10, }); // 4. Free Storage (Max: 5 points) final freeBytes = data['freeDiskSize'] ?? 0; final freeGB = freeBytes / (1024 * 1024 * 1024); int storeScore = freeGB >= 5 ? 5 : (freeGB >= 2 ? 3 : 0); details.add({ 'label': 'المساحة الحرة ${freeGB.toStringAsFixed(1)} جيجابايت', 'status': storeScore >= 3, 'achieved_score': storeScore, 'max_score': 5, }); // 5. GPS + Gyroscope Sensors (Max: 10 points) bool okSensors = features.contains('android.hardware.location.gps') && features.contains('android.hardware.sensor.gyroscope'); final int sensorScore = okSensors ? 10 : 0; details.add({ 'label': 'حساسات GPS و Gyroscope', 'status': okSensors, 'achieved_score': sensorScore, 'max_score': 10, }); // 6. Storage Write Speed (Max: 20 points) final writeSpeed = await PerformanceTester.testStorageWriteSpeed(); int writeScore; if (writeSpeed >= 30) { writeScore = 20; } else if (writeSpeed >= 15) { writeScore = 15; } else if (writeSpeed >= 5) { writeScore = 10; } else { writeScore = 5; } details.add({ 'label': 'سرعة الكتابة (${writeSpeed.toStringAsFixed(1)} MB/s)', 'status': writeScore >= 10, 'achieved_score': writeScore, 'max_score': 20, }); // 7. CPU Compute Speed (Max: 20 points) final cpuTime = await PerformanceTester.testCPUSpeed(); int cpuScore; if (cpuTime <= 1.0) { cpuScore = 20; } else if (cpuTime <= 2.5) { cpuScore = 15; } else if (cpuTime <= 4.0) { cpuScore = 10; } else { cpuScore = 5; } details.add({ 'label': 'سرعة المعالجة (${cpuTime.toStringAsFixed(2)} ثانية)', 'status': cpuScore >= 10, 'achieved_score': cpuScore, 'max_score': 20, }); // 8. Memory Pressure (Max: 15 points) final usedPercent = await _readUsedRamPercent(); int memScore; if (usedPercent <= 60) { memScore = 15; } else if (usedPercent <= 80) { memScore = 10; } else if (usedPercent <= 90) { memScore = 5; } else { memScore = 0; } details.add({ 'label': 'استخدام الرام الحالي (${usedPercent.toStringAsFixed(0)}%)', 'status': memScore >= 10, 'achieved_score': memScore, 'max_score': 15, }); // Calculate the final total score by summing up the achieved scores. final totalScore = details.fold( 0, (sum, item) => sum + (item['achieved_score'] as int)); return { 'score': totalScore.clamp(0, 100), 'details': details, }; } } ================================================== FILE PATH: ./lib/controller/functions/call_controller.dart ================================================== // import 'package:SEFER/constant/api_key.dart'; // import 'package:SEFER/controller/functions/crud.dart'; // // import 'package:agora_rtc_engine/agora_rtc_engine.dart'; // import 'package:get/get.dart'; // import 'package:permission_handler/permission_handler.dart'; // import '../../constant/box_name.dart'; // import '../firebase/firbase_messge.dart'; // import '../home/captin/map_driver_controller.dart'; // import '../../main.dart'; // class CallController extends GetxController { // String channelName = ''; // Get.find().rideId; // String token = ''; // // int uid = int.parse(box.read(BoxName.phoneDriver)); // uid of the local user // int uid = 0; // int? remoteUid; // uid of the remote user // bool _isJoined = false; // Indicates if the local user has joined the channel // String status = ''; // // late RtcEngine agoraEngine; // Agora engine instance // @override // void onInit() { // super.onInit(); // channelName = Get.find().rideId; // 'sefer300'; // // remoteUid = int.parse(Get.find().passengerPhone); // uid = int.parse(box.read(BoxName.phoneDriver)); // initAgoraFull(); // } // initAgoraFull() async { // await fetchToken(); // // Set up an instance of Agora engine // setupVoiceSDKEngine(); // // join(); // FirebaseMessagesController().sendNotificationToPassengerTokenCALL( // 'Call Income', // '${'You have call from driver'.tr} ${box.read(BoxName.nameDriver)}', // Get.find().tokenPassenger, // [ // token, // channelName, // uid.toString(), // remoteUid.toString(), // ], // ); // join(); // } // @override // void onClose() { // // agoraEngine.leaveChannel(); // super.onClose(); // } // // Future setupVoiceSDKEngine() async { // // // retrieve or request microphone permission // // await [Permission.microphone].request(); // // //create an instance of the Agora engine // // agoraEngine = createAgoraRtcEngine(); // // await agoraEngine.initialize(RtcEngineContext(appId: AK.agoraAppId)); // // // Register the event handler // // agoraEngine.registerEventHandler( // // RtcEngineEventHandler( // // onJoinChannelSuccess: (RtcConnection connection, int elapsed) { // // // Get.snackbar( // // // "Local user uid:${connection.localUid} joined the channel", ''); // // status = 'joined'.tr; // // _isJoined = true; // // update(); // // }, // // onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) { // // // Get.snackbar("Remote user uid:$remoteUid joined the channel", ''); // // status = '${Get.find().passengerName} ' // // 'joined' // // .tr; // // remoteUid = remoteUid; // // update(); // // }, // // onUserOffline: (RtcConnection connection, int? remoteUid, // // UserOfflineReasonType reason) { // // // Get.snackbar("Remote user uid:$remoteUid left the channel", ''); // // status = 'Call Left'.tr; // // remoteUid = null; // // update(); // // }, // // ), // // ); // // } // // void join() async { // // // Set channel options including the client role and channel profile // // ChannelMediaOptions options = const ChannelMediaOptions( // // clientRoleType: ClientRoleType.clientRoleBroadcaster, // // channelProfile: ChannelProfileType.channelProfileCommunication, // // ); // // await agoraEngine.joinChannel( // // token: token, // // channelId: channelName, // // options: options, // // uid: uid, // // ); // // } // // void leave() { // // _isJoined = false; // // remoteUid = null; // // update(); // // agoraEngine.leaveChannel(); // // } // // // Clean up the resources when you leave // // @override // // void dispose() async { // // await agoraEngine.leaveChannel(); // // super.dispose(); // // } // fetchToken() async { // var res = await CRUD() // .getAgoraToken(channelName: channelName, uid: uid.toString()); // token = res; // update(); // } // } ================================================== FILE PATH: ./lib/controller/functions/encrypt.dart ================================================== import 'dart:convert'; import 'package:encrypt/encrypt.dart' as encrypt; import '../../constant/api_key.dart'; class KeyEncryption { // استخدم مفتاح بطول 32 حرفًا static final _key = encrypt.Key.fromUtf8(AK.keyOfApp); static final _iv = encrypt.IV.fromLength(16); // توليد تهيئة عشوائية بطول 16 بايت static String encryptKey(String key) { final encrypter = encrypt.Encrypter(encrypt.AES(_key, mode: encrypt.AESMode.cbc)); final encrypted = encrypter.encrypt(key, iv: _iv); final result = _iv.bytes + encrypted.bytes; // تضمين التهيئة مع النص المشفر return base64Encode(result); } static String decryptKey(String encryptedKey) { print('encryptedKey: ${AK.keyOfApp}'); final decoded = base64Decode(encryptedKey); print('encryptedKey: $encryptedKey'); final iv = encrypt.IV(decoded.sublist(0, 16)); // استخراج التهيئة final encrypted = encrypt.Encrypted(decoded.sublist(16)); // استخراج النص المشفر final encrypter = encrypt.Encrypter(encrypt.AES(_key, mode: encrypt.AESMode.cbc)); return encrypter.decrypt(encrypted, iv: iv); } } ================================================== FILE PATH: ./lib/controller/functions/security_checks.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; class SecurityChecks { static const platform = MethodChannel( 'com.intaleq_driver/security'); // Choose a unique channel name static Future isDeviceCompromised() async { try { final bool result = await platform .invokeMethod('isNativeRooted'); // Invoke the native method return result; } on PlatformException catch (e) { print("Failed to check security status: ${e.message}"); return true; // Treat platform errors as a compromised device (for safety) } } static isDeviceRootedFromNative(BuildContext context) async { bool compromised = await isDeviceCompromised(); if (compromised) { showDialog( barrierDismissible: false, context: context, builder: (context) => AlertDialog( title: Text("Security Warning".tr), content: Text( "Your device appears to be compromised. The app will now close." .tr), actions: [ TextButton( onPressed: () { SystemNavigator.pop(); // Close the app }, child: Text("OK"), ), ], ), ); } else { // Continue with normal app flow print("Device is secure."); } } } ================================================== FILE PATH: ./lib/controller/functions/performance_test.dart ================================================== import 'dart:io'; class PerformanceTester { /// ✅ فحص سرعة الكتابة إلى التخزين (Storage Write Speed) بوحدة MB/s static Future testStorageWriteSpeed() async { try { final tempDir = Directory.systemTemp; final testFile = File('${tempDir.path}/speed_test.txt'); final data = List.filled(1024 * 1024 * 5, 0); // 5MB final stopwatch = Stopwatch()..start(); await testFile.writeAsBytes(data, flush: true); stopwatch.stop(); await testFile.delete(); double seconds = stopwatch.elapsedMilliseconds / 1000; if (seconds == 0) seconds = 0.001; final speed = 5 / seconds; return double.parse(speed.toStringAsFixed(2)); } catch (e) { print("❌ Storage write error: $e"); return 0.0; } } /// ✅ فحص سرعة المعالج (CPU Compute Speed) بوحدة الثواني static Future testCPUSpeed() async { try { final stopwatch = Stopwatch()..start(); double x = 0; for (int i = 0; i < 100000000; i++) { x += i * 0.000001; } stopwatch.stop(); return stopwatch.elapsedMilliseconds / 1000.0; } catch (e) { print("❌ CPU compute error: $e"); return 999.0; } } } ================================================== FILE PATH: ./lib/controller/functions/encrypt_decrypt.dart ================================================== import 'package:encrypt/encrypt.dart' as encrypt; import 'package:flutter/foundation.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/char_map.dart'; import '../../env/env.dart'; import '../../main.dart'; import '../../print.dart'; class EncryptionHelper { static EncryptionHelper? _instance; late final encrypt.Key key; late final encrypt.IV iv; EncryptionHelper._(this.key, this.iv); static EncryptionHelper get instance { if (_instance == null) { throw Exception( "EncryptionHelper is not initialized. Call `await EncryptionHelper.initialize()` in main."); } return _instance!; } /// Initializes and stores the instance globally static Future initialize() async { if (_instance != null) { debugPrint("EncryptionHelper is already initialized."); return; // Prevent re-initialization } debugPrint("Initializing EncryptionHelper..."); var keyOfApp = r(Env.keyOfApp).toString().split(Env.addd)[0]; var initializationVector = r(Env.initializationVector).toString().split(Env.addd)[0]; // Set the global instance _instance = EncryptionHelper._( encrypt.Key.fromUtf8(keyOfApp!), encrypt.IV.fromUtf8(initializationVector!), ); debugPrint("EncryptionHelper initialized successfully."); } /// Encrypts a string String encryptData(String plainText) { try { final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); final encrypted = encrypter.encrypt(plainText, iv: iv); return encrypted.base64; } catch (e) { debugPrint('Encryption Error: $e'); return ''; } } /// Decrypts a string String decryptData(String encryptedText) { try { final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); final encrypted = encrypt.Encrypted.fromBase64(encryptedText); return encrypter.decrypt(encrypted, iv: iv); } catch (e) { debugPrint('Decryption Error: $e'); return ''; } } } r(String string) { return X.r(X.r(X.r(string, cn), cC), cs).toString(); } c(String string) { return X.c(X.c(X.c(string, cn), cC), cs).toString(); } ================================================== FILE PATH: ./lib/controller/functions/tts.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_tts/flutter_tts.dart'; import 'package:get/get.dart'; class TextToSpeechController extends GetxController { final flutterTts = FlutterTts(); bool isComplete = false; // Initialize TTS in initState @override void onInit() { super.onInit(); initTts(); } // Dispose of TTS when controller is closed @override void onClose() { super.onClose(); flutterTts.completionHandler; } // Function to initialize TTS engine Future initTts() async { String? lang = WidgetsBinding.instance.platformDispatcher.locale.countryCode; await flutterTts .setLanguage(box.read(BoxName.lang).toString()); //'en-US' Set language // await flutterTts.setLanguage('ar-SA'); //'en-US' Set language // await flutterTts.setLanguage(lang!); //'en-US' Set language await flutterTts.setSpeechRate(0.5); // Adjust speech rate await flutterTts.setVolume(1.0); // Set volume } // Function to speak the given text Future speakText(String text) async { try { await flutterTts.awaitSpeakCompletion(true); var result = await flutterTts.speak(text); if (result == 1) { // TTS operation has started // You can perform additional operations here, if needed isComplete = true; update(); } } catch (error) { mySnackeBarError('Failed to speak text: $error'); } } } ================================================== FILE PATH: ./lib/controller/functions/upload_image.dart ================================================== import 'dart:convert'; import 'dart:io'; import 'package:sefer_driver/constant/api_key.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart'; import 'package:image/image.dart' as img; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/info.dart'; import '../../main.dart'; import '../../print.dart'; import 'encrypt_decrypt.dart'; class ImageController extends GetxController { File? myImage; bool isloading = false; CroppedFile? croppedFile; final picker = ImagePicker(); var image; Future detectAndCropDocument(File imageFile) async { img.Image? image = img.decodeImage(await imageFile.readAsBytes()); if (image == null) throw Exception('Unable to decode image'); int left = image.width, top = image.height, right = 0, bottom = 0; // Threshold for considering a pixel as part of the document (adjust as needed) const int threshold = 240; for (int y = 0; y < image.height; y++) { for (int x = 0; x < image.width; x++) { final pixel = image.getPixel(x, y); final luminance = img.getLuminance(pixel); if (luminance < threshold) { left = x < left ? x : left; top = y < top ? y : top; right = x > right ? x : right; bottom = y > bottom ? y : bottom; } } } // Add a small padding left = (left - 5).clamp(0, image.width); top = (top - 5).clamp(0, image.height); right = (right + 5).clamp(0, image.width); bottom = (bottom + 5).clamp(0, image.height); return img.copyCrop(image, x: left, y: top, width: right - left, height: bottom - top); } Future rotateImageIfNeeded(File imageFile) async { img.Image croppedDoc = await detectAndCropDocument(imageFile); // Check if the document is in portrait orientation bool isPortrait = croppedDoc.height > croppedDoc.width; img.Image processedImage; if (isPortrait) { // Rotate the image by 90 degrees clockwise processedImage = img.copyRotate(croppedDoc, angle: 90); } else { processedImage = croppedDoc; } // Get temporary directory final tempDir = await path_provider.getTemporaryDirectory(); final tempPath = tempDir.path; // Create the processed image file File processedFile = File('$tempPath/processed_image.jpg'); await processedFile.writeAsBytes(img.encodeJpg(processedImage)); return processedFile; } Future rotateImage(File imageFile) async { // Read the image file img.Image? image = img.decodeImage(await imageFile.readAsBytes()); if (image == null) return imageFile; // Rotate the image by 90 degrees clockwise img.Image rotatedImage = img.copyRotate(image, angle: 90); // Get temporary directory final tempDir = await path_provider.getTemporaryDirectory(); final tempPath = tempDir.path; // Create the rotated image file File rotatedFile = File('$tempPath/rotated_image.jpg'); await rotatedFile.writeAsBytes(img.encodeJpg(rotatedImage)); return rotatedFile; } choosImage(String link, String imageType) async { try { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.rear, ); if (pickedImage == null) return; image = File(pickedImage.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings( title: 'Cropper'.tr, ), ], ); if (croppedFile == null) return; myImage = File(croppedFile!.path); isloading = true; update(); // Rotate the compressed image File processedImage = await rotateImageIfNeeded(File(croppedFile!.path)); File compressedImage = await compressImage(processedImage); print('link =$link'); // Log.print('link: ${link}'); //n8u22456 await uploadImage( compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), 'imageType': imageType, }, link, ); } catch (e) { print('Error in choosImage: $e'); mySnackeBarError('Image Upload Failed'.tr); // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.primaryColor); } finally { isloading = false; update(); } } choosImageNewCAr(String link, String imageType) async { try { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.rear, ); if (pickedImage == null) return; image = File(pickedImage.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings( title: 'Cropper'.tr, ), ], ); if (croppedFile == null) return; myImage = File(croppedFile!.path); isloading = true; update(); // Rotate the compressed image File processedImage = await rotateImageIfNeeded(File(croppedFile!.path)); File compressedImage = await compressImage(processedImage); print('link =$link'); // Log.print('link: ${link}'); //n8u22456 await uploadNewCar( compressedImage, { 'driverID': box.read(BoxName.driverID) + '_' + DateTime.now().toIso8601String(), 'imageType': imageType, }, link, ); } catch (e) { print('Error in choosImage: $e'); // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.primaryColor); mySnackeBarError('Image Upload Failed'.tr); } finally { isloading = false; update(); } } // choosFaceFromDriverLicense(String link, String imageType) async { // final pickedImage = await picker.pickImage( // source: ImageSource.camera, // preferredCameraDevice: CameraDevice.rear, // ); // if (pickedImage == null) return; // image = File(pickedImage.path); // File? processedImage; // // For face images, use face detection and cropping // processedImage = await detectAndCropFace(image!); // if (processedImage == null) { // Get.snackbar('Face Detection Failed', 'No face detected in the image.'); // return; // } // isloading = true; // update(); // File compressedImage = await compressImage(processedImage); // try { // await uploadImage( // compressedImage, // { // 'driverID': box.read(BoxName.driverID).toString(), // 'imageType': imageType // }, // link, // ); // } catch (e) { // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.redColor); // } finally { // isloading = false; // update(); // } // } choosFace(String link, String imageType) async { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.front, ); if (pickedImage != null) { image = File(pickedImage.path); isloading = true; update(); // Compress the image File compressedImage = await compressImage(File(pickedImage.path)); // Save the picked image directly // File savedImage = File(pickedImage.path); print('link =$link'); try { await uploadImage( compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), 'imageType': imageType }, link, ); } catch (e) { mySnackeBarError('Image Upload Failed'.tr); // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.redColor); } finally { isloading = false; update(); } } } uploadImage(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', Uri.parse(link), ); Log.print('request: ${request}'); var length = await file.length(); var stream = http.ByteStream(file.openRead()); final headers = { 'Authorization': 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', }; var multipartFile = http.MultipartFile( 'image', stream, length, filename: basename(file.path), ); request.headers.addAll(headers); // Set the file name to the driverID request.files.add( http.MultipartFile( 'image', stream, length, filename: '${box.read(BoxName.driverID)}.jpg', ), ); data.forEach((key, value) { request.fields[key] = value; }); var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}'); return jsonDecode(res.body); } else { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } } uploadNewCar(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', Uri.parse(link), ); var length = await file.length(); var stream = http.ByteStream(file.openRead()); var multipartFile = http.MultipartFile( 'image', stream, length, filename: basename(file.path), ); request.headers.addAll({ 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', }); // Set the file name to the driverID request.files.add( http.MultipartFile( 'image', stream, length, filename: '${box.read(BoxName.driverID)}.jpg', ), ); data.forEach((key, value) { request.fields[key] = value; }); var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}'); return jsonDecode(res.body); } else { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } } choosImagePicture(String link, String imageType) async { final pickedImage = await picker.pickImage( source: ImageSource.gallery, // preferredCameraDevice: CameraDevice.rear, // maxHeight: Get.height * .3, // maxWidth: Get.width * .9, // imageQuality: 100, ); image = File(pickedImage!.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false), IOSUiSettings( title: 'Cropper'.tr, ), ], ); myImage = File(pickedImage.path); isloading = true; update(); // Save the cropped image // File savedCroppedImage = File(croppedFile!.path); File compressedImage = await compressImage(File(croppedFile!.path)); print('link =$link'); try { await uploadImage( compressedImage, {'driverID': (box.read(BoxName.driverID)), 'imageType': imageType}, link, ); } catch (e) { Log.print('e: ${e}'); mySnackeBarError('Image Upload Failed'.tr); // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.redColor); } finally { isloading = false; update(); } } uploadImagePicture(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php' ); var length = await file.length(); var stream = http.ByteStream(file.openRead()); var multipartFile = http.MultipartFile( 'image', stream, length, filename: basename(file.path), ); request.headers.addAll({ 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', }); // Set the file name to the driverID request.files.add( http.MultipartFile( 'image', stream, length, filename: '${(box.read(BoxName.driverID))}.jpg', ), ); data.forEach((key, value) { request.fields[key] = value; }); var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { return jsonDecode(res.body); } else { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } } } Future compressImage(File file) async { final dir = await path_provider.getTemporaryDirectory(); final targetPath = "${dir.absolute.path}/temp.jpg"; var result = await FlutterImageCompress.compressAndGetFile( file.absolute.path, targetPath, quality: 70, minWidth: 1024, minHeight: 1024, ); return File(result!.path); } // Future detectAndCropFace(File imageFile) async { // final inputImage = InputImage.fromFilePath(imageFile.path); // final options = FaceDetectorOptions( // enableClassification: false, // enableLandmarks: false, // enableTracking: false, // minFaceSize: 0.15, // performanceMode: FaceDetectorMode.accurate, // ); // final faceDetector = FaceDetector(options: options); // try { // final List faces = await faceDetector.processImage(inputImage); // final image = img.decodeImage(await imageFile.readAsBytes()); // if (image == null) throw Exception('Unable to decode image'); // int left, top, width, height; // if (faces.isNotEmpty) { // // Face detected, crop around the face // final face = faces[0]; // double padding = 0.2; // 20% padding // int paddingX = (face.boundingBox.width * padding).round(); // int paddingY = (face.boundingBox.height * padding).round(); // left = (face.boundingBox.left - paddingX).round(); // top = (face.boundingBox.top - paddingY).round(); // width = (face.boundingBox.width + 2 * paddingX).round(); // height = (face.boundingBox.height + 2 * paddingY).round(); // } else { // // No face detected, crop the center of the image // int size = min(image.width, image.height); // left = (image.width - size) ~/ 2; // top = (image.height - size) ~/ 2; // width = size; // height = size; // } // // Ensure dimensions are within image bounds // left = left.clamp(0, image.width - 1); // top = top.clamp(0, image.height - 1); // width = width.clamp(1, image.width - left); // height = height.clamp(1, image.height - top); // final croppedImage = // img.copyCrop(image, x: left, y: top, width: width, height: height); // // Save the cropped image // final tempDir = await path_provider.getTemporaryDirectory(); // final tempPath = tempDir.path; // final croppedFile = File('$tempPath/cropped_image.jpg'); // await croppedFile.writeAsBytes(img.encodeJpg(croppedImage, quality: 100)); // return croppedFile; // } finally { // faceDetector.close(); // } // } ================================================== FILE PATH: ./lib/controller/functions/custom_pant.dart ================================================== import 'package:flutter/material.dart'; class LineChartPainter extends CustomPainter { final List data; LineChartPainter(this.data); @override void paint(Canvas canvas, Size size) { // Calculate the scale factor. final scaleFactor = size.height / 240; // Draw the line chart. for (var i = 0; i < data.length - 1; i++) { final x1 = i * size.width / data.length; final y1 = data[i] * scaleFactor; final x2 = (i + 1) * size.width / data.length; final y2 = data[i + 1] * scaleFactor; canvas.drawLine(Offset(x1, y1), Offset(x2, y2), Paint()); } } @override bool shouldRepaint(LineChartPainter oldDelegate) => false; } ================================================== FILE PATH: ./lib/controller/functions/remove_account.dart ================================================== // import 'package:ride/controller/functions/crud.dart'; // class RemoveAccount { // void removeAccount()async{ // var res=await CRUD().post(link: link) // } // } ================================================== FILE PATH: ./lib/controller/functions/battery_status.dart ================================================== import 'package:battery_plus/battery_plus.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class BatteryNotifier { static final Battery _battery = Battery(); static int? _lastNotifiedLevel; static Future checkBatteryAndNotify() async { try { final int batteryLevel = await _battery.batteryLevel; // ✅ لا تكرر الإشعار إذا الفرق قليل if (_lastNotifiedLevel != null && (batteryLevel >= _lastNotifiedLevel! - 2)) return; if (batteryLevel <= 30) { Color backgroundColor = Colors.yellow; if (batteryLevel <= 20) { backgroundColor = Colors.red; } Get.snackbar( "⚠️ تنبيه البطارية", // العنوان "مستوى البطارية: $batteryLevel٪", // النص snackPosition: SnackPosition.TOP, backgroundColor: backgroundColor, colorText: Colors.white, duration: const Duration(seconds: 10), // مدة الظهور margin: const EdgeInsets.all(10), ); _lastNotifiedLevel = batteryLevel; } } catch (e) { print('Battery check error: $e'); } } } ================================================== FILE PATH: ./lib/controller/functions/crud.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:path/path.dart'; import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart'; import 'package:sefer_driver/controller/functions/network/net_guard.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:sefer_driver/env/env.dart'; import 'package:sefer_driver/print.dart'; import '../../constant/api_key.dart'; import '../../constant/char_map.dart'; import '../../constant/info.dart'; import '../../views/widgets/error_snakbar.dart'; import 'gemeni.dart'; import 'upload_image.dart'; class CRUD { final NetGuard _netGuard = NetGuard(); final _client = http.Client(); /// Stores the signature of the last logged error to prevent duplicates. static String _lastErrorSignature = ''; /// Stores the timestamp of the last logged error. static DateTime _lastErrorTimestamp = DateTime(2000); // Initialize with an old date /// The minimum time that must pass before logging the same error again. static const Duration _errorLogDebounceDuration = Duration(minutes: 1); /// Asynchronously logs an error to the server with debouncing to prevent log flooding. /// /// [error]: A concise description of the error. /// [details]: Detailed information, such as a stack trace or the server response body. /// [where]: The location in the code where the error occurred (e.g., 'ClassName.methodName'). static Future addError( String error, String details, String where) async { try { final currentErrorSignature = '$where-$error'; final now = DateTime.now(); if (currentErrorSignature == _lastErrorSignature && now.difference(_lastErrorTimestamp) < _errorLogDebounceDuration) { return; } _lastErrorSignature = currentErrorSignature; _lastErrorTimestamp = now; final userId = box.read(BoxName.driverID) ?? box.read(BoxName.passengerID); final userType = box.read(BoxName.driverID) != null ? 'Driver' : 'Passenger'; final phone = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); // Fire-and-forget call to prevent infinite loops if the logger itself fails. CRUD().post( link: AppLink.addError, payload: { 'error': error.toString(), 'userId': userId.toString(), 'userType': userType, 'phone': phone.toString(), 'device': where, 'details': details, }, ); } catch (e) {} } /// Centralized private method to handle all API requests. /// Includes retry logic, network checking, and standardized error handling. // --- تعديل 1: دالة _makeRequest محسنة للإنترنت الضعيف --- Future _makeRequest({ required String link, Map? payload, required Map headers, }) async { // 🟢 زيادة الوقت للسماح بالشبكات البطيئة (سوريا) const connectTimeout = Duration(seconds: 20); // رفعنا الوقت من 6 لـ 20 const receiveTimeout = Duration(seconds: 40); // رفعنا الوقت من 10 لـ 40 Future doPost() { final url = Uri.parse(link); // نستخدم _client إذا كان معرفاً، أو ننشئ واحداً جديداً مع إغلاقه لاحقاً // لضمان عدم حدوث مشاكل، سنستخدم http.post المباشر كما في النسخة المستقرة لديك // ولكن مع timeout أطول return http .post(url, body: payload, headers: headers) .timeout(connectTimeout + receiveTimeout); } http.Response response = http.Response('', 500); // Default initialization // 🟢 محاولة إعادة الاتصال (Retry) حتى 3 مرات int attempts = 0; while (attempts < 3) { try { attempts++; response = await doPost(); // إذا نجح الاتصال، نخرج من الحلقة ونعالج الرد break; } on SocketException catch (_) { if (attempts >= 3) { _netGuard.notifyOnce((title, msg) => mySnackeBarError(msg)); return 'no_internet'; } // انتظار بسيط قبل المحاولة التالية (مهم جداً للشبكات المتقطعة) await Future.delayed(const Duration(seconds: 1)); } on TimeoutException catch (_) { if (attempts >= 3) return 'failure'; // لا ننتظر هنا، نعيد المحاولة فوراً } catch (e) { // إذا كان الخطأ هو errno = 9 (Bad file descriptor) نعيد المحاولة if (e.toString().contains('errno = 9') && attempts < 3) { await Future.delayed(const Duration(milliseconds: 500)); continue; } // أخطاء أخرى لا يمكن تجاوزها addError( 'HTTP Exception: $e', 'Try: $attempts', 'CRUD._makeRequest $link'); return 'failure'; } } // --- معالجة الرد (كما هي في كودك) --- // ملاحظة: المتغير response هنا قد يكون غير معرف (null) إذا فشلت كل المحاولات // لكن بسبب الـ return داخل الـ catch، لن نصل هنا إلا بوجود response // الحل الآمن لضمان وجود response قبل استخدامه: try { // إعادة تعريف response لضمان عدم حدوث خطأ null safety في المحرر // (في المنطق الفعلي لن نصل هنا إلا ومعنا response) if (attempts > 3) return 'failure'; final sc = response.statusCode; // استخدمنا ! لأننا متأكدين final body = response.body; if (sc >= 200 && sc < 300) { try { final jsonData = jsonDecode(body); return jsonData; } catch (e, st) { addError('JSON Decode Error', 'Body: $body\n$st', 'CRUD._makeRequest $link'); return 'failure'; } } if (sc == 401) { return 'token_expired'; } if (sc >= 500) { addError( 'Server 5xx', 'SC: $sc\nBody: $body', 'CRUD._makeRequest $link'); return 'failure'; } return 'failure'; } catch (e) { return 'failure'; } } // --- تعديل 2: دالة get (كما طلبت: بوست + إرجاع النص الخام) --- // أبقيتها كما هي في كودك الأصلي تماماً، فقط حسنت الـ Timeout Future get({ required String link, Map? payload, }) async { try { var url = Uri.parse(link); // 🟢 إضافة timeout هنا أيضاً var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer ${r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]}' }, ).timeout(const Duration(seconds: 40)); // وقت كافٍ للشبكات الضعيفة Log.print('response: ${response.body}'); Log.print('response: ${response.request}'); if (response.statusCode == 200) { // المنطق الخاص بك: إرجاع الـ body كاملاً كنص (String) // لأنك تريد عمل jsonDecode لاحقاً في المكان الذي استدعى الدالة // أو التحقق من status: success داخلياً // ملاحظة: في كودك الأصلي كنت تفحص jsonDecode هنا وتعود بـ response.body // سأبقيها كما هي: var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return response.body; // إرجاع النص الخام } return jsonData['status']; } else if (response.statusCode == 401) { var jsonData = jsonDecode(response.body); if (jsonData['error'] == 'Token expired') { await Get.put(LoginDriverController()).getJWT(); return 'token_expired'; } else { // addError('Unauthorized: ${jsonData['error']}', 'crud().get - 401', // url.toString()); return 'failure'; } } else { addError('Non-200: ${response.statusCode}', 'crud().get - Other', url.toString()); return 'failure'; } } on TimeoutException { // معالجة صامتة للتايم أوت في الـ GET return 'failure'; } on SocketException { // معالجة صامتة لانقطاع النت return 'no_internet'; } catch (e) { addError('GET Exception: $e', '', link); return 'failure'; } } /// Performs a standard authenticated POST request. /// Automatically handles token renewal. Future post({ required String link, Map? payload, }) async { String token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]; // if (JwtDecoder.isExpired(token)) { // await Get.put(LoginController()).getJWT(); // token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]; // } final headers = { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $token' }; return await _makeRequest( link: link, payload: payload, headers: headers, ); } /// Performs a standard authenticated GET request (using POST method as per original code). /// Automatically handles token renewal. /// Performs an authenticated POST request to wallet endpoints. Future postWallet({ required String link, Map? payload, }) async { var jwt = await LoginDriverController().getJwtWallet(); final hmac = box.read(BoxName.hmac); final headers = { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $jwt', 'X-HMAC-Auth': hmac.toString(), }; return await _makeRequest( link: link, payload: payload, headers: headers, ); } /// Performs an authenticated GET request to wallet endpoints (using POST). Future getWallet({ required String link, Map? payload, }) async { var s = await LoginDriverController().getJwtWallet(); final hmac = box.read(BoxName.hmac); var url = Uri.parse( link, ); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $s', 'X-HMAC-Auth': hmac.toString(), }, ); if (response.statusCode == 200) { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return response.body; } return jsonData['status']; } else if (response.statusCode == 401) { // Specifically handle 401 Unauthorized var jsonData = jsonDecode(response.body); if (jsonData['error'] == 'Token expired') { // Show snackbar prompting to re-login await Get.put(LoginDriverController()).getJwtWallet(); return 'token_expired'; // Return a specific value for token expiration } else { // Other 401 errors addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401', url.toString()); return 'failure'; } } else { addError('Non-200 response code: ${response.statusCode}', 'crud().post - Other', url.toString()); return 'failure'; } } Future postWalletMtn( {required String link, Map? payload}) async { final s = await LoginDriverController().getJwtWallet(); final hmac = box.read(BoxName.hmac); final url = Uri.parse(link); try { final response = await http.post( url, body: payload, // form-urlencoded مناسب لـ filterRequest headers: { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer $s", "X-HMAC-Auth": hmac.toString(), }, ); Map wrap(String status, {Object? message, int? code}) { return { 'status': status, 'message': message, 'code': code ?? response.statusCode, }; } if (response.statusCode == 200) { try { final jsonData = jsonDecode(response.body); // نتوقع الآن شكل موحّد من السيرفر: {status, message, data?} return jsonData; } catch (e) { return wrap('failure', message: 'JSON decode error', code: response.statusCode); } } else if (response.statusCode == 401) { try { final jsonData = jsonDecode(response.body); if (jsonData is Map && jsonData['error'] == 'Token expired') { await Get.put(LoginDriverController()).getJWT(); return { 'status': 'failure', 'message': 'token_expired', 'code': 401 }; } return wrap('failure', message: jsonData); } catch (_) { return wrap('failure', message: response.body); } } else { // غير 200 – ارجع التفاصيل try { final jsonData = jsonDecode(response.body); return wrap('failure', message: jsonData); } catch (_) { return wrap('failure', message: response.body); } } } catch (e) { return { 'status': 'failure', 'message': 'HTTP request error: $e', 'code': -1 }; } } // Future postWallet( // {required String link, Map? payload}) async { // var s = await LoginDriverController().getJwtWallet(); // final hmac = box.read(BoxName.hmac); // var url = Uri.parse(link); // try { // // await LoginDriverController().getJWT(); // var response = await http.post( // url, // body: payload, // headers: { // "Content-Type": "application/x-www-form-urlencoded", // 'Authorization': 'Bearer $s', // 'X-HMAC-Auth': hmac.toString(), // }, // ); // if (response.statusCode == 200) { // try { // var jsonData = jsonDecode(response.body); // if (jsonData['status'] == 'success') { // return jsonData; // } else { // return jsonData['status']; // } // } catch (e) { // // addError(e.toString(), 'crud().post - JSON decoding'); // return 'failure'; // } // } else if (response.statusCode == 401) { // // Specifically handle 401 Unauthorized // var jsonData = jsonDecode(response.body); // if (jsonData['error'] == 'Token expired') { // return 'token_expired'; // Return a specific value for token expiration // } else { // // Other 401 errors // // addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401'); // return 'failure'; // } // } else { // // addError('Non-200 response code: ${response.statusCode}', // // 'crud().post - Other'); // return 'failure'; // } // } catch (e) { // // addError('HTTP request error: $e', 'crud().post - HTTP'); // return 'failure'; // } // } // Future post( // {required String link, Map? payload}) async { // var url = Uri.parse(link); // try { // bool isTokenExpired = JwtDecoder.isExpired(X // .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) // .toString() // .split(AppInformation.addd)[0]); // if (isTokenExpired) { // await LoginDriverController().getJWT(); // } // var response = await http.post( // url, // body: payload, // headers: { // "Content-Type": "application/x-www-form-urlencoded", // 'Authorization': // 'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}' // // 'Authorization': 'Bearer ${box.read(BoxName.jwt)}' // }, // ); // if (response.statusCode == 200) { // try { // var jsonData = jsonDecode(response.body); // if (jsonData['status'] == 'success') { // return jsonData; // } else { // return jsonData['status']; // } // } catch (e) { // // addError(e.toString(), url); // return 'failure'; // } // } else if (response.statusCode == 401) { // // Specifically handle 401 Unauthorized // var jsonData = jsonDecode(response.body); // if (jsonData['error'] == 'Token expired') { // // Show snackbar prompting to re-login // // await Get.put(LoginDriverController()).getJWT(); // // MyDialog().getDialog( // // 'Session expired. Please log in again.'.tr, // // '', // // () { // // Get.put(LoginController()).loginUsingCredentials( // // box.read(BoxName.passengerID), box.read(BoxName.email)); // // Get.back(); // // }, // // ); // return 'token_expired'; // Return a specific value for token expiration // } else { // // Other 401 errors // // addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401'); // return 'failure'; // } // } else { // // addError('Non-200 response code: ${response.statusCode}', // // 'crud().post - Other'); // return 'failure'; // } // } catch (e) { // // addError('HTTP request error: $e', 'crud().post - HTTP'); // return 'failure'; // } // } Future getAgoraToken({ required String channelName, required String uid, }) async { var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); var res = await http.get(Uri.parse( // 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'), 'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'), headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'}); if (res.statusCode == 200) { var response = jsonDecode(res.body); return response['token']; } else {} } Future getLlama({ required String link, required String payload, required String prompt, }) async { var url = Uri.parse( link, ); var headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy' // 'Authorization': 'Bearer ${Env.llamaKey}' }; var data = json.encode({ "model": "Llama-3-70b-Inst-FW", // "model": "llama-13b-chat", "messages": [ { "role": "user", "content": "Extract the desired information from the following passage as json decoded like $prompt just in this:\n\n$payload" } ], "temperature": 0.9 }); var response = await http.post( url, body: data, headers: headers, ); if (response.statusCode == 200) { return response.body; } return response.statusCode; } Future allMethodForAI(String prompt, linkPHP, imagePath) async { await ImageController().choosImage(linkPHP, imagePath); Future.delayed(const Duration(seconds: 2)); var extractedString = await arabicTextExtractByVisionAndAI(imagePath: imagePath); var json = jsonDecode(extractedString); var textValues = extractTextFromLines(json); // await Get.put(AI()).geminiAiExtraction(prompt, textValues); await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); } String extractTextFromLines(Map jsonData) { final readResult = jsonData['readResult']; final blocks = readResult['blocks']; final StringBuffer buffer = StringBuffer(); for (final block in blocks) { final lines = block['lines']; for (final line in lines) { final text = line['text']; buffer.write(text); buffer.write('\n'); } } return buffer.toString().trim(); } Future arabicTextExtractByVisionAndAI({ required String imagePath, }) async { var headers = { 'Content-Type': 'application/json', 'Ocp-Apim-Subscription-Key': AK.ocpApimSubscriptionKey }; String imagePathFull = '${AppLink.server}/card_image/$imagePath-${box.read(BoxName.driverID)}.jpg'; var request = http.Request('POST', Uri.parse( // 'https://ocrhamza.cognitiveservices.azure.com/vision/v2.1/ocr?language=ar')); // 'https://eastus.api.cognitive.microsoft.com/vision/v3.2/ocr' 'https://eastus.api.cognitive.microsoft.com/computervision/imageanalysis:analyze?features=caption,read&model-version=latest&language=en&api-version=2024-02-01')); request.body = json.encode({"url": imagePathFull}); // request.body = json.encode({"url": imagePathFull}); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { // 'response.stream.bytesToString(): ${await response.stream.bytesToString()}'); return await response.stream.bytesToString(); } else {} } Future getChatGPT({ required String link, required String payload, }) async { var url = Uri.parse( link, ); var headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ${Env.chatGPTkeySeferNew}' }; var data = json.encode({ "model": "gpt-3.5-turbo", "messages": [ { "role": "user", "content": "Extract the desired information from the following passage as json decoded like vin,make,made,year,expiration_date,color,owner,registration_date just in this:\n\n$payload" } ], "temperature": 0.9 }); var response = await http.post( url, body: data, headers: headers, ); if (response.statusCode == 200) { return response.body; } return response.statusCode; } Future postStripe({ required String link, Map? payload, }) async { // String? secretKey = await storage.read(key: BoxName.secretKey); var url = Uri.parse( link, ); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer ${AK.secretKeyStripe}', }, ); if (response.statusCode == 200) { return response.body; } else {} } Future postPayMob({ required String link, Map? payload, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse( link, ); var response = await http.post(url, body: payload, headers: {'Content-Type': 'application/json'}); var jsonData = jsonDecode(response.body); if (response.statusCode == 200) { if (jsonData['status'] == 'success') { return response.body; } else { return (jsonData['status']); } } else { return response.statusCode; } } Future sendEmail(String link, Map? payload) async { // التحقق من صلاحية التوكن String rawJwt = box.read(BoxName.jwt); String token = X .r(X.r(X.r(rawJwt, cn), cC), cs) .toString() .split(AppInformation.addd)[0]; bool isTokenExpired = JwtDecoder.isExpired(token); if (isTokenExpired) { await LoginDriverController().getJWT(); rawJwt = box.read(BoxName.jwt); // تحديث التوكن بعد التجديد token = X .r(X.r(X.r(rawJwt, cn), cC), cs) .toString() .split(AppInformation.addd)[0]; } // إعداد الهيدر final headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Bearer $token", }; // إعداد الطلب final request = http.Request('POST', Uri.parse(link)); request.bodyFields = payload ?? {}; request.headers.addAll(headers); // إرسال الطلب final response = await request.send(); // التحقق من النتيجة if (response.statusCode == 200) { } else { final responseBody = await response.stream.bytesToString(); } } Future postFromDialogue({ required String link, Map? payload, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse( link, ); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); if (response.body.isNotEmpty) { var jsonData = jsonDecode(response.body); if (response.statusCode == 200) { if (jsonData['status'] == 'success') { Get.back(); // Get.snackbar( // jsonData['status'], // jsonData['message'], // ); return response.body; } } return (jsonData['status']); } } Future sendVerificationRequest(String phoneNumber) async { final accountSid = AK.accountSIDTwillo; final authToken = AK.authTokenTwillo; final verifySid = AK.twilloRecoveryCode; final Uri verificationUri = Uri.parse( 'https://verify.twilio.com/v2/Services/$verifySid/Verifications'); // Send the verification request final response = await http.post( verificationUri, headers: { 'Authorization': 'Basic ' + base64Encode(utf8.encode('$accountSid:$authToken')), 'Content-Type': 'application/x-www-form-urlencoded', }, body: { 'To': phoneNumber, 'Channel': 'sms', }, ); if (response.statusCode == 201) { } else {} // Prompt the user to enter the OTP final otpCode = "123456"; // Replace with user input // Check the verification code final checkUri = Uri.parse( 'https://verify.twilio.com/v2/Services/$verifySid/VerificationCheck'); final checkResponse = await http.post( checkUri, headers: { 'Authorization': 'Basic ' + base64Encode(utf8.encode('$accountSid:$authToken')), 'Content-Type': 'application/x-www-form-urlencoded', }, body: { 'To': phoneNumber, 'Code': otpCode, }, ); if (checkResponse.statusCode == 201) { } else {} } Future getGoogleApi({ required String link, Map? payload, }) async { var url = Uri.parse( link, ); var response = await http.post( url, body: payload, ); var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'OK') { return jsonData; } return (jsonData['status']); } Future update({ required String endpoint, required Map data, required String id, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse('$endpoint/$id'); var response = await http.put( url, body: json.encode(data), headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); return json.decode(response.body); } Future delete({ required String endpoint, required String id, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse('$endpoint/$id'); var response = await http.delete( url, headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); return json.decode(response.body); } } /// Custom exception for when there is no internet connection. class NoInternetException implements Exception { final String message; NoInternetException( [this.message = 'No internet connection. Please check your network and try again.']); @override String toString() => message; } /// Custom exception for when the network is too slow (request times out). class WeakNetworkException implements Exception { final String message; WeakNetworkException( [this.message = 'Your network connection is too slow. Please try again later.']); @override String toString() => message; } class ApiException implements Exception { final String message; final int? statusCode; ApiException(this.message, [this.statusCode]); @override String toString() => "ApiException: $message (Status Code: ${statusCode ?? 'N/A'})"; } ================================================== FILE PATH: ./lib/controller/functions/digit_obsecur_formate.dart ================================================== import 'package:flutter/services.dart'; class DigitObscuringFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate( TextEditingValue oldValue, TextEditingValue newValue) { final maskedText = maskDigits(newValue.text); return newValue.copyWith( text: maskedText, selection: updateCursorPosition(maskedText, newValue.selection)); } String maskDigits(String text) { final totalDigits = text.length; final visibleDigits = 4; final hiddenDigits = totalDigits - visibleDigits * 2; final firstVisibleDigits = text.substring(0, visibleDigits); final lastVisibleDigits = text.substring(totalDigits - visibleDigits); final maskedDigits = List.filled(hiddenDigits, '*').join(); return '$firstVisibleDigits$maskedDigits$lastVisibleDigits'; } TextSelection updateCursorPosition( String maskedText, TextSelection currentSelection) { final cursorPosition = currentSelection.baseOffset; final cursorOffset = currentSelection.extentOffset - currentSelection.baseOffset; final totalDigits = maskedText.length; const visibleDigits = 4; final hiddenDigits = totalDigits - visibleDigits * 2; final updatedPosition = cursorPosition <= visibleDigits ? cursorPosition : hiddenDigits + visibleDigits + (cursorPosition - visibleDigits); return TextSelection.collapsed( offset: updatedPosition, affinity: currentSelection.affinity); } } ================================================== FILE PATH: ./lib/controller/functions/toast.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; class Toast { static void show(BuildContext context, String message, Color color) { final snackBar = SnackBar( clipBehavior: Clip.antiAliasWithSaveLayer, backgroundColor: color, elevation: 3, content: Text( message, style: AppStyle.title.copyWith(color: AppColor.secondaryColor), ), behavior: SnackBarBehavior.floating, animation: const AlwaysStoppedAnimation(1.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), // Custom border radius ), width: Get.width * .8, // shape: const StadiumBorder( // side: BorderSide( // color: AppColor.secondaryColor, // width: 1.0, // style: BorderStyle.solid, // )), duration: const Duration(seconds: 2), ); ScaffoldMessenger.of(context).showSnackBar( snackBar, ); } } ================================================== FILE PATH: ./lib/controller/functions/geolocation.dart ================================================== import 'package:geolocator/geolocator.dart'; class GeoLocation { Future getCurrentLocation() async { bool serviceEnabled; LocationPermission permission; // Check if location services are enabled. serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { // Location services are not enabled, so we request the user to enable it. return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { // Permissions are denied, we cannot fetch the location. return Future.error('Location permissions are denied'); } } if (permission == LocationPermission.deniedForever) { // Permissions are denied forever, we cannot request permissions. return Future.error( 'Location permissions are permanently denied, we cannot request permissions.'); } // When we reach here, permissions are granted and we can fetch the location. return await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); } } ================================================== FILE PATH: ./lib/controller/functions/log_out.dart ================================================== import 'package:sefer_driver/views/home/on_boarding_page.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import '../../constant/style.dart'; class LogOutController extends GetxController { TextEditingController checkTxtController = TextEditingController(); final formKey = GlobalKey(); final formKey1 = GlobalKey(); final emailTextController = TextEditingController(); Future deleteMyAccountDriver(String id) async { await CRUD().post(link: AppLink.removeUser, payload: {'id': id}).then( (value) => Get.snackbar('Deleted'.tr, 'Your Account is Deleted', backgroundColor: AppColor.redColor)); } checkBeforeDelete() async { var res = await CRUD().post( link: AppLink.deletecaptainAccounr, payload: {'id': box.read(BoxName.driverID)}); return res['message'][0]['id']; } deletecaptainAccount() { Get.defaultDialog( backgroundColor: AppColor.yellowColor, title: 'Are you sure to delete your account?'.tr, middleText: 'Your data will be erased after 2 weeks\nAnd you will can\'t return to use app after 1 month ', titleStyle: AppStyle.title, content: Column( children: [ Container( width: Get.width, decoration: AppStyle.boxDecoration, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( 'Your data will be erased after 2 weeks\nAnd you will can\'t return to use app after 1 month' .tr, style: AppStyle.title.copyWith(color: AppColor.redColor), ), ), ), const SizedBox( height: 20, ), Form( key: formKey, child: SizedBox( width: Get.width, child: MyTextForm( controller: checkTxtController, label: 'Enter Your First Name'.tr, hint: 'Enter Your First Name'.tr, type: TextInputType.name, ), )) ], ), confirm: MyElevatedButton( title: 'Delete'.tr, onPressed: () async { if (checkTxtController.text == (box.read(BoxName.nameDriver))) { // deletecaptainAccount(); var id = await checkBeforeDelete(); deleteMyAccountDriver(id); } else { mySnackeBarError('Your Name is Wrong'.tr); } })); } Future logOutPassenger() async { Get.defaultDialog( title: 'Are you Sure to LogOut?'.tr, content: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Cancel'.tr, onPressed: () => Get.back(), ), ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(AppColor.redColor), ), onPressed: () async { // box.remove(BoxName.agreeTerms); await box.erase(); await storage.deleteAll(); Get.offAll(OnBoardingPage()); }, child: Text( 'Sign Out'.tr, style: AppStyle.title.copyWith(color: AppColor.secondaryColor), )) ], )); } Future logOutCaptain() async { Get.defaultDialog( title: 'Are you Sure to LogOut?'.tr, titleStyle: AppStyle.title, content: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Cancel'.tr, onPressed: () => Get.back(), ), ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(AppColor.redColor), ), onPressed: () async { // box.remove(BoxName.agreeTerms); await box.erase(); await storage.deleteAll(); Get.offAll(OnBoardingPage()); }, child: Text( 'Sign Out'.tr, style: AppStyle.title.copyWith(color: AppColor.secondaryColor), )) ], )); } deletePassengerAccount() async { if (formKey1.currentState!.validate()) { if (box.read(BoxName.email).toString() == emailTextController.text) { await CRUD().post(link: AppLink.passengerRemovedAccountEmail, payload: { 'email': box.read(BoxName.email), }); } else { mySnackeBarError( 'Email you inserted is Wrong.'.tr, ); } } } } ================================================== FILE PATH: ./lib/controller/functions/package_info.dart ================================================== import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:ui'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:jailbreak_root_detection/jailbreak_root_detection.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../constant/info.dart'; import '../../main.dart'; import '../../print.dart'; import 'encrypt_decrypt.dart'; Future checkForUpdate(BuildContext context) async { final packageInfo = await PackageInfo.fromPlatform(); final currentVersion = packageInfo.buildNumber; final version = packageInfo.version; Log.print('version: ${version}'); print('currentVersion is : $currentVersion'); // Fetch the latest version from your server String latestVersion = await getPackageInfo(); box.write(BoxName.packagInfo, version); if (latestVersion.isNotEmpty && latestVersion != currentVersion) { showUpdateDialog(context); } } Future getPackageInfo() async { final response = await CRUD().get(link: AppLink.packageInfo, payload: { "platform": Platform.isAndroid ? 'android' : 'ios', "appName": AppInformation.appVersion, }); if (response != 'failure') { return jsonDecode(response)['message'][0]['version']; } return ''; } void showUpdateDialog(BuildContext context) { final String storeUrl = Platform.isAndroid ? 'https://play.google.com/store/apps/details?id=com.intaleq_driver' : 'https://apps.apple.com/jo/app/intaleq-driver/id6482995159'; showGeneralDialog( context: context, barrierDismissible: false, barrierColor: Colors.black.withOpacity(0.5), pageBuilder: (_, __, ___) { return BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Center( child: AlertDialog( // Using AlertDialog for a more Material Design look shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16)), // More rounded corners elevation: 4, // Add a bit more elevation contentPadding: EdgeInsets.zero, // Remove default content padding content: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only(top: 20.0), child: Image.asset( 'assets/images/logo.png', height: 72, // Slightly larger logo width: 72, ), ), const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Text( 'Update Available'.tr, textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleLarge?.copyWith( // Use theme's title style fontWeight: FontWeight.bold, ), ), ), Padding( padding: const EdgeInsets.all(24.0), child: Text( 'A new version of the app is available. Please update to the latest version.' .tr, // More encouraging message textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium?.copyWith( // Use theme's body style color: Colors.black87, ), ), ), const Divider(height: 0), Row( children: [ Expanded( child: TextButton( // Using TextButton for "Cancel" onPressed: () => Navigator.pop(context), style: TextButton.styleFrom( foregroundColor: Colors.grey, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(16), ), ), ), child: Text('Cancel'.tr), ), ), const SizedBox( height: 48, child: VerticalDivider(width: 0), // Using VerticalDivider ), Expanded( child: ElevatedButton( // Using ElevatedButton for "Update" onPressed: () async { if (await canLaunchUrl(Uri.parse(storeUrl))) { await launchUrl(Uri.parse(storeUrl)); } if (context.mounted) Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: AppColor .primaryColor, // Use theme's primary color foregroundColor: Theme.of(context) .colorScheme .onPrimary, // Use theme's onPrimary color shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( bottomRight: Radius.circular(16), ), ), ), child: Text('Update'.tr), ), ), ], ), ], ), ), ), ); }, transitionBuilder: (_, animation, __, child) { return ScaleTransition( scale: CurvedAnimation( parent: animation, curve: Curves.easeOutCubic, // More natural curve ), child: child, ); }, ); } class DeviceHelper { static Future getDeviceFingerprint() async { final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); var deviceData; try { if (Platform.isAndroid) { // Fetch Android-specific device information AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo; deviceData = androidInfo.toMap(); // Convert to a map for easier access // Log.print('deviceData: ${jsonEncode(deviceData)}'); } else if (Platform.isIOS) { // Fetch iOS-specific device information IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo; deviceData = iosInfo.toMap(); // Convert to a map for easier access } else { throw UnsupportedError('Unsupported platform'); } // Extract relevant device information final String deviceId = Platform.isAndroid ? deviceData['androidId'] ?? deviceData['fingerprint'] ?? 'unknown' : deviceData['identifierForVendor'] ?? 'unknown'; final String deviceModel = deviceData['model'] ?? 'unknown'; final String osVersion = Platform.isAndroid ? deviceData['version']['release'] ?? 'unknown' : deviceData['systemVersion'] ?? 'unknown'; // Log the extracted information // Generate and return the encrypted fingerprint final String fingerprint = '${deviceId}_${deviceModel}_$osVersion'; // Log.print('fingerprint: ${fingerprint}'); // print(EncryptionHelper.instance.encryptData(fingerprint)); return (fingerprint); } catch (e) { throw Exception('Failed to generate device fingerprint'); } } } class SecurityHelper { /// Performs security checks and handles potential risks static Future performSecurityChecks() async { bool isNotTrust = false; bool isJailBroken = false; bool isRealDevice = true; bool isOnExternalStorage = false; bool checkForIssues = false; bool isDevMode = false; bool isTampered = false; String bundleId = ""; try { isNotTrust = await JailbreakRootDetection.instance.isNotTrust; isJailBroken = await JailbreakRootDetection.instance.isJailBroken; isRealDevice = await JailbreakRootDetection.instance.isRealDevice; isOnExternalStorage = await JailbreakRootDetection.instance.isOnExternalStorage; List issues = await JailbreakRootDetection.instance.checkForIssues; checkForIssues = issues.isNotEmpty; isDevMode = await JailbreakRootDetection.instance.isDevMode; // Get Bundle ID PackageInfo packageInfo = await PackageInfo.fromPlatform(); bundleId = packageInfo.packageName; if (bundleId.isNotEmpty) { // Pass the CORRECT bundle ID to isTampered isTampered = await JailbreakRootDetection.instance.isTampered(bundleId); } } catch (e) { debugPrint("Error during security checks: $e"); // Consider handling specific exceptions, not just general errors. } // Save values to storage (using GetStorage) await box.write('isNotTrust', isNotTrust); // Use await for write operations await box.write('isTampered', isTampered); // Use await await box.write('isJailBroken', isJailBroken); // Use await // debugPrint("Security Check Results:"); // debugPrint("isNotTrust: $isNotTrust"); // debugPrint("isJailBroken: $isJailBroken"); // debugPrint("isRealDevice: $isRealDevice"); // debugPrint("isOnExternalStorage: $isOnExternalStorage"); // debugPrint("checkForIssues: $checkForIssues"); // debugPrint("isDevMode: $isDevMode"); // debugPrint("isTampered: $isTampered"); // debugPrint("Bundle ID: $bundleId"); // Print the bundle ID // Check for security risks and potentially show a warning if (isJailBroken || isRealDevice == false || isTampered) { // print("security_warning".tr); //using easy_localization // Use a more robust approach to show a warning, like a dialog: _showSecurityWarning(); } } /// Deletes all app data static Future clearAllData() async { //await storage.deleteAll(); // What's 'storage'? Be specific. Likely GetStorage as well. await box.erase(); // Clear GetStorage data exit(0); // This will terminate the app. Be VERY careful with this. } // static void _showSecurityWarning() { // // Show a dialog, navigate to an error screen, etc. // // Example using Get.dialog (if you use GetX): // // Get.dialog( // AlertDialog( // title: Text("Security Warning".tr), // Or use localized string // content: Text( // "Potential security risks detected. The application may not function correctly." // .tr), //Or use localized string // actions: [ // TextButton( // onPressed: () async { // await storage.deleteAll(); // await box.erase(); // Get.back(); // Close the dialog // // Or, if you really must, exit the app (but give the user a chance!) // exit(0); // }, // child: Text("OK"), // Or use a localized string // ), // ], // ), // barrierDismissible: false, // Prevent closing by tapping outside // ); // } static void _showSecurityWarning() { // Use an RxInt to track the remaining seconds. This is the KEY! RxInt secondsRemaining = 10.obs; Get.dialog( CupertinoAlertDialog( title: Text("Security Warning".tr), content: Column( mainAxisSize: MainAxisSize.min, children: [ Obx(() => Text( "Potential security risks detected. The application will close in @seconds seconds." .trParams({ // Use trParams for placeholders 'seconds': secondsRemaining.value.toString(), }), // Wrap the Text widget in Obx )), SizedBox(height: 24), // More spacing before the progress bar Obx(() => SizedBox( width: double.infinity, // Make progress bar full width child: CupertinoActivityIndicator( // in case of loading radius: 15, animating: true, ))), SizedBox(height: 8), Obx(() => ClipRRect( borderRadius: BorderRadius.circular(8), // Rounded corners child: LinearProgressIndicator( value: secondsRemaining.value / 10, backgroundColor: Colors.grey.shade300, // Lighter background valueColor: AlwaysStoppedAnimation( CupertinoColors.systemRed), // iOS-style red minHeight: 8, // Slightly thicker progress bar ), )), ], ), ), barrierDismissible: false, ); Timer.periodic(Duration(seconds: 1), (timer) { secondsRemaining.value--; if (secondsRemaining.value <= 0) { timer.cancel(); // Get.back(); _clearDataAndExit(); } }); } static Future _clearDataAndExit() async { await storage.deleteAll(); await box.erase(); exit(0); // Exit the app print('exit'); } } ================================================== FILE PATH: ./lib/controller/functions/network/connection_check.dart ================================================== import 'dart:async'; import 'dart:io'; import 'package:http/http.dart' as http; import 'net_guard.dart'; typedef BodyEncoder = Future Function(); class HttpRetry { /// ريتراي لـ network/transient errors فقط. static Future sendWithRetry( BodyEncoder send, { int maxRetries = 3, Duration baseDelay = const Duration(milliseconds: 400), Duration timeout = const Duration(seconds: 12), }) async { // ✅ Pre-flight check for internet connection if (!await NetGuard().hasInternet()) { // Immediately throw a specific exception if there's no internet. // This avoids pointless retries. throw const SocketException("No internet connection"); } int attempt = 0; while (true) { attempt++; try { final res = await send().timeout(timeout); return res; } on TimeoutException catch (_) { if (attempt >= maxRetries) rethrow; } on SocketException catch (_) { if (attempt >= maxRetries) rethrow; } on HandshakeException catch (_) { if (attempt >= maxRetries) rethrow; } on http.ClientException catch (e) { // مثال: Connection reset by peer final msg = e.message.toLowerCase(); final transient = msg.contains('connection reset') || msg.contains('broken pipe') || msg.contains('timed out'); if (!transient || attempt >= maxRetries) rethrow; } // backoff: 0.4s, 0.8s, 1.6s final delay = baseDelay * (1 << (attempt - 1)); await Future.delayed(delay); } } } ================================================== FILE PATH: ./lib/controller/functions/network/net_guard.dart ================================================== import 'dart:async'; import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; class NetGuard { static final NetGuard _i = NetGuard._(); NetGuard._(); factory NetGuard() => _i; bool _notified = false; /// فحص: (أ) فيه شبكة؟ (ب) فيه انترنت؟ (ج) السيرفر نفسه reachable؟ Future hasInternet({Uri? mustReach}) async { final connectivity = await Connectivity().checkConnectivity(); if (connectivity == ConnectivityResult.none) return false; final hasNet = await InternetConnectionChecker.createInstance().hasConnection; if (!hasNet) return false; if (mustReach != null) { try { final host = mustReach.host; final result = await InternetAddress.lookup(host); if (result.isEmpty || result.first.rawAddress.isEmpty) return false; // اختباري خفيف عبر TCP (80/443) — 400ms timeout final port = mustReach.scheme == 'http' ? 80 : 443; final socket = await Socket.connect(host, port, timeout: const Duration(milliseconds: 400)); socket.destroy(); } catch (_) { return false; } } return true; } /// إظهار إشعار مرة واحدة ثم إسكات التكرارات void notifyOnce(void Function(String title, String msg) show) { if (_notified) return; _notified = true; show('لا يوجد اتصال بالإنترنت', 'تحقق من الشبكة ثم حاول مجددًا.'); // إعادة السماح بعد 15 ثانية Future.delayed(const Duration(seconds: 15), () => _notified = false); } } ================================================== FILE PATH: ./lib/controller/themes/themes.dart ================================================== import 'package:flutter/material.dart'; import 'package:sefer_driver/constant/style.dart'; import '../../constant/colors.dart'; ThemeData lightThemeEnglish = ThemeData( brightness: Brightness.light, fontFamily: "SFPro", textTheme: TextTheme( displaySmall: AppStyle.title, displayLarge: AppStyle.headTitle, displayMedium: AppStyle.headTitle2, bodyLarge: AppStyle.title, bodyMedium: AppStyle.subtitle, ), primarySwatch: Colors.blue, dialogTheme: DialogThemeData( backgroundColor: AppColor.secondaryColor, contentTextStyle: AppStyle.title, titleTextStyle: AppStyle.headTitle2, ), appBarTheme: AppBarTheme( elevation: 0, color: AppColor.secondaryColor, centerTitle: true, iconTheme: const IconThemeData( color: AppColor.primaryColor, ), toolbarTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).bodyMedium, titleTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).titleLarge, ), ); ThemeData darkThemeEnglish = ThemeData( brightness: Brightness.dark, fontFamily: "SFPro", textTheme: TextTheme( displaySmall: AppStyle.title, displayLarge: AppStyle.headTitle, displayMedium: AppStyle.headTitle2, bodyLarge: AppStyle.title, bodyMedium: AppStyle.subtitle, ), primarySwatch: Colors.blue, dialogTheme: DialogThemeData( backgroundColor: AppColor.secondaryColor, contentTextStyle: AppStyle.title, titleTextStyle: AppStyle.headTitle2, ), appBarTheme: AppBarTheme( elevation: 0, color: AppColor.secondaryColor, centerTitle: true, iconTheme: const IconThemeData( color: AppColor.primaryColor, ), toolbarTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).bodyMedium, titleTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).titleLarge, ), ); ThemeData lightThemeArabic = ThemeData( brightness: Brightness.light, fontFamily: 'SFArabic', textTheme: TextTheme( displaySmall: AppStyle.title, displayLarge: AppStyle.headTitle, displayMedium: AppStyle.headTitle2, bodyLarge: AppStyle.title, bodyMedium: AppStyle.subtitle, ), primarySwatch: Colors.blue, dialogTheme: DialogThemeData( backgroundColor: AppColor.secondaryColor, contentTextStyle: AppStyle.title, titleTextStyle: AppStyle.headTitle2, ), appBarTheme: AppBarTheme( elevation: 0, color: AppColor.secondaryColor, centerTitle: true, iconTheme: const IconThemeData( color: AppColor.primaryColor, ), toolbarTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).bodyMedium, titleTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).titleLarge, ), ); ThemeData darkThemeArabic = ThemeData( brightness: Brightness.dark, fontFamily: 'SFArabic', textTheme: TextTheme( displaySmall: AppStyle.title, displayLarge: AppStyle.headTitle, displayMedium: AppStyle.headTitle2, bodyLarge: AppStyle.title, bodyMedium: AppStyle.subtitle, ), primarySwatch: Colors.blue, dialogTheme: DialogThemeData( backgroundColor: AppColor.secondaryColor, contentTextStyle: AppStyle.title, titleTextStyle: AppStyle.headTitle2, ), appBarTheme: AppBarTheme( elevation: 0, color: AppColor.secondaryColor, centerTitle: true, iconTheme: const IconThemeData( color: AppColor.primaryColor, ), toolbarTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).bodyMedium, titleTextStyle: TextTheme( titleSmall: AppStyle.subtitle, headlineSmall: AppStyle.title, titleLarge: AppStyle.headTitle2, ).titleLarge, ), ); ================================================== FILE PATH: ./lib/env/env.dart ================================================== import 'package:envied/envied.dart'; part 'env.g.dart'; @Envied() abstract class Env { @EnviedField(varName: 'basicAuthCredentials', obfuscate: true) static final String basicAuthCredentials = _Env.basicAuthCredentials; @EnviedField(varName: 'mapKeyOsm', obfuscate: true) static final String mapKeyOsm = _Env.mapKeyOsm; @EnviedField(varName: 'mapAPIKEYIOS', obfuscate: true) static final String mapAPIKEYIOS = _Env.mapAPIKEYIOS; @EnviedField(varName: 'email', obfuscate: true) static final String email = _Env.email; @EnviedField(varName: 'basicCompareFaces', obfuscate: true) static final String basicCompareFaces = _Env.basicCompareFaces; // @EnviedField(varName: 'getapiKey', obfuscate: true) // static final String getapiKey = _Env.getapiKey; @EnviedField(varName: 'basicCompareFacesURL', obfuscate: true) static final String basicCompareFacesURL = _Env.basicCompareFacesURL; @EnviedField(varName: 'accountSIDTwillo', obfuscate: true) static final String accountSIDTwillo = _Env.accountSIDTwillo; @EnviedField(varName: 'serverAPI', obfuscate: true) static final String serverAPI = _Env.serverAPI; @EnviedField(varName: 'mapAPIKEY', obfuscate: true) static final String mapAPIKEY = _Env.mapAPIKEY; @EnviedField(varName: 'twilloRecoveryCode', obfuscate: true) static final String twilloRecoveryCode = _Env.twilloRecoveryCode; @EnviedField(varName: 'authTokenTwillo', obfuscate: true) static final String authTokenTwillo = _Env.authTokenTwillo; @EnviedField(varName: 'chatGPTkey', obfuscate: true) static final String chatGPTkey = _Env.chatGPTkey; @EnviedField(varName: 'transactionCloude', obfuscate: true) static final String transactionCloude = _Env.transactionCloude; @EnviedField(varName: 'visionApi', obfuscate: true) static final String visionApi = _Env.visionApi; @EnviedField(varName: 'secretKey', obfuscate: true) static final String secretKey = _Env.secretKey; @EnviedField(varName: 'stripe_publishableKe', obfuscate: true) static final String stripePublishableKe = _Env.stripePublishableKe; @EnviedField(varName: 'chatGPTkeySefer', obfuscate: true) static final String chatGPTkeySefer = _Env.chatGPTkeySefer; @EnviedField(varName: 'llamaKey', obfuscate: true) static final String llamaKey = _Env.llamaKey; @EnviedField(varName: 'serverPHP', obfuscate: true) static final String serverPHP = _Env.serverPHP; @EnviedField( varName: 'anthropicAIkeySeferNewHamzaayedpython', obfuscate: true) static final String anthropicAIkeySeferNewHamzaayedpython = _Env.anthropicAIkeySeferNewHamzaayedpython; @EnviedField(varName: 'privateKeyFCM', obfuscate: true) static final String privateKeyFCM = _Env.privateKeyFCM; @EnviedField(varName: 'seferAlexandriaServer', obfuscate: true) static final String seferAlexandriaServer = _Env.seferAlexandriaServer; @EnviedField(varName: 'seferPaymentServer', obfuscate: true) static final String seferPaymentServer = _Env.seferPaymentServer; @EnviedField(varName: 'seferCairoServer', obfuscate: true) static final String seferCairoServer = _Env.seferCairoServer; @EnviedField(varName: 'seferGizaServer', obfuscate: true) static final String seferGizaServer = _Env.seferGizaServer; @EnviedField(varName: 'chatGPTkeySeferNew', obfuscate: true) static final String chatGPTkeySeferNew = _Env.chatGPTkeySeferNew; @EnviedField(varName: 'cohere', obfuscate: true) static final String cohere = _Env.cohere; @EnviedField(varName: 'claudeAiAPI', obfuscate: true) static final String claudeAiAPI = _Env.claudeAiAPI; @EnviedField(varName: 'payPalClientId', obfuscate: true) static final String payPalClientId = _Env.payPalClientId; @EnviedField(varName: 'payPalSecret', obfuscate: true) static final String payPalSecret = _Env.payPalSecret; @EnviedField(varName: 'geminiApi', obfuscate: true) static final String geminiApi = _Env.geminiApi; @EnviedField(varName: 'geminiApiMasa', obfuscate: true) static final String geminiApiMasa = _Env.geminiApiMasa; @EnviedField(varName: 'agoraAppId', obfuscate: true) static final String agoraAppId = _Env.agoraAppId; @EnviedField(varName: 'agoraAppCertificate', obfuscate: true) static final String agoraAppCertificate = _Env.agoraAppCertificate; @EnviedField(varName: 'payPalClientIdLive', obfuscate: true) static final String payPalClientIdLive = _Env.payPalClientIdLive; @EnviedField(varName: 'payPalSecretLive', obfuscate: true) static final String payPalSecretLive = _Env.payPalSecretLive; @EnviedField(varName: 'integrationIdPayMob', obfuscate: true) static final String integrationIdPayMob = _Env.integrationIdPayMob; @EnviedField(varName: 'passwordPayMob', obfuscate: true) static final String passwordPayMob = _Env.passwordPayMob; @EnviedField(varName: 'usernamePayMob', obfuscate: true) static final String usernamePayMob = _Env.usernamePayMob; @EnviedField(varName: 'payMobApikey', obfuscate: true) static final String payMobApikey = _Env.payMobApikey; @EnviedField(varName: 'integrationIdPayMobWallet', obfuscate: true) static final String integrationIdPayMobWallet = _Env.integrationIdPayMobWallet; @EnviedField(varName: 'smsPasswordEgypt', obfuscate: true) static final String smsPasswordEgypt = _Env.smsPasswordEgypt; @EnviedField(varName: 'ocpApimSubscriptionKey', obfuscate: true) static final String ocpApimSubscriptionKey = _Env.ocpApimSubscriptionKey; @EnviedField(varName: 'chatGPTkeySeferNew4', obfuscate: true) static final String chatGPTkeySeferNew4 = _Env.chatGPTkeySeferNew4; @EnviedField(varName: 'anthropicAIkeySeferNew', obfuscate: true) static final String anthropicAIkeySeferNew = _Env.anthropicAIkeySeferNew; @EnviedField(varName: 'llama3Key', obfuscate: true) static final String llama3Key = _Env.llama3Key; @EnviedField(varName: 'payMobOutPassword', obfuscate: true) static final String payMobOutPassword = _Env.payMobOutPassword; @EnviedField(varName: 'payMobOutUserName', obfuscate: true) static final String payMobOutUserName = _Env.payMobOutUserName; @EnviedField(varName: 'A', obfuscate: true) static final String A = _Env.A; @EnviedField(varName: 'B', obfuscate: true) static final String B = _Env.B; @EnviedField(varName: 'C', obfuscate: true) static final String C = _Env.C; @EnviedField(varName: 'D', obfuscate: true) static final String D = _Env.D; @EnviedField(varName: 'E', obfuscate: true) static final String E = _Env.E; @EnviedField(varName: 'F', obfuscate: true) static final String F = _Env.F; @EnviedField(varName: 'G', obfuscate: true) static final String G = _Env.G; @EnviedField(varName: 'H', obfuscate: true) static final String H = _Env.H; @EnviedField(varName: 'I', obfuscate: true) static final String I = _Env.I; @EnviedField(varName: 'J', obfuscate: true) static final String J = _Env.J; @EnviedField(varName: 'K', obfuscate: true) static final String K = _Env.K; @EnviedField(varName: 'L', obfuscate: true) static final String L = _Env.L; @EnviedField(varName: 'M', obfuscate: true) static final String M = _Env.M; @EnviedField(varName: 'N', obfuscate: true) static final String N = _Env.N; @EnviedField(varName: 'O', obfuscate: true) static final String O = _Env.O; @EnviedField(varName: 'P', obfuscate: true) static final String P = _Env.P; @EnviedField(varName: 'Q', obfuscate: true) static final String Q = _Env.Q; @EnviedField(varName: 'R', obfuscate: true) static final String R = _Env.R; @EnviedField(varName: 'S', obfuscate: true) static final String S = _Env.S; @EnviedField(varName: 'T', obfuscate: true) static final String T = _Env.T; @EnviedField(varName: 'U', obfuscate: true) static final String U = _Env.U; @EnviedField(varName: 'V', obfuscate: true) static final String V = _Env.V; @EnviedField(varName: 'W', obfuscate: true) static final String W = _Env.W; @EnviedField(varName: 'X', obfuscate: true) static final String X = _Env.X; @EnviedField(varName: 'Y', obfuscate: true) static final String Y = _Env.Y; @EnviedField(varName: 'Z', obfuscate: true) static final String Z = _Env.Z; @EnviedField(varName: 'a', obfuscate: true) static final String a = _Env.a; @EnviedField(varName: 'b', obfuscate: true) static final String b = _Env.b; @EnviedField(varName: 'c', obfuscate: true) static final String c = _Env.c; @EnviedField(varName: 'd', obfuscate: true) static final String d = _Env.d; @EnviedField(varName: 'e', obfuscate: true) static final String e = _Env.e; @EnviedField(varName: 'f', obfuscate: true) static final String f = _Env.f; @EnviedField(varName: 'g', obfuscate: true) static final String g = _Env.g; @EnviedField(varName: 'h', obfuscate: true) static final String h = _Env.h; @EnviedField(varName: 'i', obfuscate: true) static final String i = _Env.i; @EnviedField(varName: 'j', obfuscate: true) static final String j = _Env.j; @EnviedField(varName: 'k', obfuscate: true) static final String k = _Env.k; @EnviedField(varName: 'l', obfuscate: true) static final String l = _Env.l; @EnviedField(varName: 'm', obfuscate: true) static final String m = _Env.m; @EnviedField(varName: 'n', obfuscate: true) static final String n = _Env.n; @EnviedField(varName: 'o', obfuscate: true) static final String o = _Env.o; @EnviedField(varName: 'p', obfuscate: true) static final String p = _Env.p; @EnviedField(varName: 'q', obfuscate: true) static final String q = _Env.q; @EnviedField(varName: 'r', obfuscate: true) static final String r = _Env.r; @EnviedField(varName: 's', obfuscate: true) static final String s = _Env.s; @EnviedField(varName: 't', obfuscate: true) static final String t = _Env.t; @EnviedField(varName: 'u', obfuscate: true) static final String u = _Env.u; @EnviedField(varName: 'v', obfuscate: true) static final String v = _Env.v; @EnviedField(varName: 'w', obfuscate: true) static final String w = _Env.w; @EnviedField(varName: 'x', obfuscate: true) static final String x = _Env.x; @EnviedField(varName: 'y', obfuscate: true) static final String y = _Env.y; @EnviedField(varName: 'z', obfuscate: true) static final String z = _Env.z; @EnviedField(varName: 'keyOfApp', obfuscate: true) static final String keyOfApp = _Env.keyOfApp; @EnviedField(varName: 'initializationVector', obfuscate: true) static final String initializationVector = _Env.initializationVector; @EnviedField(varName: 'emailService', obfuscate: true) static final String emailService = _Env.emailService; @EnviedField(varName: 'sss_encryptionSalt', obfuscate: true) static final String sss_encryptionSalt = _Env.sss_encryptionSalt; @EnviedField(varName: 'sss_pass', obfuscate: true) static final String sss_pass = _Env.sss_pass; @EnviedField(varName: 'addd', obfuscate: true) static final String addd = _Env.addd; @EnviedField(varName: 'passnpassenger', obfuscate: true) static final String passnpassenger = _Env.passnpassenger; @EnviedField(varName: 'newId', obfuscate: true) static final String newId = _Env.newId; @EnviedField(varName: 'allowed', obfuscate: true) static final String allowed = _Env.allowed; @EnviedField(varName: 'allowedWallet', obfuscate: true) static final String allowedWallet = _Env.allowedWallet; } ================================================== FILE PATH: ./lib/env/env.g.dart ================================================== // GENERATED CODE - DO NOT MODIFY BY HAND part of 'env.dart'; // ************************************************************************** // EnviedGenerator // ************************************************************************** // coverage:ignore-file // ignore_for_file: type=lint // generated_from: .env final class _Env { static const List _enviedkeybasicAuthCredentials = [ 3119662252, 308341763, 2015166535, 3074198305, 3116745311, 1299432569, 3498707833, 1419509341, 1523398991, 134223789, 1804990251, 914766455, 143847418, 1072907411, 2552437356, 183644249, 2324763500, 2016445316, 3005673044, 3914070117, 2510335365, 219328798, 1940125228, 3171255662, 3215469540, 1508139915, 3409555914, 700823808, 1883137536, 1425916503, 586193771, ]; static const List _envieddatabasicAuthCredentials = [ 3119662299, 308341874, 2015166505, 3074198348, 3116745262, 1299432456, 3498707722, 1419509303, 1523398966, 134223835, 1804990300, 914766365, 143847308, 1072907433, 2552437250, 183644200, 2324763422, 2016445405, 3005672990, 3914070069, 2510335429, 219328815, 1940125211, 3171255645, 3215469523, 1508139987, 3409555896, 700823896, 1883137644, 1425916437, 586193671, ]; static final String basicAuthCredentials = String.fromCharCodes( List.generate( _envieddatabasicAuthCredentials.length, (int i) => i, growable: false, ).map((int i) => _envieddatabasicAuthCredentials[i] ^ _enviedkeybasicAuthCredentials[i])); static const List _enviedkeymapKeyOsm = [ 1061947572, 1154666970, 1788134034, 3441878628, 4093708564, 2488457761, 3745638123, 3197059312, 721782794, 1906372427, 673202838, 3487712682, 3536566818, 748259304, 2578078811, 896175043, 2615577190, 1895427507, 908404633, 3711829356, ]; static const List _envieddatamapKeyOsm = [ 1061947609, 1154666939, 1788134142, 3441878528, 4093708657, 2488457815, 3745638059, 3197059202, 721782885, 1906372414, 673202914, 3487712719, 3536566799, 748259212, 2578078772, 896175023, 2615577098, 1895427538, 908404715, 3711829279, ]; static final String mapKeyOsm = String.fromCharCodes(List.generate( _envieddatamapKeyOsm.length, (int i) => i, growable: false, ).map((int i) => _envieddatamapKeyOsm[i] ^ _enviedkeymapKeyOsm[i])); static const List _enviedkeymapAPIKEYIOS = [ 2151695670, 1054308886, 1870950936, 88263793, 4089069531, 3499077188, 3476458014, 3168336394, 2909695516, 4260265062, 91281871, 2357498250, 1465939768, 3162694029, 2677109738, 15978042, 3254043132, 218012237, 2437645091, 2891409295, 31581396, 277277467, 3709929938, 4286881507, 819136536, 172598488, 2414274591, 3522656593, 1841701930, 2616372343, 2715457719, 570092248, 3920129267, 2496493162, 4138678271, 3433391998, 939132383, 3897546811, 2677079369, ]; static const List _envieddatamapAPIKEYIOS = [ 2151695735, 1054308959, 1870951010, 88263696, 4089069448, 3499077181, 3476458074, 3168336494, 2909695597, 4260264973, 91281795, 2357498311, 1465939835, 3162694143, 2677109659, 15978064, 3254043050, 218012223, 2437645133, 2891409336, 31581324, 277277558, 3709929907, 4286881415, 819136593, 172598441, 2414274662, 3522656575, 1841701971, 2616372248, 2715457781, 570092217, 3920129220, 2496493114, 4138678221, 3433391945, 939132304, 3897546846, 2677079300, ]; static final String mapAPIKEYIOS = String.fromCharCodes(List.generate( _envieddatamapAPIKEYIOS.length, (int i) => i, growable: false, ).map((int i) => _envieddatamapAPIKEYIOS[i] ^ _enviedkeymapAPIKEYIOS[i])); static const List _enviedkeyemail = [ 2147741481, 3022601776, 627913709, 1413637414, 2903845769, 3930413881, 1191268173, 10965538, 598619137, 3142526324, 3745702052, 4136725053, 645579098, 2625103278, 60371886, ]; static const List _envieddataemail = [ 2147741545, 3022601817, 627913603, 1413637458, 2903845864, 3930413909, 1191268136, 10965587, 598619232, 3142526212, 3745702100, 4136725011, 645579065, 2625103297, 60371907, ]; static final String email = String.fromCharCodes(List.generate( _envieddataemail.length, (int i) => i, growable: false, ).map((int i) => _envieddataemail[i] ^ _enviedkeyemail[i])); static const List _enviedkeybasicCompareFaces = [ 2296343195, 3793709033, 3210279611, 1382972713, 2835826086, 3832217435, 2156224674, 3937478928, 3462847201, 2788598618, 125364131, 1409664400, 3732768056, 2966368179, 3018233973, 4115898929, 2270981991, 1746945700, 2357950794, 2815430643, 1906731934, 2478074234, 162304442, 975875308, 3384793524, 2071543057, 2278014588, 356216334, ]; static const List _envieddatabasicCompareFaces = [ 2296343265, 3793708931, 3210279630, 1382972739, 2835826122, 3832217390, 2156224723, 3937479030, 3462847121, 2788598576, 125364121, 1409664510, 3732768073, 2966368193, 3018233900, 4115898971, 2270981911, 1746945764, 2357950843, 2815430596, 1906731949, 2478074189, 162304482, 975875230, 3384793580, 2071543165, 2278014526, 356216418, ]; static final String basicCompareFaces = String.fromCharCodes( List.generate( _envieddatabasicCompareFaces.length, (int i) => i, growable: false, ).map((int i) => _envieddatabasicCompareFaces[i] ^ _enviedkeybasicCompareFaces[i])); static const List _enviedkeybasicCompareFacesURL = [ 3220389880, 1896092538, 3417329582, 3357206126, 441079354, 2518376273, 3594693806, 3874086501, 1406926161, 1376676982, 2858004954, 3740036395, 2372915802, 3729233843, 3036425821, 4094260731, 735548888, 1065243742, 2676762486, 2506900532, 155001808, 2207687783, 3288666464, 3285691569, 2353472176, 1047162643, 961443648, 2756212231, 2296500208, 276303533, 578074949, 1168642108, 2942379661, 3490271822, 384214389, 270731729, 3394813339, 895915516, 3882278717, 1629572933, 3416911057, 1915184088, 3257220882, 818616196, 3018470266, 4178652202, 197820745, 3699620454, 360071303, 1575552250, 1325150033, 2257081226, 349100155, 3414562195, 3728569996, 1634090533, 812808253, 2152104178, 278583218, 3758430418, ]; static const List _envieddatabasicCompareFacesURL = [ 3220389776, 1896092430, 3417329626, 3357206046, 441079369, 2518376299, 3594693761, 3874086474, 1406926135, 1376676887, 2858004921, 3740036430, 2372915831, 3729233879, 3036425784, 4094260623, 735548861, 1065243709, 2676762370, 2506900505, 155001782, 2207687761, 3288666457, 3285691523, 2353472132, 1047162656, 961443705, 2756212277, 2296500115, 276303513, 578074918, 1168642059, 2942379683, 3490271782, 384214288, 270731683, 3394813428, 895915415, 3882278728, 1629572900, 3416911009, 1915184040, 3257220924, 818616295, 3018470165, 4178652231, 197820774, 3699620357, 360071400, 1575552151, 1325149985, 2257081323, 349100041, 3414562294, 3728570067, 1634090563, 812808284, 2152104081, 278583255, 3758430369, ]; static final String basicCompareFacesURL = String.fromCharCodes( List.generate( _envieddatabasicCompareFacesURL.length, (int i) => i, growable: false, ).map((int i) => _envieddatabasicCompareFacesURL[i] ^ _enviedkeybasicCompareFacesURL[i])); static const List _enviedkeyaccountSIDTwillo = [ 2934490457, 3936142346, 881081269, 1663353371, 921098405, 4272650692, 321567310, 1386434013, 163841393, 3889058183, 137435408, 4232722058, 868241344, 73821594, 1530947120, 2076743619, 4167846303, 4193048880, 522420519, 2015502862, 1500940268, 2086238974, 3838402101, 3109767109, 1200865270, 3819869314, 686415089, 262105312, 1510999968, 3754501979, 2384065386, 1622954290, 2430377995, 3917284516, 3696201508, 1616091150, 4120537433, 261073639, 2271794810, 964848725, 1988507286, ]; static const List _envieddataaccountSIDTwillo = [ 2934490376, 3936142412, 881081293, 1663353387, 921098452, 4272650685, 321567354, 1386434024, 163841351, 3889058285, 137435493, 4232722144, 868241395, 73821602, 1530947075, 2076743597, 4167846310, 4193048904, 522420562, 2015502967, 1500940254, 2086238927, 3838402060, 3109767153, 1200865159, 3819869364, 686415043, 262105305, 1511000017, 3754501994, 2384065292, 1622954328, 2430378043, 3917284573, 3696201491, 1616091222, 4120537387, 261073599, 2271794710, 964848663, 1988507386, ]; static final String accountSIDTwillo = String.fromCharCodes( List.generate( _envieddataaccountSIDTwillo.length, (int i) => i, growable: false, ).map((int i) => _envieddataaccountSIDTwillo[i] ^ _enviedkeyaccountSIDTwillo[i])); static const List _enviedkeyserverAPI = [ 1640356061, 1109713156, 2676970884, 2982808124, 1196683320, 399162653, 2690719682, 561644024, 3698357235, 1971775398, 1362089888, 4098281206, 486435093, 585479448, 3818661702, 2914085612, 2833995326, 2692526444, 742619015, 3883726605, 159594704, 2309127406, 3071231165, 3378547787, 3529813488, 32472595, 2216397977, 4065490337, 512551596, 1762705486, 1312444727, 4004186931, 1195867106, 1348768429, 2659874408, 3475793726, 713263331, 4053902124, 758986971, 3922301125, 112346051, 2139879761, 3257242346, 3783957319, 4081680390, 1145172966, 536303801, 2395235213, 2439144280, 4194487110, 738798915, 714005630, 2227714079, 490748580, 3967642326, 1335235689, 3716697848, 3469220326, 2049368821, 1222309652, 396757610, 2968901244, 3259975456, 911418890, 1511077843, 2132052817, 2163537371, 2156825771, 125152325, 1561751260, 1215688927, 2337973320, 3930935933, 3511774723, 1393568631, 2897632439, 2748168494, 1456172952, 3811164034, 2754770638, 3017984324, 775114840, 868207674, 3891231838, 401111215, 3564618284, 3968379529, 642347579, 1486887337, 2340292518, 2747818257, 3203274707, 2116091974, 3431377939, 3119843715, 782479150, 2682645724, 541595749, 1473082883, 3224408816, 2484627503, 735549272, 708450675, 3539721658, 4199367853, 3417820545, 3923134626, 3216841440, 1932051787, 3967046873, 2641958581, 812947720, 3256507827, 2572765859, 3748554398, 1401083577, 3309283985, 2574584580, 3546476886, 953866243, 2030531099, 2826460289, 3466363490, 1508488521, 1201071975, 4112225860, 401188585, 3688992142, 1824033041, 1930822798, 1676220458, 2359239267, 3753171603, 1244067415, 4092764634, 4087602641, 3996943514, 571326231, 579542552, 855778328, 1093105414, 3867656545, 3362611777, 4176204033, 2521927795, 2975541729, 586837626, 1908427057, 2733255700, 1747354993, 2588114028, 726159856, 1382633340, 2516901742, 4034529237, 1689757631, 3013787146, 3644603595, ]; static const List _envieddataserverAPI = [ 1640355980, 1109713237, 2676970965, 2982808173, 1196683351, 399162751, 2690719633, 561643914, 3698357121, 1971775456, 1362089929, 4098281164, 486435140, 585479502, 3818661655, 2914085588, 2833995273, 2692526356, 742619090, 3883726650, 159594666, 2309127321, 3071231230, 3378547773, 3529813405, 32472649, 2216398051, 4065490427, 512551624, 1762705455, 1312444751, 4004186950, 1195867057, 1348768415, 2659874318, 3475793676, 713263312, 4053902197, 758986991, 3922301096, 112346041, 2139879782, 3257242279, 3783957309, 4081680511, 1145172905, 536303811, 2395235327, 2439144288, 4194487081, 738798887, 714005580, 2227714173, 490748630, 3967642336, 1335235618, 3716697761, 3469220255, 2049368720, 1222309714, 396757515, 2968901160, 3259975542, 911418950, 1511077780, 2132052834, 2163537296, 2156825752, 125152301, 1561751204, 1215688938, 2337973266, 3930935836, 3511774806, 1393568526, 2897632463, 2748168473, 1456173053, 3811164123, 2754770616, 3017984261, 775114753, 868207690, 3891231775, 401111289, 3564618312, 3968379586, 642347600, 1486887300, 2340292500, 2747818281, 3203274725, 2116091912, 3431377991, 3119843793, 782479175, 2682645743, 541595679, 1473082992, 3224408777, 2484627526, 735549195, 708450620, 3539721684, 4199367925, 3417820661, 3923134714, 3216841394, 1932051714, 3967046817, 2641958598, 812947839, 3256507860, 2572765840, 3748554453, 1401083612, 3309284082, 2574584646, 3546476859, 953866352, 2030531191, 2826460338, 3466363444, 1508488497, 1201071917, 4112225917, 401188510, 3688992193, 1824033084, 1930822904, 1676220515, 2359239187, 3753171684, 1244067362, 4092764654, 4087602561, 3996943596, 571326240, 579542652, 855778419, 1093105486, 3867656458, 3362611737, 4176204143, 2521927706, 2975541652, 586837506, 1908427132, 2733255751, 1747354933, 2588113931, 726159783, 1382633252, 2516901660, 4034529165, 1689757651, 3013787208, 3644603559, ]; static final String serverAPI = String.fromCharCodes(List.generate( _envieddataserverAPI.length, (int i) => i, growable: false, ).map((int i) => _envieddataserverAPI[i] ^ _enviedkeyserverAPI[i])); static const List _enviedkeymapAPIKEY = [ 3080424818, 2739058472, 3527425257, 4028529921, 1883553841, 1686420418, 489737912, 1701158226, 2467593300, 3324064773, 365079787, 2661728615, 2797847661, 2685221719, 411361949, 2671840178, 12215258, 2982665395, 3589247556, 80296077, 1358410178, 3014948061, 2896599606, 3486123033, 2777191306, 1549359348, 2947230529, 4267926550, 879333647, 4285596424, 1014258202, 940770413, 1440464234, 620322144, 599361912, 4026766772, 3024895214, 1093526381, 3971290375, ]; static const List _envieddatamapAPIKEY = [ 3080424755, 2739058529, 3527425171, 4028530016, 1883553890, 1686420411, 489737977, 1701158146, 2467593234, 3324064855, 365079732, 2661728575, 2797847567, 2685221637, 411362003, 2671840130, 12215170, 2982665449, 3589247601, 80296132, 1358410168, 3014948078, 2896599671, 3486123072, 2777191374, 1549359262, 2947230479, 4267926607, 879333703, 4285596495, 1014258256, 940770346, 1440464216, 620322067, 599361866, 4026766821, 3024895161, 1093526298, 3971290442, ]; static final String mapAPIKEY = String.fromCharCodes(List.generate( _envieddatamapAPIKEY.length, (int i) => i, growable: false, ).map((int i) => _envieddatamapAPIKEY[i] ^ _enviedkeymapAPIKEY[i])); static const List _enviedkeytwilloRecoveryCode = [ 2045483171, 1182855780, 789386213, 2002339966, 1656705048, 1862766833, 4101318183, 2476323453, 2245393184, 1936324598, 2108788169, 2271316230, 1418427378, 4094204263, 58396875, 1445429874, 1494352246, 3012324438, 203234924, 397956565, 1514286967, 1622482287, 3599184681, 980425767, 3151431159, 2063433465, 908361499, 4225441140, 1469950094, 3208438559, 2343271325, ]; static const List _envieddatatwilloRecoveryCode = [ 2045483232, 1182855717, 789386160, 2002339913, 1656705057, 1862766773, 4101318255, 2476323373, 2245393256, 1936324551, 2108788107, 2271316332, 1418427319, 4094204254, 58396827, 1445429799, 1494352190, 3012324450, 203234857, 397956481, 1514286895, 1622482235, 3599184762, 980425855, 3151431085, 2063433377, 908361577, 4225441068, 1469950178, 3208438621, 2343271409, ]; static final String twilloRecoveryCode = String.fromCharCodes( List.generate( _envieddatatwilloRecoveryCode.length, (int i) => i, growable: false, ).map((int i) => _envieddatatwilloRecoveryCode[i] ^ _enviedkeytwilloRecoveryCode[i])); static const List _enviedkeyauthTokenTwillo = [ 3482227581, 931939927, 1043129482, 3651497893, 532948387, 2286803814, 4189381494, 2810745320, 3305770584, 2455427241, 895508588, 2922817994, 715264306, 1709934147, 3600880978, 4274898682, 2817920337, 2978402175, 2746255354, 3739040319, 2762965271, 1667025470, 3382353026, 1539265897, 355746883, 3336334498, 3174964404, 2584604919, 4169347029, 2269664299, 2940650629, 1088566567, 839701275, 1983247534, 3984233019, 1145706096, 192818443, 2770233437, 2346198292, ]; static const List _envieddataauthTokenTwillo = [ 3482227530, 931939943, 1043129599, 3651497884, 532948379, 2286803724, 4189381379, 2810745304, 3305770602, 2455427224, 895508568, 2922817957, 715264330, 1709934139, 3600880998, 4274898571, 2817920353, 2978402058, 2746255309, 3739040267, 2762965287, 1667025420, 3382353082, 1539265820, 355746931, 3336334480, 3174964357, 2584604802, 4169347041, 2269664346, 2940650736, 1088566545, 839701294, 1983247606, 3984233033, 1145706024, 192818535, 2770233375, 2346198392, ]; static final String authTokenTwillo = String.fromCharCodes(List.generate( _envieddataauthTokenTwillo.length, (int i) => i, growable: false, ).map( (int i) => _envieddataauthTokenTwillo[i] ^ _enviedkeyauthTokenTwillo[i])); static const List _enviedkeychatGPTkey = [ 2771437346, 520392228, 3663326768, 1645768977, 1163429156, 1332493464, 3598252631, 363261562, 2321683879, 663590875, 1656338901, 3309075479, 3744732575, 2782197588, 3478826385, 34811558, 316875771, 2013774969, 2910176781, 3146637031, 1743630880, 2608270501, 507919069, 4269764979, 4163537191, 151793743, 202848436, 289901185, 927058643, 1770573204, 2777887954, 3308649974, 1276086820, 2836951186, 2198314295, 655629671, 1738057797, 698775614, 777256559, 374793617, 1221262936, 3207140318, 3036584754, 3677920304, 1426187892, 2064482478, 513295986, 3751814446, 1434605073, 3443454051, 2241274417, 536759710, 4098711781, 920085498, 252649970, 3968748446, 3641155398, 2485992921, ]; static const List _envieddatachatGPTkey = [ 2771437400, 520392259, 3663326749, 1645768997, 1163429223, 1332493482, 3598252641, 363261451, 2321683859, 663590792, 1656338828, 3309075568, 3744732637, 2782197535, 3478826432, 34811587, 316875699, 2013774883, 2910176841, 3146636950, 1743630923, 2608270578, 507919026, 4269764868, 4163537252, 151793782, 202848492, 289901299, 927058603, 1770573299, 2777887879, 3308649907, 1276086850, 2836951239, 2198314318, 655629662, 1738057743, 698775660, 777256472, 374793635, 1221262890, 3207140275, 3036584708, 3677920353, 1426187846, 2064482511, 513295894, 3751814476, 1434605090, 3443453960, 2241274459, 536759785, 4098711741, 920085384, 252649898, 3968748530, 3641155332, 2485992885, ]; static final String chatGPTkey = String.fromCharCodes(List.generate( _envieddatachatGPTkey.length, (int i) => i, growable: false, ).map((int i) => _envieddatachatGPTkey[i] ^ _enviedkeychatGPTkey[i])); static const List _enviedkeytransactionCloude = [ 3552601392, 1577423137, 1785973818, 743603516, 3124269689, 797794403, 3058739250, 3584792697, 424230157, 1756658327, 2429369724, 2675777515, 960621346, 1612616501, 4008522179, 991039700, 797221697, 2678498985, 1146920791, 1564426831, 678469585, 2146709224, 4013109938, 3896340821, 2778997782, 116284095, 208397719, 2722575295, 2531240064, 939941651, 3760064637, 3321328165, 2819773733, 817815798, 39775565, 2811546729, 2091663403, 2910821863, 3500288704, 2679091248, 4146668875, 3796689044, 1212250069, 24258362, 4183962457, 3238301856, 1092442450, 1020843765, 708779034, 413156191, 1529829900, 686962193, 1999810608, 3514217656, 2125725207, 1851375082, 2170030285, 4120904511, 2399566823, 4149333102, 2673228079, 3375827762, ]; static const List _envieddatatransactionCloude = [ 3552601441, 1577423177, 1785973849, 743603531, 3124269580, 797794314, 3058739294, 3584792598, 424230240, 1756658406, 2429369631, 2675777412, 960621387, 1612616535, 4008522233, 991039621, 797221655, 2678499046, 1146920712, 1564426757, 678469535, 2146709169, 4013110007, 3896340753, 2778997796, 116284135, 208397760, 2722575358, 2531240114, 939941669, 3760064548, 3321328253, 2819773806, 817815733, 39775615, 2811546685, 2091663483, 2910821853, 3500288665, 2679091323, 4146668922, 3796689104, 1212249987, 24258418, 4183962479, 3238301939, 1092442392, 1020843703, 708779049, 413156206, 1529829954, 686962210, 1999810656, 3514217725, 2125725222, 1851375039, 2170030229, 4120904525, 2399566783, 4149332994, 2673228141, 3375827806, ]; static final String transactionCloude = String.fromCharCodes( List.generate( _envieddatatransactionCloude.length, (int i) => i, growable: false, ).map((int i) => _envieddatatransactionCloude[i] ^ _enviedkeytransactionCloude[i])); static const List _enviedkeyvisionApi = [ 2905951827, 80587575, 1281388165, 3950684786, 4289409921, 2184820693, 1571740250, 3805891557, 713434862, 3590025133, 4097230101, 1465389943, 2350497015, 3922930164, 524989925, 4247347078, 3753788024, 1019255416, 1766417757, 1764121344, 2949306634, 1793124845, 1161986031, 2487865711, 1349627846, 489421602, 1966851008, 1647734264, 88157652, 1286154285, 2617793521, 4115278648, 817289242, 2107847429, 3283281346, 920896462, 56255101, 2646939498, ]; static const List _envieddatavisionApi = [ 2905951840, 80587591, 1281388228, 3950684734, 4289410034, 2184820644, 1571740169, 3805891510, 713434807, 3590025209, 4097230179, 1465389837, 2350496903, 3922930114, 524989916, 4247347159, 3753787981, 1019255358, 1766417680, 1764121417, 2949306733, 1793124751, 1161985941, 2487865605, 1349627777, 489421588, 1966850970, 1647734217, 88157614, 1286154310, 2617793413, 4115278706, 817289282, 2107847543, 3283281306, 920896418, 56255039, 2646939398, ]; static final String visionApi = String.fromCharCodes(List.generate( _envieddatavisionApi.length, (int i) => i, growable: false, ).map((int i) => _envieddatavisionApi[i] ^ _enviedkeyvisionApi[i])); static const List _enviedkeysecretKey = [ 1897247392, 217578396, 3604932159, 1134659259, 2897406193, 1488184280, 4049259204, 3875891087, 3010322606, 37206943, 953252848, 1379133342, 4253178350, 4032636035, 997746907, 3853132720, 3724927095, 1073703566, 1231405363, 416538930, 434334881, 2442654294, 783465678, 1765149931, 1822551630, 595423032, 2686979343, 2427909507, 2842125004, 4281459489, 1212190931, 241073308, 3813032922, 2046681584, 2780216544, 3968784326, 237838622, 2861620158, 689234707, 1176807043, 2544911948, 1550170605, 256897034, 2296414562, 991104958, 3608833136, 2299076404, 81353917, 994449091, 1238016198, 3287199912, 1461535664, 2331982794, 2067282912, 2863702517, 2997467372, 288549004, 3377079802, 2963986104, 1673763312, 2727115833, 1565853359, 4157125833, 205582348, 1565404605, 693909204, 2916827892, 2906500658, 2990833311, 3317096916, 2084150430, 2145739880, 3015638685, 2798791833, 3682972144, 3487457382, 1089095481, 3553867414, 1181926649, 323585577, 3471049767, 4201783155, 3077850870, 920422474, 2631484402, 3142364886, 2789472380, 3256834822, 3892541713, 1623565600, 1675505490, 2620698177, 3673524076, 2080955389, 1065100826, 733588683, 3421102604, 3124094348, 2926088386, 2572020662, 3629847241, 3210685751, 3777869452, 2312883476, 4021833219, 4154438405, 3802083340, 1330722458, 510261681, 1877461401, 2507918858, 3905113533, 1049690152, 679185187, ]; static const List _envieddatasecretKey = [ 1897247450, 217578491, 3604932192, 1134659273, 2897406110, 1488184232, 4049259182, 3875891152, 3010322587, 37206952, 953252793, 1379133431, 4253178264, 4032636085, 997746859, 3853132797, 3724927025, 1073703629, 1231405425, 416538996, 434334928, 2442654309, 783465613, 1765149913, 1822551584, 595422990, 2686979398, 2427909595, 2842124960, 4281459532, 1212190905, 241073381, 3813032881, 2046681472, 2780216472, 3968784258, 237838707, 2861620201, 689234730, 1176807088, 2544911903, 1550170554, 256897081, 2296414484, 991104968, 3608833064, 2299076444, 81353867, 994449147, 1238016147, 3287199977, 1461535625, 2331982750, 2067282901, 2863702451, 2997467299, 288549086, 3377079726, 2963986159, 1673763223, 2727115886, 1565853404, 4157125789, 205582399, 1565404554, 693909127, 2916827776, 2906500729, 2990833388, 3317096859, 2084150478, 2145739788, 3015638762, 2798791901, 3682972052, 3487457301, 1089095488, 3553867438, 1181926536, 323585659, 3471049758, 4201783040, 3077850756, 920422407, 2631484327, 3142364858, 2789472265, 3256834919, 3892541817, 1623565651, 1675505505, 2620698159, 3673524028, 2080955317, 1065100908, 733588652, 3421102670, 3124094445, 2926088433, 2572020613, 3629847229, 3210685808, 3777869543, 2312883501, 4021833267, 4154438515, 3802083418, 1330722479, 510261737, 1877461483, 2507918930, 3905113553, 1049690218, 679185231, ]; static final String secretKey = String.fromCharCodes(List.generate( _envieddatasecretKey.length, (int i) => i, growable: false, ).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i])); static const List _enviedkeystripePublishableKe = [ 3015344029, 1902300912, 3231276264, 2899582852, 3414751774, 3048820708, 2938359758, 788704318, 4294796360, 2325760221, 668283857, 636763806, 3864077179, 3133314794, 4089620169, 3406632403, 3280472031, 2409112535, 2544678424, 1665203319, 3128827340, 1399406648, 3946815802, 2616613898, 3466566726, 2373013996, 4281236182, 2468083411, 2884403903, 1530695097, 805787659, 3042168792, 3182098175, 3184387801, 3301549835, 790709842, 2870468675, 395809535, 2003672118, 1126578281, 1757181511, 4138109188, 1865840234, 1887816887, 2277201416, 1049779176, 1521258483, 3215554434, 2764388761, 3673527134, 3998906571, 2749969736, 2878206854, 2506898070, 176673685, 3294114699, 2214264080, 2548204183, 1871676311, 2391839696, 706643988, 1928371761, 2725799243, 1288130685, 3866430893, 2983353615, 1513235401, 59545031, 2930203308, 4261877461, 3267739874, 4086881993, 1081823367, 2336735749, 1548494954, 592296762, 3720331609, 384751393, 459098903, 512549943, 892921978, 2126169168, 2417982449, 1964779244, 3698771298, 1469035931, 279639423, 1150759396, 1870780507, 1117929296, 1985551080, 1481129344, 2535738267, 2431004158, 864860520, 279233338, 3841579015, 2521511723, 1271814377, 2716214256, 3336718305, 820289748, 3131475527, 3571228207, 1405139317, 3227740614, 3127259714, 2211824789, 190660135, 679540510, 2132032086, 645665395, 2706343520, 3146400746, ]; static const List _envieddatastripePublishableKe = [ 3015344107, 1902300823, 3231276215, 2899582964, 3414751852, 3048820619, 2938359742, 788704340, 4294796311, 2325760232, 668283878, 636763863, 3864077074, 3133314716, 4089620223, 3406632350, 3280471961, 2409112468, 2544678490, 1665203249, 3128827325, 1399406603, 3946815865, 2616613944, 3466566696, 2373013978, 4281236157, 2468083357, 2884403957, 1530695127, 805787729, 3042168730, 3182098054, 3184387727, 3301549885, 790709820, 2870468662, 395809467, 2003672130, 1126578225, 1757181474, 4138109245, 1865840163, 1887816925, 2277201485, 1049779128, 1521258428, 3215554532, 2764388849, 3673527091, 3998906555, 2749969676, 2878206962, 2506898113, 176673784, 3294114815, 2214264099, 2548204250, 1871676379, 2391839618, 706644004, 1928371798, 2725799194, 1288130573, 3866430916, 2983353671, 1513235370, 59544982, 2930203329, 4261877396, 3267739812, 4086881924, 1081823442, 2336735829, 1548494872, 592296800, 3720331578, 384751378, 459098950, 512549982, 892921913, 2126169108, 2417982363, 1964779156, 3698771232, 1469035969, 279639347, 1150759302, 1870780451, 1117929236, 1985551019, 1481129395, 2535738366, 2431004056, 864860432, 279233389, 3841579135, 2521511761, 1271814362, 2716214211, 3336718211, 820289667, 3131475471, 3571228190, 1405139247, 3227740577, 3127259696, 2211824870, 190660223, 679540588, 2132032014, 645665311, 2706343458, 3146400646, ]; static final String stripePublishableKe = String.fromCharCodes( List.generate( _envieddatastripePublishableKe.length, (int i) => i, growable: false, ).map((int i) => _envieddatastripePublishableKe[i] ^ _enviedkeystripePublishableKe[i])); static const List _enviedkeychatGPTkeySefer = [ 2666721791, 2549605422, 2579467960, 3604768194, 3273638864, 885930617, 1987132445, 3241854511, 805847935, 4126852805, 2210634215, 1262082129, 1892203121, 1711688944, 3262797569, 4294135985, 3827018561, 1771201626, 141420954, 2640138975, 1935180514, 2779250386, 684638345, 1626995727, 284017270, 2737802415, 1879894513, 2734217813, 654768309, 3886442942, 126758245, 1339780338, 2443625101, 4214921302, 2061854895, 2097911342, 2193209040, 3322993642, 3998652548, 4252591704, 1140633026, 3935180792, 324913339, 1202656668, 2738325524, 4255410946, 2691216859, 2746573131, 1573515629, 135580712, 3948797874, 2935580630, 2673944223, 1687517458, 688039226, 541852631, 1068385794, 3272172532, ]; static const List _envieddatachatGPTkeySefer = [ 2666721669, 2549605449, 2579467925, 3604768139, 3273638841, 885930539, 1987132462, 3241854534, 805847883, 4126852778, 2210634120, 1262082091, 1892203024, 1711688899, 3262797656, 4294136007, 3827018537, 1771201580, 141421048, 2640138982, 1935180432, 2779250312, 684638434, 1626995774, 284017205, 2737802390, 1879894441, 2734217767, 654768333, 3886442969, 126758192, 1339780279, 2443625149, 4214921274, 2061854871, 2097911364, 2193208962, 3322993592, 3998652638, 4252591658, 1140632970, 3935180690, 324913288, 1202656717, 2738325617, 4255410999, 2691216778, 2746573075, 1573515581, 135580740, 3948797891, 2935580544, 2673944263, 1687517536, 688039266, 541852603, 1068385856, 3272172440, ]; static final String chatGPTkeySefer = String.fromCharCodes(List.generate( _envieddatachatGPTkeySefer.length, (int i) => i, growable: false, ).map( (int i) => _envieddatachatGPTkeySefer[i] ^ _enviedkeychatGPTkeySefer[i])); static const List _enviedkeyllamaKey = [ 3555122118, 2326329705, 750340608, 574845812, 1835686228, 2935056413, 2541063708, 2772965730, 3906373643, 1823426502, 3833446574, 1697064783, 2908303435, 3194041791, 2304244517, 3664178553, 3009453360, 2287906884, 157165288, 1156046268, 2714638844, 3449002222, 3067331485, 1455287475, 2836626630, 370954493, 1547293137, 985303965, 923698635, 3798229340, 1521837281, 3300989696, 2747825174, 959818359, 942817307, 4222297750, 928667844, 3422055366, 791657294, 3980303473, 3934614012, 1903883342, 839746301, 3937922232, 1208202864, 531643008, 1841527350, 2104341419, 3937941497, 538909227, 434474141, 1290024891, 2875325435, 715412039, 450789800, 870839194, 1707042571, 1534702655, 3179636662, 1535079775, 4214055026, 4290924281, 3472275138, 2751876129, 2866770526, 586980005, 3783233770, 198668758, 2153105586, 2609121305, 3577364714, 1920635702, 3669329714, 653495613, ]; static const List _envieddatallamaKey = [ 3555122068, 2326329659, 750340653, 574845745, 1835686177, 2935056484, 2541063795, 2772965668, 3906373711, 1823426451, 3833446616, 1697064745, 2908303385, 3194041851, 2304244583, 3664178454, 3009453402, 2287906928, 157165278, 1156046298, 2714638758, 3449002149, 3067331548, 1455287495, 2836626573, 370954423, 1547293154, 985304043, 923698596, 3798229265, 1521837273, 3300989773, 2747825250, 959818304, 942817325, 4222297774, 928667815, 3422055318, 791657259, 3980303419, 3934613930, 1903883385, 839746234, 3937922294, 1208202772, 531643073, 1841527389, 2104341499, 3937941421, 538909280, 434474233, 1290024930, 2875325379, 715411976, 450789836, 870839287, 1707042610, 1534702673, 3179636610, 1535079736, 4214054933, 4290924222, 3472275123, 2751876200, 2866770539, 586980066, 3783233683, 198668729, 2153105642, 2609121387, 3577364658, 1920635738, 3669329776, 653495633, ]; static final String llamaKey = String.fromCharCodes(List.generate( _envieddatallamaKey.length, (int i) => i, growable: false, ).map((int i) => _envieddatallamaKey[i] ^ _enviedkeyllamaKey[i])); static const List _enviedkeyserverPHP = [ 1969208844, 3685105489, 3985860788, 1248760260, 2708419, 2098370540, 3031210828, 3907121476, 1991223849, 332363801, 2221725065, 1090835439, 577358101, 1608921829, 3192491663, 2748071000, 1318354055, 3906219165, 1311207564, 2232900632, 2432017873, 2901844894, 2566667412, 3597503333, 961116967, 1137778284, 34728661, 3025338383, ]; static const List _envieddataserverPHP = [ 1969208932, 3685105445, 3985860800, 1248760244, 2708400, 2098370518, 3031210851, 3907121515, 1991223880, 332363881, 2221725152, 1090835393, 577358182, 1608921728, 3192491753, 2748070973, 1318354165, 3906219187, 1311207648, 2232900721, 2432017831, 2901844987, 2566667451, 3597503254, 961116994, 1137778186, 34728624, 3025338493, ]; static final String serverPHP = String.fromCharCodes(List.generate( _envieddataserverPHP.length, (int i) => i, growable: false, ).map((int i) => _envieddataserverPHP[i] ^ _enviedkeyserverPHP[i])); static const List _enviedkeyanthropicAIkeySeferNewHamzaayedpython = [ 2239590971, 4285965516, 3695138759, 3637297636, 4099748391, 3630345505, 1046761753, 2316353469, 1486285890, 3453922576, 1461711626, 1540359714, 235638062, 1911640557, 1341630746, 2372710779, 376551306, 2450254571, 2261154098, 2753535277, 2097738604, 624429865, 2691420767, 1829894372, 565583722, 1373608420, 2161766275, 2813459082, 79109545, 2303720377, 1409988535, 4191969475, 733659744, 1002946509, 912373302, 3851860865, 1591076025, 2508500475, 3898489201, 2598538000, 3318881476, 2239996289, 3804260000, 657917637, 2173392825, 2181300644, 1479400036, 2432630723, 3487553971, 544261188, 936764434, 3200935935, 1465469109, 2178808415, 1832701799, 3039462395, 3931950549, 2399558786, 369170024, 4208016132, 2006223332, 2741602301, 4247906530, 2689592165, 823096094, 2866545522, 779237718, 1483928876, 3465509816, 3211719782, 3456757508, 486099864, 35839225, 2906336624, 3674340640, 2824942461, 22847070, 3081219473, 3580986795, 2608626252, 3702753378, 4135376, 2719951367, 2087574197, 2800870656, 206054240, 2765639902, 3586847345, 1832852376, 2909566728, 1258389353, 614454563, 3210321597, 2252175412, 2789694340, 905281069, 68021922, 4033873930, 2347853514, 537037329, 2796433849, 866713578, 2015214550, 743963859, 427130879, 580970434, 2645097993, 28836884, 3412571719, 3610627508, 2120413846, 965092952, 3972526624, 682605986, ]; static const List _envieddataanthropicAIkeySeferNewHamzaayedpython = [ 2239590977, 4285965483, 3695138794, 3637297557, 4099748421, 3630345538, 1046761780, 2316353484, 1486285876, 3453922687, 1461711673, 1540359707, 235638019, 1911640475, 1341630809, 2372710713, 376551335, 2450254524, 2261154140, 2753535319, 2097738537, 624429918, 2691420697, 1829894314, 565583659, 1373608342, 2161766348, 2813459130, 79109616, 2303720405, 1409988579, 4191969442, 733659664, 1002946491, 912373328, 3851860969, 1591076045, 2508500374, 3898489110, 2598538085, 3318881423, 2239996374, 3804260051, 657917597, 2173392883, 2181300727, 1479399983, 2432630706, 3487554004, 544261147, 936764508, 3200935845, 1465469158, 2178808373, 1832701743, 3039462329, 3931950476, 2399558868, 369169968, 4208016201, 2006223294, 2741602230, 4247906515, 2689592092, 823096139, 2866545465, 779237742, 1483928852, 3465509867, 3211719689, 3456757606, 486099964, 35839130, 2906336539, 3674340726, 2824942413, 22846997, 3081219556, 3580986875, 2608626221, 3702753312, 4135352, 2719951415, 2087574230, 2800870751, 206054199, 2765639830, 3586847237, 1832852447, 2909566843, 1258389307, 614454636, 3210321634, 2252175360, 2789694391, 905281044, 68022002, 4033873992, 2347853473, 537037372, 2796433884, 866713560, 2015214471, 743963810, 427130776, 580970409, 2645098072, 28836933, 3412571679, 3610627526, 2120413902, 965092916, 3972526690, 682606030, ]; static final String anthropicAIkeySeferNewHamzaayedpython = String.fromCharCodes(List.generate( _envieddataanthropicAIkeySeferNewHamzaayedpython.length, (int i) => i, growable: false, ).map((int i) => _envieddataanthropicAIkeySeferNewHamzaayedpython[i] ^ _enviedkeyanthropicAIkeySeferNewHamzaayedpython[i])); static const List _enviedkeyprivateKeyFCM = [ 3981922267, 3346880164, 1795153711, 2698012958, 4132435316, 3688811635, 1179516278, 1445266976, 3576206516, 3731032608, 217747518, 3696124548, 2263141719, 3717618969, 4095666951, 2140040103, 127587063, 2669691846, 1166813122, 1566785055, 2169781176, 3715844436, 2574766125, 1496996005, 2733377709, 3813532921, 2480544916, 2711200443, 3506022825, 4016297390, 1172688224, 1046877721, 1802929883, 1042164752, 951282737, 2844034980, 9975762, 4748154, 3834383008, 3070877504, 3773887048, 31536352, 1515491087, 2693026277, 2651975503, 1024310652, 4159993797, 514813947, 346211919, 475669877, 2397955656, 1991395847, 1840266448, 1462452404, 3974103842, 3462434715, 509397626, 219257392, 390049883, 3529471520, 214468573, 3453652672, 1910343934, 3248345121, 688901908, 158537972, 1081367554, 1144831056, 579791402, 3921153450, 2935413203, 1166676861, 3190816652, 1293833360, 4248466937, 3169479022, 660353853, 2842469670, 4181906642, 2981457359, 148164173, 2757244746, 4183233319, 3320857237, 2421402856, 995518725, 2499473346, 3030421086, 2431452981, 3503323105, 3651130299, 3305871179, 2613582820, 1428709013, 1263697053, 4062366099, 1538722640, 1130649655, 2653561849, 15230323, 2551972092, 2595160154, 2022102075, 3702440844, 1460384480, 3072636811, 803630082, 2081675564, 214832762, 1320690276, 928849104, 1963194755, 1239656811, 3861141955, 1952317543, 4009270568, 3751818032, 828084598, 2046606682, 3841830456, 1024117130, 1622140781, 851018347, 2901179357, 1147982066, 621086028, 902397950, 315404987, 721703774, 2682047910, 2201577287, 423206528, 3083164524, 536810114, 2472119946, 2424135631, 2642835754, 1491819727, 4012093736, 4290143603, 1474727393, 1711083045, 277986678, 2027034039, 141596097, 1912798708, 839576629, 2707051010, 3231733031, 4113749696, 2995182189, 3520668914, 3347369728, 1587370482, 3032032412, 4044443541, 2251358152, 1890087915, 137159941, 390058573, 2039802469, 318909920, 4018099823, 4165177100, 1002670974, 2250938852, 3498130702, 3459389476, 3863210877, 2986416063, 1538245437, 3292404863, 2027421018, 3252408140, 4239211483, 2631372546, 1234318565, 725089032, 1077235471, 2060563404, 3991627553, 1926869855, 4279067974, 1000061330, 3868058344, 4237763167, 119268378, 812800771, 2861588729, 2078590438, 295926757, 2395519663, 2813650560, 304734444, 2271168912, 1972943089, 4164895807, 1963853030, 634872854, 1135813757, 925513981, 842190267, 2578819169, 1098902754, 4226609402, 1315029793, 1719013570, 922357769, 363855675, 2462796564, 4182689866, 762698328, 1013327059, 2820501760, 2352460746, 1845169355, 1970194130, 2276456315, 1536676323, 509432962, 3539178299, 1664748476, 831963303, 1959525967, 1811457412, 2062538055, 218553516, 1481442856, 1872997940, 3852052600, 2944778740, 3091995932, 1506369797, 2184769374, 469420194, 3875176671, 1983082641, 156830608, 839208351, 343698082, 4121301936, 3629457187, 1700254524, 689767920, 3756684328, 3260069022, 723702027, 197026869, 1476158775, 640147787, 3242467175, 1231631740, 2352884230, 3030843748, 1225629893, 4018512906, 1960274124, 726761249, 383837199, 4137352616, 402373395, 2557391126, 2529892381, 3975336585, 1258243516, 139409959, 2633302110, 1372979774, 1817975077, 3445998652, 60703397, 261775031, 4264413027, 1076874911, 3629284003, 56691841, 2772902920, 2549778578, 2897023902, 314443416, 2556475300, 2532810996, 2908365250, 3039124861, 2288454488, 2588035315, 1656584557, 3238121772, 2055860495, 3980122022, 4066805930, 1841713884, 1624272622, 3373977367, 3879495608, 3111420203, 4270547770, 794961779, 1527215852, 1683813883, 2442868742, 2861787428, 30022298, 2035158296, 3836016707, 2830309630, 2593433932, 1473903968, 1918006837, 1758965873, 3838393111, 4276543062, 2028672394, 2982328524, 2644432163, 3171447640, 3109668947, 2279285900, 2813610336, 3556231578, 126863728, 3361961056, 644064697, 1400464097, 3337005729, 1295629820, 3475709079, 788576723, 2714460693, 1011779786, 735176737, 2205184000, 2560984045, 1791376721, 1706558866, 1504402526, 1409252725, 1583370247, 3436434450, 1394779303, 3344782854, 1326542936, 202837034, 1767585070, 3598053939, 3870190597, 2525308903, 3922878132, 3345261130, 35974734, 88009025, 2643558951, 422099595, 922802509, 4014273156, 2445899464, 3830397009, 4059813928, 997949196, 490526152, 104568815, 2200019813, 1490665254, 834166170, 1612573889, 3018054123, 2828340332, 797193688, 1850063835, 1009072026, 1778776095, 1169853008, 3133255138, 3518468738, 3235454781, 3424004164, 3198971586, 1466346705, 990804455, 2985664528, 2322412841, 3797624473, 461499860, 2699134584, 3471164937, 3451542450, 753407706, 243450021, 2646197692, 2920663707, 1835624057, 3529662747, 2823859943, 1974521902, 1372038081, 3795841855, 2258314511, 4081322782, 2079376553, 1349810440, 3584271937, 1026789111, 2579600666, 2761777129, 3779722283, 222490031, 1358281311, 3629320848, 1363394400, 3761616985, 3482912442, 3463122341, 2260520948, 3462604867, 2112854849, 106713855, 835546571, 3055010322, 2706334832, 4219149541, 2323649721, 2117406211, 3337739548, 2564252217, 1864066815, 3499118962, 4256446057, 427814795, 2986028242, 1330753526, 2950163024, 2076444755, 804386169, 2537649708, 2111726672, 1890911345, 2281718949, 1380263834, 1347026984, 4112888381, 1506036804, 1325045267, 2664324787, 2403182096, 1594677073, 400265876, 778544787, 2378466771, 1983435814, 4273276840, 100850925, 2328471545, 2948444531, 2657126963, 3820179195, 1053870924, 1936709241, 3223291659, 162217383, 1899809393, 3330523129, 485846683, 2941428628, 4029022001, 1143446915, 3622601070, 541967854, 2921656107, 3185611540, 3808221820, 38755396, 1063478778, 2823129320, 1151128400, 2320099643, 1793881836, 3916651928, 2239207923, 114805489, 2812828359, 3281137340, 3435690511, 2447225994, 2135471672, 2270208634, 1522002950, 2471291916, 923989421, 3439465690, 4120179531, 206342215, 3313684093, 3168474229, 1302409801, 3376867731, 4000338950, 3552032903, 2999233427, 472627141, 2103950265, 3906389748, 1100472036, 2158686899, 2776152799, 1314274685, 2676956660, 185267205, 3898859622, 158099401, 2116565065, 413498835, 128303659, 1170360952, 377110976, 4058533767, 94806833, 1390702292, 2470198701, 604165455, 1265797540, 3794877966, 2809735777, 248892698, 2520837035, 2488361820, 1818263725, 4082245230, 3511271216, 2438651903, 3111384534, 196299143, 2666311454, 2525242050, 16739257, 2053349633, 3134729987, 1066105875, 1360956937, 175246027, 3578595676, 3465909725, 1574260845, 363562265, 3942782789, 3465844926, 1398218648, 3641354110, 2112666588, 2530899842, 607827185, 29748235, 258779391, 1818237590, 2521301460, 1653013094, 2165034656, 468622356, 471251489, 1033677310, 1637958940, 560140588, 2439262654, 2489476406, 1891002746, 1302203463, 2698509219, 367767764, 3814967938, 877251532, 527587624, 1998457105, 1313841305, 2777432693, 4158445414, 3105955884, 3905457967, 3421264667, 3256358445, 2247911496, 3048444418, 1954942624, 3305736931, 3154420447, 1005608254, 1016886872, 3586838727, 846005081, 2135619981, 4036641406, 1885952153, 2035424707, 1180695664, 774703327, 4008526202, 1049621549, 3211906867, 3252341113, 2577071117, 2499523877, 2385946407, 2051798557, 1377061171, 1139007959, 2931433297, 26982963, 566620856, 3990593418, 2891348786, 985361144, 3349492759, 1669250211, 1849438310, 215958243, 2053618149, 3254450603, 3373441033, 808264803, 2420293120, 3738956768, 3030135844, 1415649519, 1984045310, 170593077, 2191242305, 2966552220, 2659661375, 3135670766, 3456270730, 3161215244, 2113148250, 1748878796, 864032655, 1647138639, 3149458351, 1878429497, 2790604930, 1804724952, 563250933, 3781808488, 2196738495, 1297061454, 1671610258, 2839219664, 54190717, 1321160430, 1454860780, 2173840316, 260448697, 2616252837, 1965529454, 3262117153, 57624293, 2383384828, 3958089900, 1647811813, 1247195842, 3913713453, 1830407355, 4237860146, 3195456369, 2243691994, 3466538342, 2221302929, 3810228874, 581191113, 2109526507, 2864821491, 226854103, 3342940685, 3662895456, 2898610202, 16647994, 3792169428, 2989468345, 2034275766, 1398459443, 2533442200, 662308801, 2288542311, 2275925043, 3096984239, 2517801243, 1035651899, 4050642982, 3651572392, 31201715, 164236749, 1181532931, 2908427529, 2605363232, 421421039, 2908707894, 1327292708, 950010697, 2700789657, 747776745, 195005289, 3667940660, 1301150487, 143697711, 3312190461, 3790729653, 3960139347, 659823607, 1138718717, 2025037006, 4151138983, 1348399036, 4071700250, 3809807973, 1316603836, 1192309846, 1387122844, 868870716, 3722390529, 1317568088, 1087995477, 1717499282, 3286993133, 1702782981, 1259532729, 107859979, 4251967060, 453409295, 647529006, 839106077, 3854140514, 2490308537, 2730383569, 448604222, 2094495664, 2882113069, 2775497632, 3967835897, 2729281564, 148462246, 4181103969, 2402226687, 2653424843, 3926326566, 4035129264, 250028820, 3650515189, 2271621666, 2645999969, 1193086188, 3941118712, 4004363215, 813195910, 1371147395, 3112788896, 3797169650, 2613939839, 3937421507, 724668422, 2878709092, 3432806086, 1607090647, 2826908585, 2464652415, 2601849612, 517899629, 1495564679, 2048130762, 708974837, 1700315538, 2579278273, 2242949441, 3460308474, 2388581660, 2770301444, 3744537010, 296354594, 2054159871, 3468853396, 1651514041, 4062623868, 3583825578, 2794129787, 1410796327, 4156382012, 2045715984, 3813065125, 3818919944, 1665102852, 1278187749, 4009313486, 202365681, 644210391, 1756153304, 3866170568, 3814335054, 2542750461, 3813215604, 1136014057, 2960011051, 3772001340, 586861871, 3923860481, 3470266176, 1546763578, 1902195736, 3104501664, 3876757106, 2571263930, 477981763, 2126062045, 269049910, 1290930322, 1780432887, 3160595001, 1417209701, 514282708, 1164023454, 2686453282, 3115969684, 4190938705, 3186443528, 1676171854, 531295233, 289168201, 1114096568, 3168586807, 613594789, 2970263892, 3449924641, 2658965264, 967110793, 3220039966, 4215063448, 3507754845, 133270418, 2334205304, 1831822609, 4262324326, 2309133978, 3999156776, 1791457596, 1256641253, 2242142937, 2820499689, 1229037104, 2660992190, 818933150, 2759281855, 3717480264, 112547385, 2956393135, 104847229, 2767915638, 1000035645, 3582285910, 3478042508, 908731263, 4060768484, 2564303962, 1475213067, 1339551978, 3750107469, 1080002507, 2787912125, 2645990150, 1568173343, 664951323, 195563864, 689296020, 3577669515, 1821670056, 3468814666, 1594124042, 817555651, 3193780319, 3426486650, 3320655549, 547932373, 1410453440, 4223791601, 1233467261, 3247156510, 2734757340, 2515500688, 2584433606, 4231237972, 2317152140, 2365102013, 936827045, 3876510247, 1680648134, 940806234, 986899195, 2391799027, 422634611, 4216371405, 547540254, 1508615574, 3364354997, 879755265, 3263706287, 533120172, 3594839962, 3452469847, 4055859708, 969997918, 4262262649, 1470323788, 1574987003, 401859900, 876195179, 2787490928, 1047019857, 1456393356, 1268268436, 1049292964, 1125089780, 49962707, 2656962752, 3432712111, 3828147887, 1008783239, 745874224, 2762581588, 118220858, 3732108798, 2127208388, 2769688285, 4274667124, 2951242862, 3366367927, 1598191526, 171242489, 744919083, 3925218218, 67453217, 202729256, 1796852965, 2981855335, 162603179, 468499587, 2498928560, 1780550188, 4154629753, 159800440, 918301787, 4009883207, 1405353177, 214354366, 2158957596, 3869560763, 3877900345, 1972516075, 652141274, 2653621912, 2767765677, 2033835604, 427710650, 3066436588, 2951118829, 2329045530, 2837864355, 369661323, 2512052550, 786311058, 817972640, 1292779617, 1845273405, 3767574573, 651561825, 4135562231, 2180200162, 857186603, 3543645467, 1098876395, 1744194175, 122392459, 4006499324, 4093925024, 2047275191, 1612275583, 4243136854, 1515517981, 967094934, 4124925157, 407264543, 3939504048, 3065407425, 3923876406, 234366703, 1267806301, 2103627408, 3161503390, 548723491, 1573785449, 1523860531, 3111076264, 3089072708, 2099939884, 2484876526, 847465510, 1287516312, 1277183311, 3825284788, 1286852397, 1071051992, 4211214318, 1395725316, 318332081, 3887322410, 3648123850, 3980865530, 482308962, 1393337805, 953623395, 869400156, 4267388190, 299775582, 4201609618, 2407563033, 2302119831, 906313690, 1287024299, 3047468697, 1961247671, 3065780178, 896060754, 2281157850, 43993189, 3759084088, 1257965245, 1712831998, 3118566793, 2952627364, 2536493746, 2411795166, 3620642485, 3555288126, 1116895003, 1021126224, 2579096214, 1020206011, 394251688, 2996670120, 1892934024, 2242747375, 2871062619, 1033916267, 233778482, 902809400, 2423438189, 3603630150, 3726742127, 3963756685, 2091120791, 1461915017, 846990501, 1140814285, 532282682, 290246973, 1413926828, 2836815176, 1545937573, 701427906, 6966626, 2521894774, 568079982, 1507550845, 1269329458, 4901247, 844581908, 2159007946, 3652623899, 2311865206, 2809893836, 2653658256, 559868311, 1797422328, 2403522753, 1340592037, 2909871562, 4258339872, 1990498549, 1747735621, 3443076681, 2839280556, 2198844498, 2969323272, 4067837655, 1809216596, 4213935470, 3721239910, 3110124563, 3633212186, 1076094919, 3492681160, 2990603714, 1282671169, 1162631115, 2299938101, 60794882, 556699340, 1151569191, 3492507576, 1719539772, 3827661025, 3541062772, 1295482807, 325546462, 810664998, 4164189336, 2550548636, 2227159271, 4052323377, 993650460, 624459121, 533363896, 3136167602, 1714985676, 2299507097, 3401403324, 2596403736, 2580829261, 1005216985, 3292487575, 389098918, 107392157, 698445126, 545507947, 3517962966, 3506980667, 2035236867, 334294585, 1567596345, 2975991597, 69070171, 108620321, 366436803, 2456257185, 300297686, 2562984755, 2934600353, 1729676095, 4066392588, 4085843491, 3296227172, 461743992, 3702256187, 2997712950, 1135886928, 2600348082, 4141089362, 892518763, 3058189589, 1934930519, 4153963813, 4252640070, 4262502884, 1253456086, 1961772005, 680562547, 1185858172, 634477470, 2339411373, 2164550347, 2803986361, 924454958, 3134526712, 966349044, 1453429200, 3082418651, 401225340, 3398590822, 128059545, 2178637220, 1774922145, 2255178124, 2918720843, 3327682118, 2214394413, 3099747667, 1661934963, 1298729940, 1272558680, 4053018353, 3789054841, 4131648492, 1773101901, 686931116, 1203446822, 3752734570, 3235657418, 1944359995, 697623116, 2039237806, 3348886677, 2064524550, 3039942399, 2701235347, 3767389171, 916901056, 48586704, 1416585585, 766915895, 3115924654, 331229057, 3134725303, 3457203626, 741448661, 854943726, 1524960663, 1896889473, 1713382184, 2640180467, 3592536672, 1428546862, 3838033593, 3778145286, 3664325196, 542063384, 529023530, 2782480697, 173628958, 958820372, 774948181, 1930508149, 1674876101, 3703541303, 3024990863, 473593391, 1202061776, 115478649, 3136639257, 3545390249, 2091581418, 2249203496, 2052969697, 969919513, 795131664, 546537576, 1302855139, 2724278010, 1751639238, 100232685, 3423489574, 103164121, 1984156496, 3109944628, 3809627117, 3362560523, 1292767560, 1281284896, 989446871, 2926075433, 1217424066, 1358302603, 252442244, 3489051600, 2648229275, 3946622619, 3719323549, 1749561460, 3345174221, 938188329, 693952432, 3443621177, 2911849161, 1427624316, 3678446798, 2906392291, 2445546358, 1977948992, 801684685, 2963795578, 3386667580, 2100145515, 936768644, 1593174223, 3875136628, 2590738238, 2890201689, 216936839, 1339115227, 2635418504, 119932769, 1340581862, 4144168265, 3938057421, 1168936317, 2215987271, 17184930, 216656254, 2188297819, 2061448278, 1202480469, 1405677027, 292664931, 953177447, 3172167786, 2503470694, 1562534143, 1387761019, 1505457387, 592131087, 3951980790, 1017622389, 2281683049, 2074962955, 3329400364, 1404464966, 3295703247, 3486575464, 2090288213, 3184219425, 761918525, 2960208240, 3763970129, 833445166, 267175176, 572901416, 770701708, 2145108397, 3628405300, 1694398909, 377464713, 999531075, 355730846, 1936325029, 1976818713, 854711490, 132862484, 1207569661, 392699516, 1081009974, 836817083, 8548221, 3978550238, 1419003659, 972930352, 1428068551, 4209168645, 4197520880, 3943327533, 99781359, 1496417935, 970974623, 1028307449, 2504293777, 2296530467, 54001860, 334118479, 3633345056, 3002480859, 1813811374, 25154938, 301497518, 4275021930, 3282143123, 1785549025, 3598774605, 668914748, 3160281112, 190382168, 3606378643, 3008775778, 894795587, 2920018267, 992106292, 605405246, 1572036356, 1611796179, 3432918843, 2744331545, 1848223043, 1152080712, 1195579261, 374577063, 1687993070, 3507249428, 3508208098, 24847331, 3733363729, 410066894, 1140860469, 1186346254, 4001954564, 1781698919, 1473739648, 611800377, 2528535721, 483659100, 1465122916, 1423007157, 2160485157, 2603441149, 814091188, 839018888, 2290160479, 709434822, 3758915541, 206497366, 647739199, 1332381676, 3765956308, 2329586525, 3933383957, 2402114313, 2149614186, 2027684415, 3252300857, 3409909559, 2129462542, 3413088674, 550912561, 1884734489, 3454710315, 3089136778, 3468891815, 450825700, 1068267958, 1083780482, 1882776931, 3387913880, 2512854824, 3765561147, 2082119393, 3191789998, 3268009062, 1072301092, 989191045, 902359821, 2242814577, 2285401049, 3185723396, 1189582677, 1052972760, 3007704025, 2985550861, 2069850031, 3678424230, 1801617804, 246137952, 1713777329, 4040290028, 1552898325, 787558002, 2622943985, 3295504759, 3744612268, 3526116115, 3352769670, 3910684858, 4186388391, 3972654099, 2209684028, 3906598359, 1607122378, 4076456035, 3754124346, 2634876984, 4104847148, 2656001877, 2198100150, 3683620463, 646937365, 364412410, 2895405383, 3041104998, 2380266516, 4262451672, 1818177963, 3391440962, 2968709759, 3349770446, 1689905488, 2452371329, 776949993, 1046308568, 1592843043, 3356487496, 543456261, 4019266966, 3413881002, 2162344782, 2906465773, 604490828, 2482347082, 1465834774, 3590369453, 4006089194, 2221173365, 1680871970, 2374564446, 140760082, 935674497, 1201104267, 388802414, 3253154925, 3608163578, 375711410, 2065707519, 136847632, 3867470770, 802096470, 3359615282, 2988900115, 445520923, 2627882076, 1277600524, 1248782998, 4211777827, 1753939330, 4078827803, 2202860817, 1375887292, 1336540211, 4107127315, 3240966349, 1025999202, 2217540088, 635654532, 3012341919, 3048508995, 762060967, 3937951865, 757818969, 286528768, 2504250232, 4291469257, 793464992, 1934262619, 3603733483, 4264651163, 450041391, 3683285142, 3943679854, 4184673313, 3112966325, 2999093658, 839336362, 1252897003, 1520818631, 1996403225, 4076122542, 2679158812, 1234736508, 3277957203, 2521119640, 477707976, 2764279211, 1725521666, 189237909, 2649848915, 1921924037, 3323989921, 3497554286, 3667891284, 363810963, 4123651570, 654290819, 3828886729, 1074566868, 3529808189, 2376273563, 3188405429, 1340442687, 23366406, 177240564, 1418661962, 2772522930, 3329973409, 2499441159, 2436920191, 1677149960, 2838258055, 3248073812, 1936894453, 195979059, 3336629797, 2225225170, 2241276337, 2103330645, 867316452, 1005790753, 1435458802, 2518696166, 1500391368, 2957570303, 1399704578, 1635394098, 1448662176, 2140705131, 2354872919, 478054843, 3956581489, 2386494806, 3659886269, 1810497191, 988357215, 1183625291, 3308188174, 3864913942, 2139265271, 3106141222, 4095094433, 3908751236, 1219514047, 3934434965, 4198330208, 2716119872, 671526211, 1442746803, 2980086740, 1779948513, 3104658113, 3039535623, 2864235814, 1361080987, 3301975174, 2301937357, 64212135, 964827543, 4062021037, 463814621, 2591002756, 3034306082, 1346952501, 3616259860, 3529562482, 1407376597, 1300938740, 1831428582, 1377054435, 3494483672, 747322418, 216966075, 3109940556, 528951892, 1669013946, 101428898, 2355473724, 1271448741, 296701196, 268703684, 3772961050, 1364096728, 3595360865, 3834654553, 245756443, 1180671740, 3059654943, 1665841768, 4037643718, 1968685557, 4003118184, 1863308575, 3388905795, 4159463682, 4075930734, 3935485977, 2840325196, 18372373, 922566769, 3339869542, 2322470696, 2065294323, 4265824665, 429328623, 2074833176, 2599110428, 369418755, 3008438360, 2290841335, 2261453736, 3219343943, 3835916767, 3330072959, 1011610580, 4028138814, 2334037773, 1160961029, 3783760768, 4129099873, 3347763150, 1542597051, 2667694442, 1899324151, 4271283002, 446119623, 1742983365, 1490047239, 3496881753, 1609204301, 1618233515, 1446119000, 3059663608, 2392848378, 2197177325, 4202324901, 830381063, 3172287722, 2284794326, 60048900, 776939959, 126368974, 3335316819, 1617224393, 1887735511, 1166521134, 2051868140, 204477306, 2610832872, 1270236240, 2858895850, 2259287284, 562086299, 192678059, 206934821, 2586951764, 915075707, 1531503316, 2422154594, 52428376, 3158676538, 3151131838, 136530178, 1767843381, 272791523, 3828859539, 1225138780, 163687578, 3525118767, 2535968292, 1924379759, 283228679, 4163469278, 3564332123, 2796953513, 3876635710, 2631269364, 435019183, 3612086791, 3922297413, 2481322453, 2240232544, 264330780, 665379959, 121343678, 3341464509, 1276481199, 890467429, 2406267587, 2548172695, 1555519814, 2624817395, 2649640796, 2008390449, 3369404831, 3318100743, 4221083470, 876058616, 1611683006, 3782414599, 927777533, 88074728, 1295423020, 4122276637, 3546635539, 1290911081, 1656784269, 1878676170, 994393576, 2611964223, 3332196548, 613467902, 4227931359, 628818529, 810178161, 4187267699, 3258744658, 1124346511, 2242608640, 1767743482, 3960871523, 3694411777, 406925992, 881968096, 1110666459, 2373577443, 1816382591, 3578792728, 3059987639, 1362889683, 3276050168, 85597507, 3955182174, 4190965891, 210511918, 182308576, 2970087759, 681329371, 217312980, 3140854762, 4199572746, 2423266063, 611338769, 188684580, 387654590, 4208113818, 938495350, 245698597, 2592260023, 4067163389, 519701232, 1490532487, 3677927206, 4258482897, 3236806699, 873090090, 1615040827, 2684458234, 1214354773, 3808440772, 2406008897, 3692493684, 1219698021, 2285892732, 100870239, 3388557694, 2876509474, 4244766036, 1017137303, 3662418363, 4236747031, 837030258, 3878772982, 442432038, 2350568934, 1377998825, 580739222, 3664426791, 4221279257, 1015619765, 2788249033, 760252448, 3392519986, 2585360459, 140810994, 2492079986, 1783515715, 3751207537, 1323412349, 3653658228, 1639014390, 887227437, 2465063999, 3023598050, 899721999, 2706288461, 1998284994, 2926476684, 2950171951, 3726696418, 2404322839, 1986985524, 1863053884, 4292239636, 1500243302, 2477397933, 1886915427, 314868964, 285534586, 238835825, 2091996952, 1712504420, 2535782508, 1059481110, 1551368040, 2569309671, 164825657, 4197566927, 3007996126, 734721058, 1075862705, 1190607268, 3085176441, 2647730498, 276950343, 4188313105, 2644079974, 4268419917, 2118105026, 2838182688, 631686803, 4049268539, 1213849470, 395500138, 411451934, 3921892282, 1428122457, 3020360876, 3699851865, 2119420288, 1032914964, 911509731, 379170880, 1931756704, 2671028788, 2596306016, 524457794, 2484367349, 3969243850, 2002483571, 3535862375, 4168823533, 4122856451, 299191759, 4043906425, 3530247727, 3073040529, 2219836774, 1533630956, 833955906, 3525350270, 1111680406, 3599551747, 479339881, 4188026512, 3947101254, 3309992798, 4150344220, 1712302370, 971968818, 694304365, 4189216881, 650392319, 2475725098, 1112484136, 4067521904, 1457755905, 1198460893, 1448917178, 644122900, 1977075084, 2680431451, 2297523520, 758780515, 2362536300, 69290656, 3355651761, 2497463743, 3637278887, 817056130, 1618493112, 3238323433, 2576549056, 4134473132, 3941966948, 2468389063, 1989550897, 939185386, 154995128, 1050055369, 603118285, 3385201060, 1906746855, 2510736699, 1496731888, 3576997171, 1620074729, 1769919715, 3212241340, 2437369248, 2845004790, 773974130, 2057140996, 3506691775, 1774264184, 835045581, 2654816329, 1511846742, 1592372647, 3063102621, 1560480041, 3994960219, 776324840, 3819796405, 898988054, 37164886, 1744208957, 1089382268, 3694627279, 732493848, 763581161, 2631056576, 176492401, 121625068, 3815059576, 3075385388, 156121283, 3028625738, 4214465957, 2335965573, 2130896323, 3930208688, 3555403758, 3702865408, 3804078404, 3050737015, 3869289500, 2102279238, 3206425564, 267786674, 3483225181, 522554066, 1984826377, 3217768675, 3838297681, 3405536830, 2966997290, 2902635987, 2810651413, 2195519628, 4153919901, 3765936067, 2391008749, 415766520, 3494083625, 278039327, 2195922196, 3358034354, 3985136516, 3706836578, 319317736, 1266735130, 2648410921, 3052965412, 3860521011, 1335678359, 898803331, 2771426421, 1100294522, 837103821, 1822780985, 2468563755, 2652326421, 1237920298, 3888314916, 3703270860, 2334954603, 425709934, 2923195992, 3781553449, 2481380543, 2836201016, 4163743535, 1856271603, 2514914508, 2659740260, 994689858, 1754129618, 2572270590, 933071645, 3238911999, 2140596713, 2324809752, 2447233203, 3944524421, 1464590078, 1783469000, 1426484321, 2831036589, 669953366, 2467395920, 1346745980, 28384445, 520057418, 2605156850, 3547641409, 3968632424, 3586137739, 1829248051, 2877202614, 3505134519, 972761614, 669880595, 2736668144, 1806406509, 3613308662, 3957011320, 2148405042, 4260751373, 2998225764, 2338191417, 216214311, 4183131842, 374916770, 2884617637, 3296738313, 2074837802, 2384235525, 3030717299, 1950687364, 967763152, 4071323425, 3730628665, 2438950262, 1779914536, 3291569086, 472167725, 3873972613, 3746688797, 3288172204, 1586007980, 20146338, 1356698351, 1241784843, 896604961, 3504660206, 1230568383, 2418737211, 859280986, 4002301551, 2466760899, 834105300, 3254854935, 3968072035, 4123415185, 1521003012, 2749958854, 546877746, 1779121879, 918664132, 323508823, 2959053448, 2234275917, 391098903, 1525191579, 3014675918, 840072995, 2289738701, 2626990321, 2617163154, 1509589808, 1658571668, 3968660169, 2750932260, 965382996, 3744578228, 63238035, 1420213592, 3547158354, 659688910, 1687362099, 3671914349, 4088721928, 3129154106, 2800628877, 2056370684, 655539975, 419330280, 3477754689, 118810946, 3783215365, 3617854189, 2773406401, 3398689733, 137446820, 3445441799, 1377751978, 102773037, 1428576770, 2126861245, 282024741, 137965589, 799908344, 2747012104, 2588842363, 4079593756, 1884796543, 2089878612, 287438339, 3042459863, 284155932, 2194328115, 2537630306, 1115213219, 1000033464, 2054992093, 4288536304, 3809982624, 3143688791, 912790566, 2690711345, 3282737653, 1757552999, 1662483077, 2906945953, 2589432623, 3764809490, 3954618988, 2997904974, 378410069, 2557433647, 2315034770, 3168371160, 1074613766, 3685021410, 2666944827, 667360663, 392246967, 1963080188, 241189265, 2383220761, 273454907, 2699152184, 1178758157, 3686978840, 3588348145, 475514317, 1401569826, 2822156887, 762344545, 1302677667, 1336163318, 1574429551, 2438801135, 3464343896, 2773171189, 800437699, 1988558003, 3139930905, 2680545570, 2517347943, 381423179, 3749204260, 171704860, 4110583218, 4082557273, 4117643380, 1581712905, 1478575901, 3213409901, 3570398352, 199363079, 74998555, 1497479943, 1588902876, 2182716719, 2044279883, 2530715703, 3631828968, 3028359884, 3296477376, 3712890896, 695166934, 1681668003, 2116068226, 541304037, 98394202, 3675545685, 4167724997, 3036031502, 2203689807, 1365103938, 128733408, 2267978318, 2423691132, 421730666, 1133375234, 1488361108, 921779152, 2401667467, 103926862, 3304404831, 1435097980, 104836849, 2621606137, 1212957977, 2886318207, 125706266, 3458107665, 1923375261, 1974177236, 1379184180, 151282983, 1974411369, 3532138619, 3129889958, 493207527, 3855901858, 385431276, 593699702, 2003604409, 1273493811, 2534089971, 3801017906, 1391378085, 4052598651, 1493885902, 2547139905, 55775436, 3393276795, 3022286616, 3556257664, 4073739116, 3010324767, 253360888, 1769675772, 4198702121, 3004501477, 934221424, 2043508004, 3285425452, 1261525474, 1643528612, 20940993, 2937444680, 2920811264, 3721095898, 3980255034, 4082099408, 2207357862, 2397279872, 3133632760, 3858259552, 2205386511, 3119367492, 1226554158, 1383031641, 418493382, 3495739874, 3765302976, 1618904343, 247540440, 234268054, 2441127976, 2008348696, 965985008, 2881602208, 2608102572, 2300847298, 3891718328, 1421948532, 3557204540, 612553099, 4060595604, 46753905, 4050163030, 1338654393, 3060241350, 2974986367, 2158728507, 1980012169, 3427060753, 4039506524, 3687711034, 2625388079, 122917121, 65262698, 1710153628, 1062178361, 1192911960, 966332899, 2929033306, 4175997354, 1820552253, 3990059547, 2738720271, 1415735718, 1747006761, 3680962181, 2550782379, 1472091423, 2408227799, 659637802, 1330226412, 3165519077, 2780611778, 3779279565, 3640745234, 3531581475, 617584432, 2625316884, 2964566706, 2366391302, 373228380, 3957914941, 1258771570, 1731935386, 810067853, 2605132230, 1840584526, 4079026280, 4094595934, 829301828, 565188535, 1263030328, 3726343709, 918653609, 472976186, 4286770678, 4036012713, 3176300636, 1107071055, 4144843767, 25492387, 2207649473, 3633977206, 2147514011, 1269991804, 2683965332, 2520639290, 3086660701, 617169089, 3432492182, 3710673013, 3409402171, 119439193, 3963100264, 3342998344, 3693521218, 1853335090, 2389605173, 2872784534, 2317685497, 3978855008, 3380967185, 4286235106, 1349107887, 1969512946, 4208086384, 581163680, 1082760276, 738048149, 1202565836, 565233836, 3445288438, 3039896757, 2880462532, 2474618502, 1513484970, 2142309827, 683739786, 378146314, 604326336, 2048166945, 2597099465, 4072040928, 1755442912, 2907595471, 3467550247, 250062411, 56058659, 1145710430, 3039069266, 1308673499, 1714524332, 581730636, 2761367602, 626014209, 137071723, 470268169, 1437302565, 2321627678, 22353324, 1332773196, 2159532693, 2158846549, 2373532920, 1862594758, 597810181, 2340972393, 3639427680, 1007863726, 695031015, 3011496685, 270375245, 506179337, 2465725881, 3586616321, 2004336553, 2540593185, 3053313031, 242205498, 1129472966, 2423477468, 2905078526, 1273830817, 3684442631, 1606743285, 1856404782, 997845114, 3493020767, 3764183853, 1210713014, 775445948, 2693348766, 1544199630, 4134758035, 2289181747, 2575820169, 4039240109, 1927565147, 2469436912, 1147407391, 88721923, 4251027520, 3943603462, 3343041971, 4136117809, 1408968141, 2011730488, 1115400373, 91805372, 3797413206, 3231843795, 254866824, 50349007, 3008475015, 4096823174, 806995258, 579015943, 224913096, 3452629520, 3935452085, 2158823338, 443232881, 27590479, 1626003822, 1659214304, 3730751302, 3304817506, 2126464135, 468094930, 2004841432, 4244266140, 3191633824, 621908160, 386502852, 3160550258, 1846013927, 3929062191, 1752552051, 2020989873, 3733195436, 3332803725, 568035617, 677499606, 887350608, 1910824007, 1074653741, 2669527119, 223941937, 3638297443, 3976028795, 2153246105, 3107649842, 2225817714, 365559155, 2590904030, 4267229876, 565109877, 1465231259, 1031473198, 1393103679, 3065248506, 874527522, 4007089971, 1754535268, 468826683, 3193473935, 2427827574, 3093649186, 3340523571, 538785348, 540707700, 1138431154, 390508157, 2231744390, 3431900480, 2267895757, 2586775989, 458121248, 4151047812, 1794590573, 2207519661, 757298974, 2917271667, 2795562736, 2743741950, 1960281059, 662426606, 3129250965, 3284489932, 2860828788, 1665561948, 243380839, 1919574353, 2539834343, 806470139, 1347773492, 2588536919, 1735157985, 2984222111, 3613443080, 2161200608, 1139265850, 428233632, 3310537846, 130112194, 1688164293, 1800051811, 302537682, 2956495410, 1641858969, 47106965, 2547135390, 3629305305, 2304666287, 2953885888, 4274433428, 3596400556, 979899549, 1408111459, 2891516324, 3148158119, 2198724778, 3377935353, 3741107315, 3692011630, 589770277, 1491910405, 3070679829, 96783510, 1097094619, 718459500, 1566463826, 2251827641, 615019390, 3547997086, 208891287, 3237297588, 3017013236, 1351182280, 3220242913, 1869677811, 2552355320, 2314224780, 3646448874, 827517512, 286583337, 2545551719, 1652513053, 2288536154, 1104922602, 1453694093, 3747222644, 3724572717, 208872394, 1298083238, 2440775102, 490732304, 2579371915, 773048215, 3117989783, 3093360535, 2944738318, 3420927430, 610089208, 3465176615, 2026748828, 893684011, 1051908807, 1631920906, 3068536747, 2517988544, 1237193659, 1186253152, 3445268041, 1527128786, 52389220, 2272891464, 4216412620, 162836167, 285766635, 1450011436, 2529126016, 2774138045, 363705219, 1046202415, 2342962149, 3660787015, 1475962515, 470852383, 718191623, 616824944, 76199769, 1858153084, 4018570557, 3978103333, 2630348151, 3609233416, 3189344676, 2518740437, 3931673556, 1974037890, 704660142, 3939759348, 28317872, 155880254, 98267636, 2179068948, 1621791453, 3883686984, 3889013516, 3901334336, 595696159, 2056195890, 1766401857, 3894355691, 374485730, 3627058903, 2345537254, 774497373, 2739386696, 638042079, 2714586118, 3681906223, 3586849544, 2279548262, 2388695512, 2729026734, 3921872400, 2742643461, 3256049952, 3524792600, 900652213, 4027843861, 1664123083, 1693946252, 1091032590, 3229605224, 3138471550, 4076063174, 1921014104, 703457779, 3778215220, 2874553038, 1977925517, 3474710342, 1397524212, 1639376229, 1365339851, 1396788617, 4170383328, 2374091134, 917644633, 923930639, 335414448, 2894224058, 2132047519, 2139834936, 893152735, 3658071140, 1808034705, 3992989164, 541814435, 2467639229, 4252046851, 2221776534, 4010357500, 3280876403, 2195433727, 605914204, 3580984099, 1849716223, 1379095517, 1444911428, 1727601518, 1107293130, 1360518977, 3882144643, 2304676230, 3161709399, 4202670478, 1726836178, 1352003285, 1211530781, 1428143088, 233742193, 254065653, 3778834578, 2960826705, 3846707957, 78125029, 3035610061, 4248789487, 1988353744, 1488294606, 2658401089, 826190398, 982579256, 2611299281, 607386235, 383744519, 741541202, 685070477, 839618654, 168365378, 3600193469, 3516963641, 3847439358, 59984353, 3531750373, 4110124515, 1832015278, 1109782359, 224715782, 1368486037, 2896735063, 1631277466, 2122909243, 1329181006, 3883429858, 2709763262, 1485532168, 1454163675, 3877647488, 1314197277, 2191792338, 1547290735, 2767848648, 3165457718, 2615232542, 3554360174, 3461892329, 437444556, 2530137891, 2811265260, 1462499085, 344905327, 3209896916, 2633921064, 1629316811, 1898327023, 1699291966, 3173676731, 2413271340, 2308589503, 3010504633, 2318476076, 4283542148, 3136680443, 1274070160, 3634534492, 1621178692, 2720726637, 2557726718, 1593800678, 3618016582, 4222420563, 1427771361, 2709604096, 3380881481, 3429159678, 1651149672, 851806684, 1924253026, 3042327229, 2621745272, 31459648, 1789941349, 2699969840, 4089263817, 309554307, 2416205374, 668142405, 1028045075, 2577874596, 3966935454, 4013816966, 952209266, 2464801694, 1951540504, 270149487, 3537443337, 1700303154, 1525434601, 2016801699, 1016066231, 788950326, 3301786090, 867188914, 591182740, 4147481744, 1636209111, 2870738335, 1379570713, 1718211426, 2080443576, 3117953119, 787459719, 454627901, 2241519126, 1690518058, 1687083774, 721125501, 177924835, 596380000, 3547974950, 3551038049, 193705970, 3903775738, 2791266941, 2946582806, 3677605584, 4114537422, 517706327, 2851515209, 3606961145, 3140861945, 2004897753, 2934409336, 2266808973, 1728851303, 2963852036, 3726868429, 2346475915, 3284094460, 2603029281, 1910866618, 2201562964, 922269736, 3490564305, 1223267941, 781137632, 1409009696, 1481644162, 638868514, 1299363950, 184622510, 2140815555, 972229383, 3463817591, 337587666, 1588378885, 2458859056, 734138965, 829580768, 1807474494, 1339021242, 2949169736, 2696891033, 3696602735, 1454748247, 829820702, 3565850641, 1581233899, 3083125002, 1038667443, 3614790955, 2537209861, 429330569, 3337980755, 3093601805, 4279291223, 1931300006, 3549963871, 3073864229, 3313723218, 1045894152, 3527208247, 3955141082, 1168948257, 2252748292, 1419859777, 1697615867, 1861852649, 2965412203, 2785614098, 2019081017, 3865163652, 1715960207, 538250598, 3777321576, 2012459609, 2954119511, 2929968610, 3887420692, 3803424535, 3695819128, 3864966792, 2146529039, 88966253, 3171364951, 3564359251, 2710751340, 3483003590, 2389828882, 3033472152, 4212945213, 3200039359, 2723039622, 1234116552, 1847511641, 1554459825, 490403919, 2702426108, 1360638138, 3767662101, 978930427, 1673983808, 2622724125, 1465277160, 3276263209, 104027869, 1275307505, 3713601516, 1892013036, 2561897658, 666977991, 263458610, 1205359270, 3825584429, 1772594848, 983170947, 1967517594, 2312744096, 1934059502, 237802706, 3413186660, 3980764592, 4157606336, 3321271480, 2228423201, 2951588029, 3216481751, 4263810151, 3695527411, 3201086913, 3465621801, 3115371457, 596190060, 2778927014, 1192881408, 4070672649, 1695932166, 2461613458, 3114294227, 1035068802, 1219869074, 1567081138, 3182031525, 996055838, 2184037038, 1613272955, 4138419359, 3574859140, 2772736437, 3058734518, 879110565, 1620863568, 451271198, 1423497993, 2260885020, 2287937560, 2182652781, 1959408511, 3417993986, 2762728750, 3723683050, 3620972185, 4004350356, 3852922831, 4042483635, 817590845, 4008434170, 4150679218, 1818473315, 2274061975, 1287134641, 2606537046, 2900163666, 764327589, 3380352217, 663960686, 1574962534, 908720832, 732411607, 3092799659, 89050124, 2612418305, 1167021814, 2703900926, 196466092, 4100558315, 422322205, 553572451, 3812332461, 2709890514, 1048889592, 2536724688, 1892819687, 1492915362, 4123276265, 656277319, 1950735096, 2209777574, 3597582923, 207740613, 1242405110, 2794288428, 2384281671, 789332028, 2113081093, 4033156773, 3430572653, 2514642758, 3849776233, 3999536558, 2183668968, 1797714154, 1574723005, 291326548, 1162829322, 2833518095, 312882022, 3489561023, 311193931, 226320155, 1285113365, 1105912286, 188068592, 3599336506, 2095448637, 2645627254, 3743399066, 2671665149, 4239787521, 132154696, 3481420823, 3573468233, 4187070124, 2530155508, 2924766285, 3143247770, 3915372328, 1180529678, 3971354205, 602939736, 1999356640, 874227868, 3051951819, 1059212591, 2567771075, 3659557483, 2849657868, 2790113113, 3534643290, 3382123624, 4227034778, 3266187526, ]; static const List _envieddataprivateKeyFCM = [ 3981922188, 3346880254, 1795153788, 2698013014, 4132435203, 3688811583, 1179516195, 1445267054, 3576206589, 3731032591, 217747529, 3696124648, 2263141678, 3717619029, 4095667026, 2140040158, 127587006, 2669691804, 1166813066, 1566785094, 2169781214, 3715844475, 2574766173, 1496996034, 2733377762, 3813532822, 2480544930, 2711200497, 3506022899, 4016297438, 1172688140, 1046877773, 1802929802, 1042164833, 951282810, 2844035055, 9975776, 4748082, 3834383082, 3070877485, 3773887037, 31536307, 1515491141, 2693026254, 2651975485, 1024310600, 4159993740, 514813826, 346211880, 475669775, 2397955687, 1991395920, 1840266491, 1462452356, 3974103825, 3462434798, 509397564, 219257440, 390049821, 3529471603, 214468585, 3453652649, 1910343858, 3248345175, 688901920, 158537909, 1081367627, 1144831013, 579791472, 3921153439, 2935413240, 1166676746, 3190816714, 1293833426, 4248466877, 3169478971, 660353796, 2842469697, 4181906612, 2981457405, 148164217, 2757244794, 4183233345, 3320857330, 2421402754, 995518829, 2499473320, 3030421012, 2431453010, 3503323024, 3651130250, 3305871145, 2613582739, 1428709116, 1263697098, 4062366119, 1538722564, 1130649669, 2653561749, 15230247, 2551971988, 2595160174, 2022102114, 3702440932, 1460384421, 3072636927, 803630154, 2081675590, 214832659, 1320690228, 928849028, 1963194817, 1239656744, 3861141930, 1952317442, 4009270596, 3751818055, 828084543, 2046606649, 3841830497, 1024117196, 1622140703, 851018243, 2901179311, 1147981982, 621085960, 902397898, 315404995, 721703698, 2682047986, 2201577231, 423206609, 3083164463, 536810170, 2472120044, 2424135594, 2642835833, 1491819669, 4012093789, 4290143529, 1474727381, 1711083089, 277986629, 2027034048, 141596059, 1912798653, 839576678, 2707051088, 3231733057, 4113749681, 2995182087, 3520668807, 3347369801, 1587370379, 3032032489, 4044443552, 2251358192, 1890087826, 137160045, 390058506, 2039802448, 318909864, 4018099801, 4165177144, 1002670892, 2250938765, 3498130792, 3459389510, 3863210809, 2986416010, 1538245464, 3292404761, 2027420976, 3252408118, 4239211422, 2631372596, 1234318510, 725089090, 1077235532, 2060563365, 3991627607, 1926869815, 4279067919, 1000061410, 3868058288, 4237763132, 119268433, 812800822, 2861588626, 2078590423, 295926673, 2395519644, 2813650610, 304734336, 2271168989, 1972943007, 4164895827, 1963852970, 634872925, 1135813639, 925513901, 842190288, 2578819122, 1098902675, 4226609325, 1315029779, 1719013560, 922357863, 363855736, 2462796620, 4182689811, 762698288, 1013326977, 2820501838, 2352460677, 1845169306, 1970194071, 2276456247, 1536676296, 509433073, 3539178362, 1664748496, 831963339, 1959525922, 1811457493, 2062537993, 218553564, 1481442912, 1872997986, 3852052481, 2944778691, 3091995984, 1506369860, 2184769337, 469420240, 3875176679, 1983082659, 156830633, 839208405, 343698126, 4121301893, 3629457250, 1700254547, 689767861, 3756684381, 3260069078, 723702118, 197026924, 1476158802, 640147758, 3242467108, 1231631664, 2352884297, 3030843693, 1225629887, 4018512988, 1960274169, 726761294, 383837250, 4137352652, 402373467, 2557391206, 2529892428, 3975336654, 1258243576, 139410019, 2633302047, 1372979807, 1817975138, 3445998615, 60703431, 261775064, 4264413018, 1076874950, 3629284039, 56691936, 2772902972, 2549778684, 2897023917, 314443467, 2556475285, 2532810938, 2908365210, 3039124787, 2288454425, 2588035204, 1656584504, 3238121759, 2055860583, 3980122014, 4066805983, 1841713803, 1624272541, 3373977423, 3879495641, 3111420266, 4270547826, 794961696, 1527215837, 1683813782, 2442868845, 2861787459, 30022392, 2035158316, 3836016762, 2830309589, 2593433899, 1473903924, 1918006911, 1758965792, 3838393179, 4276543024, 2028672482, 2982328510, 2644432219, 3171447612, 3109668921, 2279285950, 2813610250, 3556231637, 126863672, 3361960994, 644064651, 1400464041, 3337005760, 1295629737, 3475709142, 788576740, 2714460764, 1011779763, 735176792, 2205184112, 2560983995, 1791376649, 1706558918, 1504402458, 1409252608, 1583370306, 3436434504, 1394779357, 3344782943, 1326542890, 202837107, 1767585117, 3598053916, 3870190638, 2525308830, 3922878207, 3345261176, 35974662, 88009015, 2643558986, 422099661, 922802465, 4014273248, 2445899495, 3830396951, 4059813977, 997949304, 490526207, 104568705, 2200019713, 1490665329, 834166251, 1612573860, 3018054021, 2828340234, 797193652, 1850063855, 1009072075, 1778776170, 1169853030, 3133255113, 3518468848, 3235454738, 3424004110, 3198971543, 1466346644, 990804399, 2985664632, 2322412872, 3797624542, 461499801, 2699134526, 3471164999, 3451542489, 753407667, 243450086, 2646197716, 2920663789, 1835623949, 3529662797, 2823859887, 1974521924, 1372038029, 3795841911, 2258314571, 4081322833, 2079376619, 1349810559, 3584271990, 1026789037, 2579600744, 2761777053, 3779722310, 222490010, 1358281268, 3629320916, 1363394330, 3761616942, 3482912456, 3463122387, 2260520845, 3462604833, 2112854786, 106713769, 835546513, 3055010369, 2706334722, 4219149503, 2323649784, 2117406324, 3337739606, 2564252239, 1864066698, 3499118870, 4256446013, 427814844, 2986028215, 1330753452, 2950163002, 2076444673, 804386069, 2537649781, 2111726626, 1890911253, 2281718984, 1380263848, 1347027035, 4112888342, 1506036786, 1325045286, 2664324834, 2403182116, 1594677030, 400265922, 778544882, 2378466730, 1983435876, 4273276891, 100850817, 2328471483, 2948444452, 2657126915, 3820179145, 1053870855, 1936709165, 3223291684, 162217457, 1899809283, 3330523041, 485846737, 2941428711, 4029022020, 1143446995, 3622600996, 541967781, 2921656159, 3185611613, 3808221771, 38755368, 1063478728, 2823129218, 1151128344, 2320099649, 1793881765, 3916651982, 2239207877, 114805436, 2812828407, 3281137354, 3435690594, 2447226055, 2135471712, 2270208559, 1522003006, 2471292030, 923989441, 3439465659, 4120179491, 206342261, 3313683994, 3168474150, 1302409759, 3376867839, 4000339007, 3552032989, 2999233483, 472627197, 2103950292, 3906389688, 1100471964, 2158686928, 2776152718, 1314274576, 2676956611, 185267308, 3898859569, 158099371, 2116564997, 413498794, 128303740, 1170360864, 377111024, 4058533844, 94806789, 1390702268, 2470198724, 604165431, 1265797578, 3794878057, 2809735702, 248892713, 2520837093, 2488361847, 1818263751, 4082245209, 3511271239, 2438651795, 3111384482, 196299206, 2666311526, 2525242011, 16739286, 2053349733, 3134730085, 1066105976, 1360957002, 175245999, 3578595606, 3465909687, 1574260829, 363562331, 3942782753, 3465844955, 1398218704, 3641354062, 2112666502, 2530899905, 607827122, 29748288, 258779283, 1818237684, 2521301397, 1653013032, 2165034707, 468622399, 471251533, 1033677231, 1637959034, 560140569, 2439262678, 2489476479, 1891002624, 1302203437, 2698509256, 367767703, 3814967989, 877251486, 527587659, 1998457154, 1313841402, 2777432647, 4158445342, 3105955966, 3905457985, 3421264726, 3256358467, 2247911545, 3048444527, 1954942659, 3305736858, 3154420398, 1005608299, 1016886836, 3586838668, 846005097, 2135620047, 4036641303, 1885952247, 2035424682, 1180695587, 774703288, 4008526136, 1049621630, 3211906906, 3252340993, 2577071177, 2499523862, 2385946477, 2051798649, 1377061187, 1139007888, 2931433321, 26983014, 566620908, 3990593487, 2891348843, 985361069, 3349492770, 1669250253, 1849438208, 215958199, 2053618099, 3254450639, 3373441134, 808264720, 2420293240, 3738956747, 3030135874, 1415649420, 1984045192, 170593119, 2191242276, 2966552233, 2659661435, 3135670658, 3456270821, 3161215331, 2113148268, 1748878774, 864032749, 1647138595, 3149458404, 1878429531, 2790605003, 1804724878, 563250847, 3781808397, 2196738439, 1297061432, 1671610362, 2839219685, 54190640, 1321160381, 1454860714, 2173840342, 260448756, 2616252823, 1965529367, 3262117203, 57624273, 2383384722, 3958089955, 1647811733, 1247195808, 3913713532, 1830407374, 4237860107, 3195456324, 2243691948, 3466538281, 2221302982, 3810228901, 581191075, 2109526456, 2864821418, 226854018, 3342940775, 3662895373, 2898610216, 16648045, 3792169363, 2989468361, 2034275782, 1398459504, 2533442293, 662308785, 2288542245, 2275925093, 3096984278, 2517801292, 1035651938, 4050643009, 3651572420, 31201731, 164236793, 1181532994, 2908427621, 2605363278, 421420952, 2908707954, 1327292778, 950010639, 2700789717, 747776729, 195005272, 3667940676, 1301150500, 143697733, 3312190348, 3790729630, 3960139362, 659823534, 1138718612, 2025036982, 4151139063, 1348399080, 4071700288, 3809807887, 1316603858, 1192309798, 1387122856, 868870782, 3722390636, 1317568108, 1087995405, 1717499349, 3286993028, 1702783042, 1259532784, 107860062, 4251967034, 453409378, 647529028, 839106143, 3854140423, 2490308602, 2730383584, 448604166, 2094495731, 2882113148, 2775497621, 3967835850, 2729281646, 148462273, 4181103946, 2402226590, 2653424796, 3926326608, 4035129333, 250028835, 3650515104, 2271621710, 2645999918, 1193086113, 3941118603, 4004363168, 813196015, 1371147505, 3112788935, 3797169575, 2613939790, 3937421466, 724668461, 2878709008, 3432806023, 1607090607, 2826908627, 2464652317, 2601849716, 517899610, 1495564723, 2048130738, 708974721, 1700315595, 2579278247, 2242949414, 3460308404, 2388581750, 2770301541, 3744537028, 296354651, 2054159803, 3468853439, 1651514110, 4062623752, 3583825663, 2794129708, 1410796364, 4156382067, 2045716042, 3813065205, 3818920060, 1665102927, 1278187702, 4009313434, 202365588, 644210309, 1756153331, 3866170616, 3814335035, 2542750399, 3813215494, 1136013967, 2960011135, 3772001369, 586861895, 3923860551, 3470266123, 1546763528, 1902195756, 3104501745, 3876757003, 2571263946, 477981715, 2126062056, 269049977, 1290930374, 1780432836, 3160595037, 1417209655, 514282678, 1164023519, 2686453333, 3115969734, 4190938631, 3186443622, 1676171819, 531295352, 289168154, 1114096636, 3168586877, 613594858, 2970263844, 3449924674, 2658965313, 967110856, 3220039975, 4215063520, 3507754767, 133270519, 2334205217, 1831822689, 4262324268, 2309134077, 3999156807, 1791457643, 1256641239, 2242142944, 2820499630, 1229037130, 2660992240, 818933202, 2759281905, 3717480198, 112547414, 2956393194, 104847146, 2767915613, 1000035595, 3582285923, 3478042564, 908731190, 4060768405, 2564303875, 1475213146, 1339551965, 3750107418, 1080002464, 2787912171, 2645990252, 1568173359, 664951361, 195563881, 689296034, 3577669586, 1821670119, 3468814631, 1594124139, 817555692, 3193780232, 3426486546, 3320655599, 547932385, 1410453389, 4223791522, 1233467189, 3247156553, 2734757292, 2515500767, 2584433579, 4231237925, 2317152244, 2365102059, 936827108, 3876510334, 1680648073, 940806185, 986899132, 2391798915, 422634537, 4216371386, 547540263, 1508615623, 3364355035, 879755346, 3263706333, 533120245, 3594839989, 3452469780, 4055859642, 969997840, 4262262593, 1470323769, 1574986928, 401859924, 876195122, 2787490848, 1047019794, 1456393400, 1268268486, 1049293027, 1125089723, 49962653, 2656962696, 3432712130, 3828147908, 1008783282, 745874291, 2762581508, 118220810, 3732108684, 2127208336, 2769688211, 4274667061, 2951242846, 3366367940, 1598191583, 171242379, 744919145, 3925218297, 67453201, 202729328, 1796852917, 2981855265, 162603224, 468499657, 2498928520, 1780550234, 4154629649, 159800351, 918301713, 4009883178, 1405353115, 214354316, 2158957675, 3869560785, 3877900396, 1972515992, 652141294, 2653621934, 2767765732, 2033835536, 427710690, 3066436569, 2951118745, 2329045596, 2837864401, 369661422, 2512052501, 786311077, 817972689, 1292779605, 1845273436, 3767574613, 651561746, 4135562168, 2180200113, 857186643, 3543645505, 1098876326, 1744194088, 122392536, 4006499245, 4093925068, 2047275237, 1612275511, 4243136821, 1515518053, 967094981, 4124925057, 407264616, 3939504118, 3065407383, 3923876471, 234366602, 1267806253, 2103627474, 3161503447, 548723525, 1573785350, 1523860596, 3111076351, 3089072652, 2099939967, 2484876475, 847465547, 1287516381, 1277183359, 3825284807, 1286852437, 1071051944, 4211214237, 1395725438, 318332058, 3887322447, 3648123837, 3980865465, 482308870, 1393337748, 953623319, 869400070, 4267388268, 299775497, 4201609675, 2407563100, 2302119847, 906313648, 1287024348, 3047468764, 1961247686, 3065780155, 896060678, 2281157811, 43993134, 3759084138, 1257965196, 1712831923, 3118566845, 2952627404, 2536493762, 2411795120, 3620642444, 3555288174, 1116895018, 1021126205, 2579096287, 1020205963, 394251755, 2996670176, 1892934138, 2242747270, 2871062637, 1033916190, 233778528, 902809453, 2423438132, 3603630196, 3726742054, 3963756768, 2091120815, 1461915071, 846990542, 1140814264, 532282751, 290247034, 1413926893, 2836815229, 1545937634, 701427847, 6966619, 2521894691, 568079964, 1507550789, 1269329413, 4901133, 844581979, 2159007935, 3652623993, 2311865120, 2809893775, 2653658358, 559868372, 1797422291, 2403522696, 1340592093, 2909871519, 4258339860, 1990498435, 1747735562, 3443076647, 2839280610, 2198844475, 2969323320, 4067837666, 1809216562, 4213935392, 3721239890, 3110124671, 3633212240, 1076094898, 3492681148, 2990603686, 1282671129, 1162631073, 2299938114, 60794983, 556699268, 1151569257, 3492507535, 1719539824, 3827661008, 3541062702, 1295482877, 325546474, 810665070, 4164189352, 2550548701, 2227159188, 4052323447, 993650554, 624459010, 533363840, 3136167651, 1714985727, 2299507153, 3401403375, 2596403792, 2580829190, 1005216955, 3292487673, 389098899, 107392208, 698445074, 545507873, 3517962883, 3506980695, 2035236933, 334294539, 1567596363, 2975991617, 69070131, 108620399, 366436780, 2456257228, 300297627, 2562984799, 2934600429, 1729676149, 4066392674, 4085843569, 3296227094, 461743932, 3702256193, 2997713007, 1135886905, 2600348129, 4141089304, 892518749, 3058189666, 1934930462, 4153963847, 4252640004, 4262502844, 1253456044, 1961771953, 680562507, 1185858068, 634477484, 2339411358, 2164550300, 2803986401, 924455038, 3134526645, 966348986, 1453429154, 3082418575, 401225239, 3398590724, 128059633, 2178637212, 1774922230, 2255178215, 2918720795, 3327682099, 2214394442, 3099747606, 1661934883, 1298729894, 1272558632, 4053018305, 3789054773, 4131648440, 1773101876, 686931174, 1203446895, 3752734552, 3235657405, 1944360014, 697623102, 2039237867, 3348886781, 2064524654, 3039942319, 2701235418, 3767389087, 916901041, 48586650, 1416585478, 766915953, 3115924685, 331229169, 3134725341, 3457203708, 741448579, 854943645, 1524960723, 1896889580, 1713382254, 2640180408, 3592536589, 1428546938, 3838033608, 3778145355, 3664325161, 542063487, 529023584, 2782480714, 173629044, 958820397, 774948118, 1930508109, 1674876078, 3703541375, 3024990950, 473593431, 1202061697, 115478614, 3136639346, 3545390288, 2091581374, 2249203480, 2052969632, 969919597, 795131713, 546537563, 1302855058, 2724277934, 1751639184, 100232597, 3423489601, 103164049, 1984156416, 3109944603, 3809627092, 3362560613, 1292767536, 1281284953, 989446818, 2926075470, 1217424046, 1358302685, 252442366, 3489051572, 2648229374, 3946622689, 3719323628, 1749561368, 3345174159, 938188313, 693952393, 3443621184, 2911849094, 1427624214, 3678446744, 2906392205, 2445546247, 1977949039, 801684661, 2963795503, 3386667543, 2100145413, 936768746, 1593174171, 3875136524, 2590738188, 2890201611, 216936927, 1339115234, 2635418552, 119932717, 1340581782, 4144168239, 3938057468, 1168936260, 2215987317, 17184998, 216656204, 2188297832, 2061448228, 1202480390, 1405676949, 292664855, 953177361, 3172167692, 2503470625, 1562534091, 1387760951, 1505457322, 592131196, 3951980740, 1017622275, 2281682949, 2074963044, 3329400423, 1404464938, 3295703205, 3486575395, 2090288146, 3184219409, 761918532, 2960208185, 3763970070, 833445184, 267175292, 572901486, 770701766, 2145108431, 3628405341, 1694398934, 377464778, 999531056, 355730920, 1936325012, 1976818811, 854711443, 132862578, 1207569573, 392699403, 1081010007, 836817039, 8548126, 3978550150, 1419003753, 972930310, 1428068521, 4209168748, 4197520795, 3943327582, 99781339, 1496418041, 970974632, 1028307344, 2504293859, 2296530528, 54001838, 334118403, 3633345114, 3002480798, 1813811418, 25154819, 301497575, 4275021870, 3282143209, 1785548939, 3598774548, 668914781, 3160281209, 190382091, 3606378713, 3008775681, 894795635, 2920018236, 992106311, 605405192, 1572036413, 1611796135, 3432918850, 2744331628, 1848223022, 1152080655, 1195579213, 374577093, 1687992973, 3507249443, 3508208035, 24847241, 3733363803, 410066863, 1140860417, 1186346319, 4001954674, 1781698837, 1473739716, 611800397, 2528535791, 483659071, 1465122828, 1423007227, 2160485143, 2603441040, 814091149, 839018968, 2290160391, 709434753, 3758915475, 206497337, 647739248, 1332381604, 3765956247, 2329586541, 3933384048, 2402114381, 2149614119, 2027684430, 3252300895, 3409909622, 2129462592, 3413088705, 550912515, 1884734543, 3454710353, 3089136894, 3468891844, 450825661, 1068267994, 1083780548, 1882776870, 3387913941, 2512854880, 3765561099, 2082119335, 3191790046, 3268009033, 1072301170, 989191158, 902359876, 2242814468, 2285401008, 3185723472, 1189582618, 1052972683, 3007703952, 2985550900, 2069850107, 3678424277, 1801617902, 246137944, 1713777350, 4040289926, 1552898375, 787557918, 2622943875, 3295504658, 3744612315, 3526116130, 3352769717, 3910684927, 4186388438, 3972654148, 2209684073, 3906598287, 1607122308, 4076456023, 3754124290, 2634877003, 4104847198, 2656001795, 2198100222, 3683620366, 646937427, 364412316, 2895405374, 3041104958, 2380266561, 4262451611, 1818177993, 3391440913, 2968709647, 3349770411, 1689905461, 2452371437, 776949895, 1046308521, 1592843104, 3356487469, 543456311, 4019266983, 3413881071, 2162344761, 2906465706, 604490755, 2482347066, 1465834864, 3590369482, 4006089115, 2221173266, 1680872055, 2374564413, 140760167, 935674542, 1201104318, 388802361, 3253154825, 3608163470, 375711467, 2065707447, 136847675, 3867470807, 802096481, 3359615348, 2988900131, 445520961, 2627882095, 1277600628, 1248783074, 4211777909, 1753939380, 4078827895, 2202860875, 1375887346, 1336540226, 4107127365, 3240966394, 1025999119, 2217540015, 635654621, 3012341994, 3048508986, 762061022, 3937951775, 757818976, 286528835, 2504250177, 4291469209, 793465046, 1934262578, 3603733421, 4264651251, 450041375, 3683285196, 3943679787, 4184673378, 3112966398, 2999093698, 839336387, 1252896925, 1520818592, 1996403247, 4076122584, 2679158894, 1234736428, 3277957223, 2521119720, 477707961, 2764279279, 1725521745, 189237987, 2649848870, 1921924016, 3323989910, 3497554263, 3667891214, 363811064, 4123651488, 654290867, 3828886696, 1074566784, 3529808219, 2376273583, 3188405382, 1340442737, 23366486, 177240450, 1418661901, 2772522976, 3329973480, 2499441230, 2436920109, 1677150014, 2838258127, 3248073782, 1936894367, 195979079, 3336629774, 2225225119, 2241276354, 2103330620, 867316439, 1005790818, 1435458745, 2518696085, 1500391322, 2957570195, 1399704654, 1635394112, 1448662254, 2140705107, 2354872868, 478054856, 3956581405, 2386494766, 3659886331, 1810497217, 988357149, 1183625343, 3308188244, 3864913999, 2139265159, 3106141303, 4095094466, 3908751299, 1219514066, 3934435025, 4198330136, 2716119828, 671526183, 1442746755, 2980086690, 1779948439, 3104658095, 3039535718, 2864235860, 1361081085, 3301975283, 2301937405, 64212162, 964827629, 4062021079, 463814632, 2591002819, 3034306167, 1346952449, 3616259925, 3529562410, 1407376532, 1300938695, 1831428515, 1377054337, 3494483692, 747322432, 216966114, 3109940520, 528951861, 1669013973, 101428960, 2355473679, 1271448808, 296701278, 268703676, 3772961132, 1364096698, 3595360819, 3834654495, 245756468, 1180671694, 3059654993, 1665841701, 4037643682, 1968685444, 4003118090, 1863308596, 3388905742, 4159463735, 4075930631, 3935486025, 2840325144, 18372419, 922566678, 3339869492, 2322470770, 2065294276, 4265824751, 429328514, 2074833244, 2599110511, 369418826, 3008438327, 2290841232, 2261453789, 3219343987, 3835916688, 3330072907, 1011610559, 4028138841, 2334037885, 1160961116, 3783760846, 4129099787, 3347763102, 1542597118, 2667694424, 1899324085, 4271282956, 446119665, 1742983316, 1490047357, 3496881782, 1609204238, 1618233545, 1446118922, 3059663537, 2392848332, 2197177262, 4202324988, 830381121, 3172287659, 2284794296, 60048962, 776939908, 126368955, 3335316768, 1617224322, 1887735485, 1166521152, 2051868066, 204477206, 2610832849, 1270236219, 2858895839, 2259287190, 562086365, 192678119, 206934813, 2586951728, 915075661, 1531503276, 2422154569, 52428317, 3158676597, 3151131876, 136530275, 1767843437, 272791438, 3828859553, 1225138750, 163687616, 3525118791, 2535968361, 1924379683, 283228722, 4163469205, 3564332148, 2796953478, 3876635722, 2631269302, 435019165, 3612086867, 3922297398, 2481322386, 2240232460, 264330793, 665379893, 121343689, 3341464458, 1276481244, 890467371, 2406267556, 2548172784, 1555519749, 2624817350, 2649640810, 2008390522, 3369404910, 3318100808, 4221083403, 876058551, 1611683033, 3782414641, 927777450, 88074630, 1295423080, 4122276692, 3546635644, 1290910992, 1656784313, 1878676100, 994393490, 2611964229, 3332196493, 613467795, 4227931323, 628818521, 810178104, 4187267638, 3258744627, 1124346594, 2242608757, 1767743392, 3960871431, 3694411882, 406926017, 881968001, 1110666426, 2373577393, 1816382483, 3578792736, 3059987612, 1362889724, 3276050088, 85597552, 3955182099, 4190966009, 210511877, 182308482, 2970087804, 681329385, 217312993, 3140854657, 4199572816, 2423266165, 611338832, 188684622, 387654540, 4208113919, 938495321, 245698576, 2592260049, 4067163288, 519701160, 1490532584, 3677927251, 4258482849, 3236806675, 873090172, 1615040788, 2684458162, 1214354785, 3808440737, 2406008869, 3692493629, 1219697942, 2285892661, 100870168, 3388557595, 2876509547, 4244766014, 1017137375, 3662418421, 4236747106, 837030183, 3878772957, 442432073, 2350568850, 1377998755, 580739246, 3664426859, 4221279304, 1015619724, 2788248972, 760252494, 3392520063, 2585360397, 140810933, 2492079891, 1783515673, 3751207447, 1323412246, 3653658141, 1639014292, 887227458, 2465064055, 3023598037, 899722089, 2706288424, 1998284933, 2926476733, 2950172024, 3726696397, 2404322937, 1986985484, 1863053903, 4292239694, 1500243239, 2477397953, 1886915350, 314868887, 285534487, 238835718, 2091997051, 1712504340, 2535782409, 1059481183, 1551367995, 2569309609, 164825691, 4197566908, 3007996085, 734721121, 1075862748, 1190607349, 3085176370, 2647730445, 276950387, 4188313125, 2644079881, 4268419844, 2118105082, 2838182759, 631686819, 4049268588, 1213849385, 395500072, 411452014, 3921892342, 1428122391, 3020360899, 3699851885, 2119420335, 1032914977, 911509677, 379170830, 1931756689, 2671028834, 2596306004, 524457754, 2484367232, 3969243802, 2002483508, 3535862321, 4168823426, 4122856522, 299191719, 4043906305, 3530247806, 3073040578, 2219836713, 1533630862, 833955854, 3525350202, 1111680468, 3599551819, 479339782, 4188026562, 3947101234, 3309992746, 4150344305, 1712302447, 971968892, 694304293, 4189216769, 650392268, 2475725134, 1112484223, 4067521798, 1457755946, 1198460815, 1448917123, 644122951, 1977075137, 2680431395, 2297523471, 758780438, 2362536223, 69290711, 3355651817, 2497463781, 3637278974, 817056241, 1618493172, 3238323388, 2576549002, 4134473192, 3941966929, 2468389041, 1989550973, 939185326, 154995083, 1050055328, 603118324, 3385201150, 1906746781, 2510736761, 1496731781, 3576997247, 1620074651, 1769919649, 3212241368, 2437369289, 2845004733, 773974037, 2057141058, 3506691796, 1774264143, 835045567, 2654816287, 1511846672, 1592372689, 3063102665, 1560480091, 3994960161, 776324825, 3819796470, 898988127, 37164863, 1744209023, 1089382200, 3694627204, 732493949, 763581103, 2631056564, 176492295, 121624993, 3815059473, 3075385449, 156121253, 3028625679, 4214466001, 2335965654, 2130896272, 3930208737, 3555403653, 3702865481, 3804078449, 3050736921, 3869289586, 2102279214, 3206425581, 267786710, 3483225109, 522553985, 1984826481, 3217768625, 3838297603, 3405536892, 2966997336, 2902635966, 2810651474, 2195519725, 4153919922, 3765936022, 2391008672, 415766461, 3494083590, 278039419, 2195922263, 3358034390, 3985136598, 3706836517, 319317636, 1266735212, 2648411005, 3052965502, 3860521030, 1335678431, 898803396, 2771426331, 1100294411, 837103846, 1822781033, 2468563788, 2652326495, 1237920364, 3888314952, 3703270820, 2334954536, 425709917, 2923195959, 3781553520, 2481380595, 2836201082, 4163743559, 1856271548, 2514914438, 2659740167, 994689845, 1754129636, 2572270539, 933071740, 3238911884, 2140596641, 2324809811, 2447233246, 3944524476, 1464590026, 1783468988, 1426484230, 2831036641, 669953331, 2467395863, 1346745881, 28384490, 520057360, 2605156811, 3547641364, 3968632337, 3586137855, 1829248118, 2877202640, 3505134530, 972761720, 669880678, 2736668092, 1806406495, 3613308561, 3957011249, 2148405107, 4260751448, 2998225713, 2338191432, 216214347, 4183131890, 374916817, 2884617705, 3296738403, 2074837837, 2384235627, 3030717220, 1950687430, 967763135, 4071323483, 3730628609, 2438950210, 1779914608, 3291569149, 472167750, 3873972683, 3746688843, 3288172257, 1586008060, 20146320, 1356698249, 1241784905, 896604945, 3504660141, 1230568406, 2418737165, 859280916, 4002301486, 2466760865, 834105222, 3254855025, 3968071974, 4123415200, 1521003134, 2749958796, 546877786, 1779121903, 918664084, 323508737, 2959053504, 2234275880, 391098989, 1525191645, 3014675896, 840073045, 2289738632, 2626990270, 2617163262, 1509589768, 1658571743, 3968660159, 2750932338, 965382975, 3744578296, 63238114, 1420213534, 3547158310, 659688884, 1687362145, 3671914268, 4088722031, 3129154158, 2800628987, 2056370583, 655540043, 419330238, 3477754734, 118810913, 3783215471, 3617854122, 2773406457, 3398689703, 137446866, 3445441869, 1377752025, 102773113, 1428576867, 2126861301, 282024782, 137965689, 799908253, 2747012194, 2588842274, 4079593773, 1884796491, 2089878589, 287438453, 3042459900, 284156012, 2194328180, 2537630290, 1115213252, 1000033505, 2054992007, 4288536260, 3809982695, 3143688764, 912790607, 2690711376, 3282737600, 1757552909, 1662483187, 2906946034, 2589432661, 3764809557, 3954618893, 2997905021, 378410012, 2557433717, 2315034839, 3168371113, 1074613870, 3685021357, 2666944892, 667360674, 392247007, 1963080100, 241189372, 2383220828, 273454969, 2699152244, 1178758254, 3686978906, 3588348050, 475514283, 1401569874, 2822156896, 762344480, 1302677715, 1336163239, 1574429530, 2438801066, 3464343842, 2773171098, 800437683, 1988558023, 3139930912, 2680545639, 2517347885, 381423133, 3749204297, 171704872, 4110583193, 4082557234, 4117643302, 1581712990, 1478575912, 3213409795, 3570398407, 199363141, 74998573, 1497480030, 1588902796, 2182716742, 2044279866, 2530715733, 3631828882, 3028359850, 3296477370, 3712890920, 695166871, 1681668033, 2116068277, 541304010, 98394159, 3675545603, 4167725043, 3036031561, 2203689734, 1365103893, 128733363, 2267978244, 2423691027, 421730605, 1133375285, 1488361202, 921779168, 2401667552, 103926809, 3304404846, 1435097879, 104836756, 2621606060, 1212958061, 2886318131, 125706275, 3458107714, 1923375310, 1974177254, 1379184218, 151282965, 1974411302, 3532138499, 3129890017, 493207508, 3855901937, 385431260, 593699630, 2003604462, 1273493881, 2534089857, 3801017963, 1391378122, 4052598581, 1493885943, 2547139892, 55775400, 3393276717, 3022286702, 3556257769, 4073739050, 3010324859, 253360788, 1769675721, 4198702190, 3004501396, 934221364, 2043508053, 3285425528, 1261525380, 1643528647, 20941045, 2937444647, 2920811364, 3721095811, 3980254979, 4082099366, 2207357842, 2397279974, 3133632668, 3858259510, 2205386556, 3119367462, 1226554211, 1383031614, 418493331, 3495739858, 3765303024, 1618904366, 247540363, 234268079, 2441128017, 2008348718, 965984916, 2881602286, 2608102654, 2300847274, 3891718353, 1421948487, 3557204590, 612553182, 4060595648, 46753808, 4050162968, 1338654448, 3060241317, 2974986277, 2158728563, 1980012232, 3427060807, 4039506494, 3687711103, 2625388131, 122917169, 65262652, 1710153668, 1062178371, 1192911872, 966332844, 2929033267, 4175997317, 1820552271, 3990059567, 2738720326, 1415735781, 1747006787, 3680962248, 2550782445, 1472091463, 2408227745, 659637885, 1330226362, 3165519011, 2780611834, 3779279541, 3640745291, 3531581467, 617584482, 2625316976, 2964566776, 2366391382, 373228345, 3957914969, 1258771463, 1731935395, 810067909, 2605132175, 1840584492, 4079026219, 4094595850, 829301813, 565188508, 1263030380, 3726343757, 918653651, 472976245, 4286770577, 4036012761, 3176300564, 1107071008, 4144843702, 25492461, 2207649467, 3633977115, 2147514019, 1269991726, 2683965438, 2520639319, 3086660719, 617169064, 3432492192, 3710672959, 3409402126, 119439117, 3963100196, 3342998301, 3693521188, 1853335107, 2389605201, 2872784581, 2317685454, 3978854958, 3380967256, 4286235050, 1349107910, 1969512853, 4208086344, 581163757, 1082760289, 738048249, 1202565794, 565233861, 3445288398, 3039896709, 2880462484, 2474618602, 1513485029, 2142309807, 683739876, 378146407, 604326311, 2048166999, 2597099427, 4072040838, 1755442901, 2907595452, 3467550225, 250062363, 56058708, 1145710399, 3039069222, 1308673449, 1714524366, 581730562, 2761367556, 626014288, 137071648, 470268228, 1437302621, 2321627765, 22353300, 1332773166, 2159532786, 2158846563, 2373532852, 1862594729, 597810252, 2340972379, 3639427609, 1007863785, 695030942, 3011496664, 270375172, 506179402, 2465725939, 3586616372, 2004336589, 2540593231, 3053313124, 242205516, 1129472933, 2423477390, 2905078481, 1273830886, 3684442720, 1606743201, 1856404822, 997845042, 3493020698, 3764183901, 1210713036, 775445903, 2693348863, 1544199589, 4134758141, 2289181799, 2575820269, 4039240160, 1927565098, 2469436858, 1147407442, 88722021, 4251027513, 3943603541, 3343042023, 4136117766, 1408968078, 2011730517, 1115400444, 91805388, 3797413122, 3231843740, 254866909, 50348931, 3008475074, 4096823241, 806995214, 579016061, 224913061, 3452629625, 3935452158, 2158823384, 443232806, 27590422, 1626003736, 1659214230, 3730751274, 3304817447, 2126464234, 468094899, 2004841401, 4244266212, 3191633815, 621908138, 386502901, 3160550164, 1846013869, 3929062208, 1752551945, 2020989829, 3733195509, 3332803772, 568035707, 677499620, 887350633, 1910823965, 1074653760, 2669527160, 223941914, 3638297358, 3976028732, 2153246112, 3107649886, 2225817653, 365559041, 2590903965, 4267229921, 565109787, 1465231336, 1031473275, 1393103622, 3065248441, 874527608, 4007090012, 1754535205, 468826697, 3193473952, 2427827474, 3093649161, 3340523605, 538785320, 540707646, 1138431196, 390508078, 2231744465, 3431900471, 2267895721, 2586776002, 458121288, 4151047880, 1794590530, 2207519743, 757299014, 2917271579, 2795562629, 2743741909, 1960280979, 662426508, 3129251070, 3284489896, 2860828673, 1665561966, 243380736, 1919574277, 2539834250, 806470044, 1347773453, 2588536886, 1735157907, 2984222123, 3613443173, 2161200535, 1139265877, 428233703, 3310537775, 130112178, 1688164348, 1800051748, 302537661, 2956495443, 1641859068, 47107059, 2547135481, 3629305242, 2304666342, 2953885877, 4274433508, 3596400581, 979899601, 1408111447, 2891516400, 3148158100, 2198724832, 3377935260, 3741107224, 3692011552, 589770358, 1491910442, 3070679896, 96783584, 1097094582, 718459446, 1566463764, 2251827675, 615019287, 3547997145, 208891375, 3237297624, 3017013184, 1351182236, 3220242871, 1869677733, 2552355223, 2314224878, 3646448768, 827517565, 286583396, 2545551636, 1652513092, 2288536082, 1104922507, 1453694202, 3747222584, 3724572766, 208872447, 1298083301, 2440775047, 490732369, 2579372015, 773048301, 3117989885, 3093360594, 2944738427, 3420927373, 610089166, 3465176652, 2026748904, 893684058, 1051908742, 1631921016, 3068536731, 2517988527, 1237193610, 1186253081, 3445268010, 1527128720, 52389139, 2272891438, 4216412582, 162836209, 285766621, 1450011463, 2529126133, 2774138060, 363705296, 1046202433, 2342962096, 3660787056, 1475962584, 470852430, 718191714, 616824852, 76199732, 1858152976, 4018570617, 3978103382, 2630348100, 3609233488, 3189344713, 2518740409, 3931673493, 1974038003, 704660170, 3939759283, 28317915, 155880200, 98267554, 2179068966, 1621791391, 3883686925, 3889013631, 3901334391, 595696176, 2056195920, 1766401898, 3894355593, 374485636, 3627058850, 2345537203, 774497303, 2739386687, 638042094, 2714586176, 3681906252, 3586849617, 2279548160, 2388695521, 2729026787, 3921872454, 2742643549, 3256050029, 3524792649, 900652251, 4027843931, 1664123130, 1693946364, 1091032684, 3229605164, 3138471477, 4076063116, 1921014030, 703457671, 3778215254, 2874553061, 1977925591, 3474710324, 1397524114, 1639376206, 1365339786, 1396788688, 4170383281, 2374091079, 917644604, 923930747, 335414501, 2894224106, 2132047599, 2139834955, 893152688, 3658071072, 1808034793, 3992989059, 541814478, 2467639183, 4252046925, 2221776604, 4010357422, 3280876308, 2195433621, 605914166, 3580984135, 1849716108, 1379095441, 1444911407, 1727601442, 1107293059, 1360518929, 3882144763, 2304676291, 3161709325, 4202670520, 1726836122, 1352003231, 1211530831, 1428143025, 233742132, 254065558, 3778834684, 2960826649, 3846707853, 78125009, 3035610100, 4248789418, 1988353666, 1488294629, 2658401083, 826190428, 982579292, 2611299229, 607386192, 383744560, 741541151, 685070534, 839618609, 168365358, 3600193535, 3516963691, 3847439236, 59984269, 3531750322, 4110124503, 1832015299, 1109782285, 224715854, 1368486105, 2896734990, 1631277553, 2122909256, 1329180973, 3883429764, 2709763270, 1485532223, 1454163641, 3877647601, 1314197322, 2191792264, 1547290652, 2767848576, 3165457667, 2615232590, 3554360090, 3461892227, 437444488, 2530137939, 2811265237, 1462499144, 344905227, 3209896933, 2633921104, 1629316777, 1898326951, 1699291982, 3173676758, 2413271387, 2308589561, 3010504667, 2318476122, 4283542195, 3136680355, 1274070214, 3634534510, 1621178665, 2720726580, 2557726616, 1593800629, 3618016530, 4222420581, 1427771311, 2709604213, 3380881521, 3429159578, 1651149604, 851806597, 1924252937, 3042327186, 2621745230, 31459639, 1789941262, 2699969865, 4089263763, 309554426, 2416205404, 668142387, 1028045099, 2577874636, 3966935504, 4013817059, 952209219, 2464801737, 1951540594, 270149440, 3537443389, 1700303197, 1525434562, 2016801738, 1016066298, 788950372, 3301785988, 867188989, 591182823, 4147481811, 1636209026, 2870738430, 1379570794, 1718211382, 2080443521, 3117953048, 787459788, 454627963, 2241519140, 1690518095, 1687083652, 721125394, 177924742, 596379914, 3547974935, 3551038003, 193705890, 3903775616, 2791266867, 2946582821, 3677605527, 4114537380, 517706278, 2851515163, 3606961097, 3140861854, 2004897727, 2934409226, 2266809059, 1728851203, 2963852138, 3726868473, 2346475963, 3284094362, 2603029369, 1910866684, 2201562938, 922269724, 3490564244, 1223267927, 781137550, 1409009688, 1481644234, 638868594, 1299363926, 184622589, 2140815496, 972229474, 3463817524, 337587642, 1588378988, 2458859134, 734138931, 829580747, 1807474453, 1339021298, 2949169677, 2696891107, 3696602637, 1454748205, 829820794, 3565850664, 1581233802, 3083125053, 1038667479, 3614790977, 2537209949, 429330636, 3337980768, 3093601877, 4279291192, 1931300040, 3549963879, 3073864202, 3313723184, 1045894249, 3527208306, 3955141051, 1168948341, 2252748369, 1419859715, 1697615792, 1861852595, 2965412158, 2785614205, 2019081072, 3865163742, 1715960246, 538250537, 3777321518, 2012459552, 2954119463, 2929968567, 3887420735, 3803424578, 3695819037, 3864966887, 2146529087, 88966190, 3171364893, 3564359203, 2710751269, 3483003647, 2389828945, 3033472226, 4212945272, 3200039382, 2723039734, 1234116526, 1847511553, 1554459841, 490403964, 2702426000, 1360638205, 3767662172, 978930326, 1673983766, 2622724213, 1465277083, 3276263245, 104027788, 1275307451, 3713601502, 1892012973, 2561897677, 666977941, 263458652, 1205359359, 3825584411, 1772594920, 983171048, 1967517634, 2312744179, 1934059481, 237802726, 3413186583, 3980764628, 4157606392, 3321271436, 2228423185, 2951588085, 3216481710, 4263810110, 3695527305, 3201086853, 3465621870, 3115371405, 596190044, 2778927076, 1192881464, 4070672740, 1695932240, 2461613540, 3114294196, 1035068883, 1219869157, 1567081195, 3182031599, 996055887, 2184037079, 1613272888, 4138419380, 3574859260, 2772736509, 3058734564, 879110600, 1620863518, 451271243, 1423498063, 2260885075, 2287937569, 2182652696, 1959408408, 3417994095, 2762728774, 3723682981, 3620972276, 4004350412, 3852922782, 4042483673, 817590891, 4008434068, 4150679257, 1818473264, 2274062019, 1287134600, 2606536974, 2900163619, 764327663, 3380352169, 663960579, 1574962505, 908720822, 732411552, 3092799743, 89050189, 2612418392, 1167021764, 2703900870, 196466159, 4100558276, 422322268, 553572367, 3812332444, 2709890491, 1048889523, 2536724669, 1892819626, 1492915400, 4123276207, 656277302, 1950735023, 2209777636, 3597582857, 207740555, 1242405021, 2794288469, 2384281621, 789332086, 2113081185, 4033156755, 3430572545, 2514642706, 3849776156, 3999536605, 2183668944, 1797714141, 1574723027, 291326525, 1162829392, 2833518205, 312881997, 3489561035, 311193915, 226320225, 1285113431, 1105912206, 188068540, 3599336557, 2095448587, 2645627174, 3743399104, 2671665081, 4239787616, 132154633, 3481420916, 3573468186, 4187070105, 2530155413, 2924766233, 3143247818, 3915372411, 1180529697, 3971354169, 602939694, 1999356624, 874227885, 3051951772, 1059212570, 2567771044, 3659557415, 2849657961, 2790113052, 3534643250, 3382123561, 4227034791, 3266187579, ]; static final String privateKeyFCM = String.fromCharCodes(List.generate( _envieddataprivateKeyFCM.length, (int i) => i, growable: false, ).map((int i) => _envieddataprivateKeyFCM[i] ^ _enviedkeyprivateKeyFCM[i])); static const List _enviedkeyseferAlexandriaServer = [ 561626930, 633083736, 2361828362, 1447543854, 3920215751, 3977052305, 56439383, 2924005955, 2887064304, 1234943430, 194442153, 3626141888, 1509369656, 1650057872, 3519117786, 3274533490, 491826437, 533770710, 4141862644, 4187012171, 2430062877, 2907455038, 1742678927, 2296049884, 1760389566, 1221398232, 935680774, 1351136606, 718685809, 2123102396, 4254062591, 2907141589, 4271154045, 1848462991, ]; static const List _envieddataseferAlexandriaServer = [ 561626970, 633083692, 2361828478, 1447543902, 3920215732, 3977052331, 56439416, 2924005996, 2887064195, 1234943395, 194442191, 3626141861, 1509369674, 1650057969, 3519117750, 3274533399, 491826557, 533770679, 4141862554, 4187012143, 2430062959, 2907455063, 1742679022, 2296049906, 1760389581, 1221398193, 935680882, 1351136571, 718685790, 2123102415, 4254062490, 2907141555, 4271153944, 1848463101, ]; static final String seferAlexandriaServer = String.fromCharCodes( List.generate( _envieddataseferAlexandriaServer.length, (int i) => i, growable: false, ).map((int i) => _envieddataseferAlexandriaServer[i] ^ _enviedkeyseferAlexandriaServer[i])); static const List _enviedkeyseferPaymentServer = [ 3057656239, 657535477, 109621120, 438746630, 2825183251, 1295398530, 1159685965, 2235676796, 2867770059, 4192319583, 1581885764, 1046887200, 2012669934, 1054936259, 1432678649, 2561003603, 3003461548, 3565878351, 1242339361, 2750710250, 3431261302, 110269137, 3725624909, 386615130, 2112858611, 2458073767, ]; static const List _envieddataseferPaymentServer = [ 3057656263, 657535361, 109621236, 438746742, 2825183328, 1295398584, 1159685986, 2235676755, 2867770040, 4192319546, 1581885730, 1046887237, 2012669852, 1054936243, 1432678542, 2561003645, 3003461599, 3565878311, 1242339406, 2750710170, 3431261273, 110269090, 3725624872, 386615100, 2112858518, 2458073813, ]; static final String seferPaymentServer = String.fromCharCodes( List.generate( _envieddataseferPaymentServer.length, (int i) => i, growable: false, ).map((int i) => _envieddataseferPaymentServer[i] ^ _enviedkeyseferPaymentServer[i])); static const List _enviedkeyseferCairoServer = [ 554285807, 2520419867, 109597109, 2517074580, 1748622146, 1589310422, 1962910500, 1388616353, 1591217629, 901955760, 3647228425, 3325878060, 3617317456, 4039807145, 3547658771, 4241136334, 382653640, 2515548320, 2900913398, 762008712, 483463271, 2574305905, 1510034298, 2817818771, 3080340389, 634186800, 1446616883, 422397129, 3810006153, 3945475093, 1466889275, 786246728, 1668712427, 127266347, 3101393660, 4048505087, 365218980, 1149306274, 1502064665, 4151910079, 2284298730, 127151816, 876052815, ]; static const List _envieddataseferCairoServer = [ 554285703, 2520419951, 109597121, 2517074660, 1748622129, 1589310444, 1962910475, 1388616334, 1591217582, 901955797, 3647228539, 3325878106, 3617317429, 4039807195, 3547658813, 4241136317, 382653613, 2515548358, 2900913299, 762008826, 483463241, 2574305821, 1510034195, 2817818853, 3080340416, 634186783, 1446616896, 422397100, 3810006255, 3945475184, 1466889289, 786246758, 1668712328, 127266375, 3101393557, 4048504988, 365219023, 1149306253, 1502064746, 4151910106, 2284298636, 127151789, 876052797, ]; static final String seferCairoServer = String.fromCharCodes( List.generate( _envieddataseferCairoServer.length, (int i) => i, growable: false, ).map((int i) => _envieddataseferCairoServer[i] ^ _enviedkeyseferCairoServer[i])); static const List _enviedkeyseferGizaServer = [ 3118946899, 1712833733, 4188235609, 599113098, 3109348574, 792973267, 1258395345, 587037447, 4003887963, 2803488395, 2456328506, 717990898, 396142477, 1454720050, 4048815160, 3557424875, 2374665328, 1079536468, 3505169905, 3184301160, 1741109435, 2836056620, 3309697657, 3934656961, 3247607243, 1499599720, 3066487767, 2683167529, 1777938433, 3705455265, ]; static const List _envieddataseferGizaServer = [ 3118946875, 1712833713, 4188235565, 599113210, 3109348525, 792973289, 1258395390, 587037480, 4003887932, 2803488482, 2456328512, 717990803, 396142590, 1454720087, 4048815198, 3557424782, 2374665218, 1079536506, 3505169822, 3184301062, 1741109463, 2836056645, 3309697559, 3934656932, 3247607268, 1499599643, 3066487730, 2683167567, 1777938532, 3705455315, ]; static final String seferGizaServer = String.fromCharCodes(List.generate( _envieddataseferGizaServer.length, (int i) => i, growable: false, ).map( (int i) => _envieddataseferGizaServer[i] ^ _enviedkeyseferGizaServer[i])); static const List _enviedkeychatGPTkeySeferNew = [ 524609778, 1506255114, 3951712514, 1694351305, 1839008247, 3483857671, 245629162, 1769242533, 3720116699, 1862455741, 3294813994, 1911310292, 3068955121, 1450475183, 358062003, 1252996373, 2313134052, 3185760878, 4235680692, 2538405834, 1389689947, 2770096344, 541499838, 1492773931, 1622963918, 337157103, 2266628558, 2643161654, 2578526648, 776056941, 913803905, 395949184, 1740835306, 2320829415, 1921378933, 938497366, 2545855153, 1966896741, 2309836703, 4250329085, 2394004957, 1406782031, 982524590, 1405107857, 2597439697, 1423242745, 861048046, 2350869074, 313537846, 3642066576, 3487739670, 1404558371, 3688027685, 3676472816, 70939572, 2915157867, 3191591920, 803835132, ]; static const List _envieddatachatGPTkeySeferNew = [ 524609672, 1506255213, 3951712559, 1694351251, 1839008195, 3483857768, 245629099, 1769242607, 3720116664, 1862455804, 3294814072, 1911310235, 3068955030, 1450475233, 358062059, 1252996479, 2313133955, 3185760796, 4235680753, 2538405763, 1389689870, 2770096352, 541499864, 1492773984, 1622963853, 337157078, 2266628502, 2643161668, 2578526656, 776056842, 913803988, 395949253, 1740835294, 2320829366, 1921378817, 938497316, 2545855171, 1966896649, 2309836782, 4250329036, 2394004900, 1406781990, 982524635, 1405107945, 2597439713, 1423242643, 861047970, 2350869089, 313537874, 3642066649, 3487739714, 1404558448, 3688027773, 3676472706, 70939628, 2915157767, 3191591858, 803835024, ]; static final String chatGPTkeySeferNew = String.fromCharCodes( List.generate( _envieddatachatGPTkeySeferNew.length, (int i) => i, growable: false, ).map((int i) => _envieddatachatGPTkeySeferNew[i] ^ _enviedkeychatGPTkeySeferNew[i])); static const List _enviedkeycohere = [ 3711539293, 4179110757, 3130863424, 2960119040, 2122625981, 3820047552, 652029293, 4205876489, 1018002557, 3268656047, 4054153249, 3736768279, 1660469661, 518561934, 3645184133, 2404489058, 175727548, 738686967, 525251142, 2845503261, 416254488, 1941563430, 2660301817, 3655308782, 3258399601, 1297901408, 3704861065, 2420328274, 4212767748, 2471409060, 510684855, 3897265290, 1890967453, 3949010443, 1810318671, 1053079416, 3414768212, 3441931396, 2546433339, 1616935716, 911576240, 1876146680, 4206294986, 82871504, 636793252, 1709251168, 3653675524, ]; static const List _envieddatacohere = [ 3711539228, 4179110672, 3130863404, 2960119159, 2122626009, 3820047608, 652029204, 4205876540, 1018002478, 3268656127, 4054153334, 3736768376, 1660469742, 518561982, 3645184237, 2404489000, 175727572, 738686875, 525251073, 2845503277, 416254572, 1941563465, 2660301740, 3655308680, 3258399561, 1297901319, 3704861126, 2420328250, 4212767825, 2471409137, 510684869, 3897265402, 1890967547, 3949010494, 1810318622, 1053079370, 3414768128, 3441931476, 2546433366, 1616935794, 911576311, 1876146592, 4206294968, 82871432, 636793288, 1709251106, 3653675624, ]; static final String cohere = String.fromCharCodes(List.generate( _envieddatacohere.length, (int i) => i, growable: false, ).map((int i) => _envieddatacohere[i] ^ _enviedkeycohere[i])); static const List _enviedkeyclaudeAiAPI = [ 4214176629, 1124638299, 2619089107, 1163611692, 992094328, 1653463158, 404137156, 2307152983, 4144951281, 299318335, 934124021, 1540305935, 928421081, 138086963, 3167661776, 1372811540, 2261648682, 2885259996, 1799144723, 3418493097, 2389110802, 2920233976, 461024631, 1752528300, 3565458959, 4095183340, 2011007996, 2726474493, 305117885, 762213518, 2758430717, 253479114, 2603590907, 1779760738, 2906738701, 4158441589, 1229764385, 798641777, 1539096011, 2989341773, 3454218987, 1822602079, 932125700, 947203612, 3655438005, 2447484736, 2956534335, 1076145364, 2247366951, 423924790, 1480298822, 1410357868, 2744154990, 1247629533, 1775582016, 454725042, 1801490831, 3579628558, 1631065418, 2465428321, 3842850690, 3133403313, 3724182006, 4080090221, 1410035498, 2171194230, 106772809, 2347956017, 2657386897, 3121396559, 4279527128, 2270046571, 1730331616, 4261065335, 3186987742, 3773357116, 3849071379, 3891297185, 831998274, 2341938365, 3284125826, 3277664265, 4041004498, 2327667910, 2958647319, 1020377745, 1862857570, 2737445225, 2191919935, 3580771524, 2375606747, 3097462976, 3930099097, 864947971, 1073786313, 3471588950, 1391122894, 1703809459, 250205428, 1750130551, 4293188922, 2386528221, 3933658081, 3186790479, 2897706107, 3287658006, 1255252420, 3569289577, 672671881, 3536109751, 995759990, 3515423137, 1044370531, 3466374959, 4006211974, ]; static const List _envieddataclaudeAiAPI = [ 4214176527, 1124638268, 2619089150, 1163611741, 992094234, 1653463061, 404137193, 2307152934, 4144951175, 299318352, 934123974, 1540305974, 928421045, 138086942, 3167661736, 1372811587, 2261648741, 2885259940, 1799144794, 3418493166, 2389110885, 2920233903, 461024547, 1752528355, 3565459061, 4095183279, 2011007930, 2726474431, 305117907, 762213575, 2758430628, 253479065, 2603590832, 1779760681, 2906738789, 4158441491, 1229764440, 798641675, 1539095956, 2989341702, 3454218941, 1822602014, 932125810, 947203694, 3655438077, 2447484781, 2956534281, 1076145291, 2247366931, 423924844, 1480298755, 1410357798, 2744154914, 1247629547, 1775582072, 454725109, 1801490896, 3579628639, 1631065352, 2465428265, 3842850736, 3133403271, 3724181913, 4080090120, 1410035582, 2171194169, 106772740, 2347956092, 2657387006, 3121396510, 4279527085, 2270046476, 1730331609, 4261065276, 3186987691, 3773357171, 3849071481, 3891297227, 831998217, 2341938414, 3284125906, 3277664342, 4041004435, 2327667954, 2958647364, 1020377762, 1862857521, 2737445180, 2191919995, 3580771496, 2375606713, 3097462968, 3930099147, 864948026, 1073786285, 3471588899, 1391122840, 1703809481, 250205339, 1750130470, 4293188887, 2386528144, 3933657994, 3186790423, 2897706020, 3287658051, 1255252373, 3569289528, 672671960, 3536109807, 995759876, 3515423225, 1044370447, 3466375021, 4006212074, ]; static final String claudeAiAPI = String.fromCharCodes(List.generate( _envieddataclaudeAiAPI.length, (int i) => i, growable: false, ).map((int i) => _envieddataclaudeAiAPI[i] ^ _enviedkeyclaudeAiAPI[i])); static const List _enviedkeypayPalClientId = [ 3964014192, 328188734, 3257917027, 2981524744, 762854651, 1278558590, 1661686812, 895551114, 3658160604, 667899397, 2615598432, 462222434, 727405441, 1476120821, 2647811886, 423093032, 2993338011, 3614899073, 2340119251, 3382347015, 427437223, 3792647783, 3921607588, 3512761770, 756769182, 1603520082, 3515462204, 232329925, 2410859774, 2460361885, 820845086, 4183500369, 1931262151, 1689992696, 120545701, 3879827173, 1602543592, 2969825002, 61485072, 3202981946, 1897507982, 2652734676, 540379785, 149357530, 4027904299, 2118640306, 4265962279, 1539190296, 3268313462, 1830550448, 1442658137, 1019852816, 1010645669, 1870250713, 2044570364, 303096386, 128904340, 3176115966, 1276339843, 3734426547, 309957214, 2899021254, 4937236, 2273386592, 4103933378, 4095644960, 1299370727, 3423053014, 2037087516, 981965453, 3817839937, 3513283066, 3550082144, 1079634613, 167744721, 1383127324, 398219827, 3256593277, 3441359548, 553036197, 1871961202, 3081272338, 2000847044, 3135285297, 536392156, 1633610110, 1169847617, ]; static const List _envieddatapayPalClientId = [ 3964014113, 328188799, 3257916975, 2981524849, 762854550, 1278558482, 1661686906, 895551172, 3658160533, 667899440, 2615598388, 462222360, 727405557, 1476120769, 2647811933, 423092997, 2993338082, 3614899186, 2340119228, 3382347133, 427437201, 3792647697, 3921607648, 3512761758, 756769217, 1603520060, 3515462221, 232329885, 2410859726, 2460361934, 820845131, 4183500325, 1931262124, 1689992635, 120545786, 3879827092, 1602543537, 2969824956, 61485117, 3202981999, 1897508073, 2652734655, 540379836, 149357501, 4027904330, 2118640383, 4265962360, 1539190304, 3268313388, 1830550429, 1442658098, 1019852919, 1010645649, 1870250645, 2044570313, 303096433, 128904447, 3176115910, 1276339926, 3734426566, 309957158, 2899021209, 4937248, 2273386506, 4103933319, 4095645047, 1299370687, 3423052946, 2037087607, 981965507, 3817839921, 3513282978, 3550082087, 1079634662, 167744646, 1383127372, 398219843, 3256593204, 3441359558, 553036257, 1871961140, 3081272394, 2000847030, 3135285353, 536392112, 1633610044, 1169847597, ]; static final String payPalClientId = String.fromCharCodes(List.generate( _envieddatapayPalClientId.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayPalClientId[i] ^ _enviedkeypayPalClientId[i])); static const List _enviedkeypayPalSecret = [ 715208699, 1261465271, 996598473, 2478052279, 310595984, 2720144039, 1222666862, 1737960009, 1327584488, 2592973739, 2996394985, 1421742627, 1995798153, 2825846452, 2156655438, 2273550156, 269635613, 3923388057, 3343844740, 1995132694, 398583486, 3882255302, 2943192425, 3774776326, 1373436436, 3710933937, 4144917625, 3822097863, 2166662208, 2911530014, 2689032097, 708369246, 1107873132, 2229621984, 2562011064, 4230198198, 3772901992, 40779790, 1010882163, 2689693377, 1090903845, 2724700338, 2599493679, 3026550268, 2362691949, 2830309503, 1598854625, 2777978578, 4229328334, 3764251393, 2312746858, 1843437368, 1030656526, 188717711, 1484094219, 3725653090, 2694512916, 651913169, 6389417, 2939466111, 1605509358, 481546583, 3874331467, 1129734256, 497233076, 1949853791, 3370723743, 2975592290, 1413242222, 556588420, 1975577321, 310810944, 217365406, 4261566681, 3063855803, 3984859365, 441697722, 4061772989, 2250337636, 2718952207, 3214026095, 2160181562, 993668501, 3221559055, 2224265074, 2719932205, ]; static const List _envieddatapayPalSecret = [ 715208625, 1261465333, 996598408, 2478052342, 310596070, 2720144086, 1222666788, 1737959960, 1327584431, 2592973822, 2996394906, 1421742696, 1995798221, 2825846404, 2156655380, 2273550118, 269635701, 3923388077, 3343844815, 1995132796, 398583515, 3882255269, 2943192339, 3774776446, 1373436530, 3710934003, 4144917567, 3822097855, 2166662253, 2911530029, 2689032089, 708369165, 1107873032, 2229621900, 2562011098, 4230198271, 3772901947, 40779835, 1010882117, 2689693335, 1090903927, 2724700415, 2599493655, 3026550194, 2362691881, 2830309401, 1598854532, 2777978596, 4229328291, 3764251499, 2312746791, 1843437405, 1030656596, 188717765, 1484094307, 3725653036, 2694512984, 651913115, 6389452, 2939466004, 1605509339, 481546511, 3874331436, 1129734177, 497233143, 1949853742, 3370723796, 2975592225, 1413242150, 556588528, 1975577275, 310810918, 217365416, 4261566612, 3063855825, 3984859319, 441697731, 4061772944, 2250337538, 2718952247, 3214026039, 2160181576, 993668557, 3221559139, 2224265008, 2719932225, ]; static final String payPalSecret = String.fromCharCodes(List.generate( _envieddatapayPalSecret.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayPalSecret[i] ^ _enviedkeypayPalSecret[i])); static const List _enviedkeygeminiApi = [ 897972057, 3451866454, 498583348, 4232329306, 746850959, 2080038489, 2981238258, 2239809128, 3452607695, 4110806216, 681493908, 3964436933, 525233958, 3061353075, 1246732706, 3959080873, 1758700133, 3044791945, 2430431056, 3044887698, 1033900895, 331508253, 2471939397, 3918243840, 2529846383, 3844772569, 1036254075, 1872953211, 3670441247, 3249352087, 879919608, 3751924622, 4136608280, 1707172270, 2398871554, 1688096575, 3758666320, 4013790547, 2652210672, 3933941563, 3009434839, 1160634384, 2822833044, 1691539047, 865047485, 348233834, ]; static const List _envieddatageminiApi = [ 897971976, 3451866393, 498583385, 4232329259, 746851029, 2080038442, 2981238179, 2239809073, 3452607650, 4110806264, 681493932, 3964436915, 525233994, 3061353020, 1246732755, 3959080899, 1758700076, 3044791998, 2430431035, 3044887806, 1033900809, 331508311, 2471939363, 3918243958, 2529846335, 3844772589, 1036253996, 1872953145, 3670441305, 3249352146, 879919511, 3751924715, 4136608373, 1707172292, 2398871653, 1688096582, 3758666339, 4013790570, 2652210630, 3933941586, 3009434767, 1160634466, 2822833100, 1691538955, 865047551, 348233734, ]; static final String geminiApi = String.fromCharCodes(List.generate( _envieddatageminiApi.length, (int i) => i, growable: false, ).map((int i) => _envieddatageminiApi[i] ^ _enviedkeygeminiApi[i])); static const List _enviedkeygeminiApiMasa = [ 1068867104, 789257086, 2374344205, 435412262, 3147772022, 1418727241, 3478566266, 260647262, 1581763645, 4236797141, 1188141620, 3886173370, 146107725, 2771412392, 58681471, 1211448302, 1196653291, 2982162803, 2595440940, 4038610731, 4160079213, 2738477577, 3385793863, 1602812657, 2015749603, 229017089, 3804968053, 962800061, 3024940641, 1212539540, 1360148835, 1408053521, 3429000386, 649946, 2087677916, 3383687339, 3251681117, 299934732, 1422286964, 866458004, 1010537299, 137700404, 850882077, 2135461630, 3085155084, 783334757, ]; static const List _envieddatageminiApiMasa = [ 1068867185, 789257009, 2374344288, 435412311, 3147771948, 1418727226, 3478566187, 260647191, 1581763661, 4236797105, 1188141689, 3886173326, 146107663, 2771412474, 58681356, 1211448229, 1196653190, 2982162706, 2595441000, 4038610785, 4160079138, 2738477657, 3385793904, 1602812565, 2015749561, 229017201, 3804968000, 962800016, 3024940546, 1212539554, 1360148781, 1408053574, 3429000356, 649913, 2087677876, 3383687324, 3251681037, 299934797, 1422286872, 866458053, 1010537227, 137700422, 850882117, 2135461522, 3085155150, 783334665, ]; static final String geminiApiMasa = String.fromCharCodes(List.generate( _envieddatageminiApiMasa.length, (int i) => i, growable: false, ).map((int i) => _envieddatageminiApiMasa[i] ^ _enviedkeygeminiApiMasa[i])); static const List _enviedkeyagoraAppId = [ 2081958950, 3344593607, 1531753513, 2899020569, 869569789, 3295793548, 3082998270, 1277945613, 1162903749, 3972314168, 2730389472, 2677575780, 3810492656, 542461687, 2742222978, 3348808301, 2181751558, 1577905018, 1917907079, 364195670, 425739494, 823877058, 456543235, 3687427185, 3045999446, 3072327834, 294249014, 3900947542, 3761384921, 3382746976, 2311171750, 3912269023, 1002146462, 2802304975, 3672302120, 2454273928, 1301961603, 2322647617, 2106877078, ]; static const List _envieddataagoraAppId = [ 2081958929, 3344593654, 1531753489, 2899020577, 869569741, 3295793642, 3082998220, 1277945703, 1162903795, 3972314123, 2730389462, 2677575691, 3810492613, 542461639, 2742223035, 3348808199, 2181751604, 1577904974, 1917907198, 364195683, 425739476, 823877115, 456543287, 3687427141, 3045999470, 3072327850, 294249039, 3900947557, 3761384937, 3382746901, 2311171742, 3912269035, 1002146470, 2802304919, 3672302170, 2454274000, 1301961711, 2322647555, 2106877178, ]; static final String agoraAppId = String.fromCharCodes(List.generate( _envieddataagoraAppId.length, (int i) => i, growable: false, ).map((int i) => _envieddataagoraAppId[i] ^ _enviedkeyagoraAppId[i])); static const List _enviedkeyagoraAppCertificate = [ 1231343090, 1126238149, 2870548765, 2368799538, 2481968720, 811443040, 3018369170, 4249215140, 1068794062, 1747859621, 1256909121, 514271897, 2763397915, 2035587145, 156033108, 1681890820, 1886740530, 1884712524, 224080234, 3924776020, 1905483324, 450048921, 1945734337, 1950078510, 1350520675, 965205544, 261890511, 1757528176, 2969984316, 2637097007, 819491548, 3063824946, 786426118, 1168115103, 1869856400, 396491045, 3188443334, 3766826677, 3664921460, 3067285639, ]; static const List _envieddataagoraAppCertificate = [ 1231343000, 1126238196, 2870548778, 2368799555, 2481968745, 811443028, 3018369190, 4249215185, 1068794106, 1747859612, 1256909170, 514271904, 2763397931, 2035587107, 156033084, 1681890933, 1886740485, 1884712569, 224080210, 3924775969, 1905483277, 450048943, 1945734389, 1950078487, 1350520663, 965205532, 261890551, 1757528065, 2969984270, 2637097046, 819491562, 3063824970, 786426208, 1168115178, 1869856456, 396491095, 3188443294, 3766826713, 3664921398, 3067285739, ]; static final String agoraAppCertificate = String.fromCharCodes( List.generate( _envieddataagoraAppCertificate.length, (int i) => i, growable: false, ).map((int i) => _envieddataagoraAppCertificate[i] ^ _enviedkeyagoraAppCertificate[i])); static const List _enviedkeypayPalClientIdLive = [ 3340953550, 1570613616, 3376132438, 3269724962, 3804064268, 857198706, 2655838304, 1658530168, 487036806, 262438804, 4209989150, 231395561, 2176104869, 1523997140, 2510136932, 2266877306, 967569581, 2672444331, 443322639, 286613773, 1656343185, 2990159011, 1185149430, 1099513061, 2427627413, 3234351421, 2378746608, 3403941308, 1482230507, 1093780579, 781517395, 1980014253, 4076106219, 2265857702, 3609569037, 3930502253, 438896637, 3540942576, 2974158627, 2795685385, 3956621788, 1872323052, 1290224853, 161517149, 3847812425, 3059579803, 3837252468, 2561740666, 3611012111, 2995567970, 2224419204, 2512441842, 2150558508, 1252443279, 1087154235, 3619101299, 412198367, 2313075308, 1455100416, 1003205434, 3446126585, 3741444825, 1094255308, 2226626400, 194099588, 3360225415, 2665093331, 3251398805, 3832188177, 2864838568, 274314879, 4288895515, 1095258347, 2672193899, 928261495, 3489122279, 1491289826, 3106670330, 3212433909, 1505616325, 590729829, 4068093960, 2764605618, 3754850393, 502512782, 1917766414, 1760183411, ]; static const List _envieddatapayPalClientIdLive = [ 3340953503, 1570613546, 3376132368, 3269725001, 3804064358, 857198643, 2655838223, 1658530082, 487036896, 262438867, 4209989226, 231395463, 2176104898, 1523997082, 2510136855, 2266877215, 967569631, 2672444359, 443322723, 286613819, 1656343267, 2990158992, 1185149333, 1099512998, 2427627424, 3234351371, 2378746536, 3403941328, 1482230490, 1093780496, 781517317, 1980014305, 4076106170, 2265857741, 3609569123, 3930502232, 438896537, 3540942525, 2974158657, 2795685488, 3956621753, 1872322958, 1290224829, 161517095, 3847812355, 3059579842, 3837252417, 2561740611, 3611012170, 2995567923, 2224419255, 2512441754, 2150558550, 1252443320, 1087154274, 3619101195, 412198334, 2313075241, 1455100529, 1003205503, 3446126525, 3741444736, 1094255260, 2226626356, 194099665, 3360225473, 2665093296, 3251398852, 3832188230, 2864838617, 274314761, 4288895614, 1095258299, 2672193802, 928261414, 3489122258, 1491289783, 3106670256, 3212433855, 1505616275, 590729783, 4068094032, 2764605632, 3754850305, 502512866, 1917766476, 1760183327, ]; static final String payPalClientIdLive = String.fromCharCodes( List.generate( _envieddatapayPalClientIdLive.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayPalClientIdLive[i] ^ _enviedkeypayPalClientIdLive[i])); static const List _enviedkeypayPalSecretLive = [ 4150202229, 252730445, 624717246, 2264233849, 2078209126, 2839093202, 4269014238, 599368642, 873227692, 2101045030, 1865908070, 3124842957, 851226307, 3701206028, 988261854, 5749222, 585700967, 1471622276, 688943072, 2605584979, 3302215221, 3363138126, 101067790, 3391859525, 683814021, 2163047615, 88102227, 2642479401, 3395766116, 2130428901, 1574877883, 3517483116, 4064510891, 550006229, 446412299, 1992849641, 3206218430, 3866766348, 1448477647, 2408276277, 2559414744, 394116727, 1513483786, 3065814798, 3528477663, 2130023271, 2237902818, 2992738881, 4087784278, 1409606614, 2673538539, 1045314284, 3172715952, 1158308776, 3010695706, 1018070396, 2235041561, 983125766, 170008713, 2229027887, 122619291, 1906748419, 1124606812, 1915461031, 2892250470, 384380014, 539695177, 1783704777, 1568626503, 2978814249, 3682305140, 3144081257, 1099627880, 1933264226, 4028856113, 527740201, 2294419107, 2281561033, 3704438190, 635533350, 4214429808, 1335829969, 3956191903, 1658306042, 2761099708, 135803759, 2838960500, 452339821, ]; static const List _envieddatapayPalSecretLive = [ 4150202175, 252730396, 624717306, 2264233784, 2078209074, 2839093155, 4269014197, 599368617, 873227714, 2101045090, 1865907968, 3124842916, 851226245, 3701206140, 988261787, 5749159, 585700905, 1471622322, 688943056, 2605584920, 3302215287, 3363138170, 101067902, 3391859458, 683814133, 2163047675, 88102194, 2642479459, 3395766030, 2130428828, 1574877898, 3517483054, 4064510954, 550006193, 446412338, 1992849539, 3206218438, 3866766401, 1448477581, 2408276325, 2559414696, 394116621, 1513483869, 3065814875, 3528477678, 2130023223, 2237902803, 2992738858, 4087784293, 1409606558, 2673538522, 1045314182, 3172716010, 1158308800, 3010695755, 1018070294, 2235041655, 983125809, 170008762, 2229027946, 122619347, 1906748528, 1124606743, 1915461110, 2892250376, 384379919, 539695230, 1783704829, 1568626455, 2978814225, 3682305028, 3144081232, 1099627856, 1933264138, 4028856150, 527740262, 2294419149, 2281560964, 3704438223, 635533425, 4214429728, 1335829894, 3956191943, 1658305928, 2761099748, 135803651, 2838960438, 452339713, ]; static final String payPalSecretLive = String.fromCharCodes( List.generate( _envieddatapayPalSecretLive.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayPalSecretLive[i] ^ _enviedkeypayPalSecretLive[i])); static const List _enviedkeyintegrationIdPayMob = [ 2711867375, 4094106772, 66776679, 2172809628, 1407400692, 2483490736, 2796837216, 414182399, 1030457165, 2912663149, 1122981724, 4233525351, 2783465375, ]; static const List _envieddataintegrationIdPayMob = [ 2711867359, 4094106790, 66776660, 2172809643, 1407400642, 2483490691, 2796837200, 414182311, 1030457151, 2912663093, 1122981680, 4233525285, 2783465459, ]; static final String integrationIdPayMob = String.fromCharCodes( List.generate( _envieddataintegrationIdPayMob.length, (int i) => i, growable: false, ).map((int i) => _envieddataintegrationIdPayMob[i] ^ _enviedkeyintegrationIdPayMob[i])); static const List _enviedkeypasswordPayMob = [ 3476055420, 948855401, 990058547, 1518961812, 1986635851, 1630811721, 581655628, 842276458, 4065253996, 485180379, 1152419252, 3216056255, 4265257470, 1371595368, 1059014342, 2584071750, 1033576381, 3613177506, 3004037069, 580262902, 2164109007, 508249427, ]; static const List _envieddatapasswordPayMob = [ 3476055323, 948855337, 990058589, 1518961919, 1986635791, 1630811771, 581655663, 842276435, 4065253973, 485180336, 1152419221, 3216056279, 4265257402, 1371595319, 1059014376, 2584071729, 1033576421, 3613177552, 3004037013, 580262810, 2164108941, 508249407, ]; static final String passwordPayMob = String.fromCharCodes(List.generate( _envieddatapasswordPayMob.length, (int i) => i, growable: false, ).map((int i) => _envieddatapasswordPayMob[i] ^ _enviedkeypasswordPayMob[i])); static const List _enviedkeyusernamePayMob = [ 2647974768, 444760733, 1962118316, 2567217974, 2222725922, 3887608995, 186704756, 942365873, 1496646118, 3918720892, 563872343, 3403095027, 131129821, 3430657630, 3618174847, 2808387742, 3979711925, ]; static const List _envieddatausernamePayMob = [ 2647974723, 444760746, 1962118303, 2567217927, 2222725915, 3887608978, 186704708, 942365829, 1496646102, 3918720841, 563872357, 3403094955, 131129775, 3430657542, 3618174739, 2808387804, 3979711961, ]; static final String usernamePayMob = String.fromCharCodes(List.generate( _envieddatausernamePayMob.length, (int i) => i, growable: false, ).map((int i) => _envieddatausernamePayMob[i] ^ _enviedkeyusernamePayMob[i])); static const List _enviedkeypayMobApikey = [ 828685855, 2003922353, 1610524957, 4020268132, 3029320301, 584416750, 2097617338, 2656430581, 590232852, 411175381, 2899928614, 3545462265, 398848759, 3348930362, 1472599123, 1335140841, 2989526414, 936641119, 2881931450, 3001913719, 909318898, 2115369230, 58318947, 3841630227, 3101810139, 1598758, 1900929996, 2547280721, 1963966862, 3348701991, 1280746724, 2079631576, 3353966872, 3122043968, 948737010, 3025891157, 14633219, 3749442806, 3474128764, 1770506318, 561336108, 3279706293, 3057286896, 2739927905, 1214847882, 3649614550, 3740147523, 429130980, 800539962, 1747326730, 2986155220, 3784059346, 931468589, 2556053843, 1695051336, 565210774, 2394664459, 319319323, 532947566, 1327263302, 796153436, 1807485744, 2112147427, 3609764870, 2163526008, 1397560652, 1019521171, 2717159956, 1208318514, 1614487024, 2461914970, 1259364295, 179599338, 387280946, 3969139758, 1555658809, 2802707971, 993407505, 3844859198, 682022744, 1533108341, 2577239428, 233497412, 4090899249, 3120113155, 995754974, 2343578281, 3874502625, 1412892991, 611304529, 2148220573, 2651370412, 567578478, 4015976190, 3165504079, 1049204820, 1442698986, 1891280188, 3352600844, 2846403957, 3585683118, 2551850467, 3787313460, 3656015350, 3284691117, 1608015952, 515538285, 2189782421, 1391466821, 2636603430, 2468609204, 1060073234, 1648367099, 1488429510, 3551372073, 4052925145, 3440751312, 2136986439, 141138320, 2639332937, 867271229, 2617488662, 4222703897, 3774688720, 1962912687, 2580829534, 3100515184, 3915324865, 1073675234, 3728754394, 1369413785, 3562245245, 3541049993, 345953852, 1162168206, 501629054, 420299065, 1915220170, 4159574324, 3781839444, 1680872649, 1765587112, 3379185887, 143625190, 4166574612, 256377419, 3227231865, 1545512228, 3772671166, 1367331674, 4005379183, 370879497, 1396342076, 1513799130, 4106479151, 4181310729, 3150025761, 1697297906, 1132732618, 4244491943, 970445420, 2332386069, 2189073928, 2336129536, 721945876, 2169869880, 329898563, 495162007, 987261115, 1676356396, 1552712735, 1446907690, 2547715963, 3887587915, 4158817816, 269531085, 4287544153, 3525028879, 352653816, 1502259184, 4036295807, 3171019519, 1010900901, 984710380, 2005768193, 1770210088, 2571690960, 3396710989, 963943056, 3101385388, 2022568759, 1209292012, 1300298396, 265335891, 991904992, 639380949, 1431991600, 1387608946, 549994549, 2702939610, 3273679600, 2105182200, 1135393101, 3850554599, 1074156032, 4157592924, 2040967898, 2200552052, 900600526, 1431239582, 3450853379, 424812604, 748566252, 2935151763, 1639671366, 2873892173, 2657758459, 543176646, 2503086081, 1015282077, 1574915115, 1886678515, 3855981337, 144435161, 2220902159, 444189079, 3033281155, 236107366, 3474077884, 3302603211, 2529422655, 3026277571, 1583628386, 1457810148, 3115490443, 2160904624, 1741384831, 3244563283, 2971731245, 2570668609, 415852065, 2421463038, 3122969308, 3284084600, 3734895695, 4255840663, 3822252728, 4028017442, 2984043013, 2718820681, 2536154764, 1678332092, 1273993299, 3130509886, 3456560267, 1974690290, 2611477637, 1878515626, 2610704538, 3744175569, 2078175211, 1387603814, 983914748, 2294272, 2262161637, 1228506799, 3575299528, 4073732059, 3877691167, 3458866392, 2427088183, 2099442580, 1984032360, 3879635047, 3815391587, 126738788, 2410697558, 3287972020, 569488390, 346969100, 2635009835, 3894746345, 3052633828, 2319804539, 1949108754, 2466211944, ]; static const List _envieddatapayMobApikey = [ 828685906, 2003922421, 1610525039, 4020268067, 3029320220, 584416677, 2097617407, 2656430498, 590232903, 411175396, 2899928660, 3545462191, 398848646, 3348930386, 1472599097, 1335140750, 2989526505, 936641047, 2881931468, 3001913650, 909318818, 2115369290, 58318869, 3841630275, 3101810097, 1598828, 1900930043, 2547280679, 1963966932, 3348702051, 1280746662, 2079631517, 3353966944, 3122043954, 948736957, 3025891170, 14633296, 3749442757, 3474128702, 1770506251, 561336174, 3279706322, 3057286786, 2739927821, 1214847980, 3649614467, 3740147508, 429130928, 800540027, 1747326777, 2986155197, 3784059367, 931468671, 2556053821, 1695051288, 565210787, 2394664529, 319319413, 532947480, 1327263273, 796153360, 1807485699, 2112147374, 3609764916, 2163525931, 1397560693, 1019521249, 2717160017, 1208318576, 1614486935, 2461914920, 1259364267, 179599268, 387280998, 3969139786, 1555658844, 2802708091, 993407577, 3844859147, 682022696, 1533108257, 2577239508, 233497378, 4090899206, 3120113229, 995754900, 2343578331, 3874502551, 1412892998, 611304544, 2148220655, 2651370441, 567578420, 4015976116, 3165504057, 1049204837, 1442698942, 1891280210, 3352600891, 2846403855, 3585683144, 2551850452, 3787313474, 3656015266, 3284691172, 1608015892, 515538196, 2189782498, 1391466799, 2636603502, 2468609235, 1060073251, 1648367032, 1488429553, 3551372133, 4052925116, 3440751273, 2136986484, 141138344, 2639332865, 867271273, 2617488722, 4222703968, 3774688670, 1962912750, 2580829549, 3100515078, 3915324918, 1073675190, 3728754314, 1369413887, 3562245145, 3541050097, 345953910, 1162168316, 501628959, 420299073, 1915220219, 4159574342, 3781839395, 1680872601, 1765587141, 3379185807, 143625106, 4166574681, 256377345, 3227231744, 1545512286, 3772671183, 1367331601, 4005379114, 370879568, 1396342118, 1513799103, 4106479176, 4181310817, 3150025808, 1697297857, 1132732551, 4244491986, 970445344, 2332386112, 2189074042, 2336129606, 721945948, 2169869835, 329898498, 495162022, 987261178, 1676356427, 1552712791, 1446907721, 2547715891, 3887587962, 4158817837, 269531022, 4287544067, 3525028918, 352653741, 1502259089, 4036295717, 3171019435, 1010900969, 984710307, 2005768313, 1770210118, 2571690919, 3396711037, 963943122, 3101385464, 2022568787, 1209291926, 1300298452, 265335835, 991904914, 639380887, 1431991665, 1387608832, 549994588, 2702939561, 3273679530, 2105182109, 1135393087, 3850554546, 1074156109, 4157592841, 2040967823, 2200551950, 900600468, 1431239599, 3450853441, 424812626, 748566190, 2935151862, 1639671299, 2873892132, 2657758353, 543176590, 2503086199, 1015282131, 1574915137, 1886678442, 3855981397, 144435127, 2220902236, 444189094, 3033281217, 236107315, 3474077941, 3302603144, 2529422706, 3026277547, 1583628337, 1457810057, 3115490523, 2160904664, 1741384766, 3244563298, 2971731224, 2570668584, 415852103, 2421462966, 3122969253, 3284084526, 3734895678, 4255840732, 3822252797, 4028017519, 2984043085, 2718820638, 2536154869, 1678332151, 1273993247, 3130509916, 3456560370, 1974690183, 2611477708, 1878515706, 2610704620, 3744175538, 2078175139, 1387603807, 983914665, 2294373, 2262161577, 1228506780, 3575299518, 4073731969, 3877691238, 3458866332, 2427088209, 2099442601, 1984032267, 3879634961, 3815391488, 126738748, 2410697508, 3287972076, 569488490, 346969166, 2635009863, 3894746251, 3052633734, 2319804441, 1949108848, 2466211850, ]; static final String payMobApikey = String.fromCharCodes(List.generate( _envieddatapayMobApikey.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayMobApikey[i] ^ _enviedkeypayMobApikey[i])); static const List _enviedkeyintegrationIdPayMobWallet = [ 3751071568, 3933800217, 3327767708, 2603223096, 3226788798, 2152717269, 3488079092, 849365887, 4102793661, 2200028242, 3289603366, 1701593398, 1751264534, ]; static const List _envieddataintegrationIdPayMobWallet = [ 3751071584, 3933800235, 3327767723, 2603223055, 3226788745, 2152717286, 3488079053, 849365799, 4102793679, 2200028170, 3289603402, 1701593460, 1751264634, ]; static final String integrationIdPayMobWallet = String.fromCharCodes( List.generate( _envieddataintegrationIdPayMobWallet.length, (int i) => i, growable: false, ).map((int i) => _envieddataintegrationIdPayMobWallet[i] ^ _enviedkeyintegrationIdPayMobWallet[i])); static const List _enviedkeysmsPasswordEgypt = [ 2964652601, 661394472, 4103522417, 1801911188, 2218174362, 415053497, 2738166764, 765909451, 405014297, 2439444423, 3974108013, 1883547923, 2491987381, 3793733862, 3078233468, 2849878358, ]; static const List _envieddatasmsPasswordEgypt = [ 2964652659, 661394433, 4103522343, 1801911292, 2218174375, 415053512, 2738166670, 765909476, 405014361, 2439444362, 3974107957, 1883548001, 2491987437, 3793733770, 3078233406, 2849878330, ]; static final String smsPasswordEgypt = String.fromCharCodes( List.generate( _envieddatasmsPasswordEgypt.length, (int i) => i, growable: false, ).map((int i) => _envieddatasmsPasswordEgypt[i] ^ _enviedkeysmsPasswordEgypt[i])); static const List _enviedkeyocpApimSubscriptionKey = [ 1680613404, 766984278, 489575845, 4184529926, 1083542025, 2774869789, 2842389196, 382068769, 2082818229, 1293781006, 1948330559, 2730833372, 623113212, 2632476463, 2126610411, 2716605945, 3632004881, 3803177136, 525648801, 3759637161, 1618570024, 4220960602, 1995238230, 3630408850, 1180468595, 292798063, 1954541046, 3490607301, 1054257593, 2301544482, 1422895000, 3432042072, ]; static const List _envieddataocpApimSubscriptionKey = [ 1680613420, 766984240, 489575824, 4184530018, 1083542120, 2774869886, 2842389167, 382068802, 2082818257, 1293781100, 1948330588, 2730833337, 623113160, 2632476446, 2126610392, 2716605896, 3632004979, 3803177089, 525648832, 3759637148, 1618570062, 4220960611, 1995238243, 3630408864, 1180468554, 292798038, 1954540992, 3490607350, 1054257545, 2301544464, 1422895101, 3432042091, ]; static final String ocpApimSubscriptionKey = String.fromCharCodes( List.generate( _envieddataocpApimSubscriptionKey.length, (int i) => i, growable: false, ).map((int i) => _envieddataocpApimSubscriptionKey[i] ^ _enviedkeyocpApimSubscriptionKey[i])); static const List _enviedkeychatGPTkeySeferNew4 = [ 165946952, 2519274331, 1711285420, 1361145579, 2380979994, 3780095409, 3040402589, 1501335247, 1544015156, 1776405554, 3482217997, 1223473272, 3953006632, 3986682735, 2615350534, 3465778657, 4036685621, 3227709941, 3728734684, 1585693318, 769867411, 2387100925, 3913016003, 2189494387, 2810125591, 3688154746, 3779108683, 2432158751, 3867671973, 1348640224, 3635346110, 3778218683, 1049974663, 1157936066, 3963405148, 611839680, 2960325913, 1180667318, 188557971, 1613283441, 3915082576, 312029694, 3405987139, 750305674, 286506941, 600133805, 708734631, 3064918952, 919297550, 1097290694, 3165042777, 537250103, 2942587704, 2424548847, 3345432998, 1874121802, 353612717, 542705171, 2596302736, 2850310258, 2691267156, 1970156388, 2668786355, ]; static const List _envieddatachatGPTkeySeferNew4 = [ 165946930, 2519274300, 1711285377, 1361145501, 2380980086, 3780095448, 3040402680, 1501335266, 1544015110, 1776405598, 3482218044, 1223473186, 3953006660, 3986682655, 2615350654, 3465778568, 4036685656, 3227709881, 3728734614, 1585693360, 769867492, 2387100844, 3913015948, 2189494277, 2810125685, 3688154648, 3779108735, 2432158795, 3867672011, 1348640163, 3635346055, 3778218723, 1049974773, 1157936058, 3963405115, 611839637, 2960325980, 1180667343, 188558021, 1613283360, 3915082521, 312029579, 3405987189, 750305758, 286506996, 600133865, 708734611, 3064919001, 919297630, 1097290738, 3165042719, 537250146, 2942587757, 2424548766, 3345433033, 1874121753, 353612696, 542705227, 2596302818, 2850310186, 2691267128, 1970156326, 2668786399, ]; static final String chatGPTkeySeferNew4 = String.fromCharCodes( List.generate( _envieddatachatGPTkeySeferNew4.length, (int i) => i, growable: false, ).map((int i) => _envieddatachatGPTkeySeferNew4[i] ^ _enviedkeychatGPTkeySeferNew4[i])); static const List _enviedkeyanthropicAIkeySeferNew = [ 1390788784, 2899333933, 2601017452, 583956846, 3110859152, 193944522, 951522168, 1238163245, 2618464762, 3456466756, 2362895605, 2392646809, 1447972066, 1256291038, 2920427097, 1750471581, 1975295559, 2468637305, 1648601760, 289576623, 2213687885, 1815967478, 178013466, 2788059547, 365457058, 3266752649, 2540305940, 1940060148, 3706825815, 2164572557, 2305628851, 703739885, 4055255283, 1950391799, 1146632371, 3224019945, 2341516270, 3381071414, 2572375663, 4138541842, 689066929, 3282840646, 566677748, 1887412751, 519910471, 1089100679, 3824974340, 427911784, 3944412672, 3700666201, 1149706331, 1359925046, 4040017590, 894323584, 2254132999, 2967896879, 538439848, 278878499, 614393047, 4202890985, 156481971, 1649184035, 508351254, 2105159426, 879175573, 2488976392, 3587723789, 2773795641, 2908862306, 390299385, 4154118259, 1688160337, 2322984466, 4223202135, 2939324335, 2707297582, 3764943743, 3688611620, 1321505108, 358717938, 671761162, 1399845294, 2987873839, 2252061806, 2129319815, 1451107509, 1128177468, 4219469215, 2740115944, 2533695196, 2958741446, 1563390906, 2248533402, 553421148, 2994863918, 2326073237, 2418385593, 3370448551, 2027834607, 3366697397, 2278908194, 1784228985, 3785959825, 3382170346, 1921601241, 3292065984, 2880865390, 3234799239, 1573280306, 1139986144, 2636040870, 1654065515, 3919623519, 578173425, 1524095618, ]; static const List _envieddataanthropicAIkeySeferNew = [ 1390788810, 2899333962, 2601017409, 583956767, 3110859250, 193944489, 951522133, 1238163292, 2618464652, 3456466731, 2362895558, 2392646816, 1447972047, 1256290995, 2920427063, 1750471593, 1975295505, 2468637213, 1648601837, 289576702, 2213687928, 1815967384, 178013551, 2788059601, 365457095, 3266752704, 2540305997, 1940060060, 3706825754, 2164572611, 2305628807, 703739837, 4055255223, 1950391726, 1146632385, 3224019934, 2341516191, 3381071449, 2572375575, 4138541857, 689066908, 3282840626, 566677702, 1887412838, 519910518, 1089100747, 3824974444, 427911775, 3944412769, 3700666135, 1149706255, 1359925106, 4040017616, 894323673, 2254133057, 2967896834, 538439919, 278878533, 614393071, 4202890910, 156482011, 1649184118, 508351324, 2105159512, 879175638, 2488976507, 3587723833, 2773795598, 2908862247, 390299292, 4154118166, 1688160317, 2322984537, 4223202105, 2939324311, 2707297649, 3764943658, 3688611655, 1321505081, 358717863, 671761223, 1399845315, 2987873862, 2252061757, 2129319883, 1451107540, 1128177498, 4219469231, 2740115901, 2533695126, 2958741409, 1563390858, 2248533470, 553421098, 2994863995, 2326073337, 2418385640, 3370448597, 2027834539, 3366697409, 2278908175, 1784228942, 3785959847, 3382170281, 1921601163, 3292065970, 2880865285, 3234799318, 1573280355, 1139986104, 2636040916, 1654065459, 3919623475, 578173363, 1524095726, ]; static final String anthropicAIkeySeferNew = String.fromCharCodes( List.generate( _envieddataanthropicAIkeySeferNew.length, (int i) => i, growable: false, ).map((int i) => _envieddataanthropicAIkeySeferNew[i] ^ _enviedkeyanthropicAIkeySeferNew[i])); static const List _enviedkeyllama3Key = [ 3303025890, 3040127445, 159804670, 3638428578, 2485542120, 3962641454, 274247243, 3629970635, 3234635792, 2115979750, 923341190, 3294121335, 3806401870, 2817630500, 4261607353, 990462919, 2333653192, 4244395593, 159390286, 2585700164, 3692206516, 3873181795, 3445980531, 2163279259, 455617944, 1572817148, 3630998964, 3691408189, 3389804023, 3521084222, 2836418047, 4223664654, 2858292901, 656160633, 3309801784, 1291082685, 2478661609, 371653079, 267632023, 1722212424, 3278786486, 1940105508, 243864795, 850041693, 3528862299, 3967016145, 855965655, 427497014, 3032641752, 411531135, 2222697726, 198475334, 3216809596, 2987641478, 493693562, 2376918683, 2111796947, 2192882037, 1188439978, 930517079, 2340764567, 1769421478, 3217307146, ]; static const List _envieddatallama3Key = [ 3303025801, 3040127407, 159804569, 3638428669, 2485542045, 3962641530, 274247187, 3629970610, 3234635811, 2115979651, 923341247, 3294121267, 3806401804, 2817630534, 4261607418, 990462870, 2333653241, 4244395535, 159390240, 2585700105, 3692206579, 3873181710, 3445980427, 2163279298, 455618031, 1572817064, 3630999039, 3691408196, 3389803908, 3521084230, 2836417990, 4223664731, 2858292982, 656160584, 3309801818, 1291082696, 2478661531, 371653039, 267632093, 1722212386, 3278786434, 1940105538, 243864733, 850041642, 3528862228, 3967016123, 855965618, 427496962, 3032641684, 411531045, 2222697660, 198475283, 3216809530, 2987641549, 493693488, 2376918728, 2111796962, 2192881965, 1188440024, 930517007, 2340764667, 1769421540, 3217307238, ]; static final String llama3Key = String.fromCharCodes(List.generate( _envieddatallama3Key.length, (int i) => i, growable: false, ).map((int i) => _envieddatallama3Key[i] ^ _enviedkeyllama3Key[i])); static const List _enviedkeypayMobOutPassword = [ 691888625, 3418568462, 3667328651, 3120661808, 3394738650, 516854079, 4156982005, 2562517432, 2242685936, 1982999215, 955894797, 508403475, 388170670, 1154547106, 2087642196, 2350753856, 2501567039, 2096072246, 3678900752, 212267875, 161654232, 2850135153, 3346306461, 2248978659, 189152548, 3328740901, 550684179, 4015886188, 3643074951, 2340386410, 3533334677, 3289964604, ]; static const List _envieddatapayMobOutPassword = [ 691888565, 3418568508, 3667328753, 3120661882, 3394738588, 516854087, 4156981918, 2562517501, 2242685907, 1982999267, 955894851, 508403576, 388170653, 1154547156, 2087642158, 2350753907, 2501566983, 2096072268, 3678900770, 212267783, 161654145, 2850135049, 3346306541, 2248978605, 189152578, 3328740978, 550684235, 4015886110, 3643075039, 2340386310, 3533334743, 3289964624, ]; static final String payMobOutPassword = String.fromCharCodes( List.generate( _envieddatapayMobOutPassword.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayMobOutPassword[i] ^ _enviedkeypayMobOutPassword[i])); static const List _enviedkeypayMobOutUserName = [ 2722035514, 758760241, 3666170111, 848922883, 2404908817, 3220605697, 4045166960, 2962281252, 4053803990, 1833278131, 1428760222, 1119616996, 2649111811, 3893320771, 2133081586, 3983757096, 2987459343, 2007545360, 1656443894, 1098117283, 2501420758, 3444268112, 1948142210, 1554282014, ]; static const List _envieddatapayMobOutUserName = [ 2722035520, 758760283, 3666169994, 848922985, 2404908925, 3220605790, 4045166849, 2962281298, 4053803961, 1833278188, 1428760312, 1119616915, 2649111912, 3893320745, 2133081492, 3983757135, 2987459429, 2007545468, 1656443822, 1098117329, 2501420686, 3444268092, 1948142272, 1554282098, ]; static final String payMobOutUserName = String.fromCharCodes( List.generate( _envieddatapayMobOutUserName.length, (int i) => i, growable: false, ).map((int i) => _envieddatapayMobOutUserName[i] ^ _enviedkeypayMobOutUserName[i])); static const List _enviedkeyA = [2728777574]; static const List _envieddataA = [2728777527]; static final String A = String.fromCharCodes(List.generate( _envieddataA.length, (int i) => i, growable: false, ).map((int i) => _envieddataA[i] ^ _enviedkeyA[i])); static const List _enviedkeyB = [253296250]; static const List _envieddataB = [253296162]; static final String B = String.fromCharCodes(List.generate( _envieddataB.length, (int i) => i, growable: false, ).map((int i) => _envieddataB[i] ^ _enviedkeyB[i])); static const List _enviedkeyC = [520289948]; static const List _envieddataC = [520290010]; static final String C = String.fromCharCodes(List.generate( _envieddataC.length, (int i) => i, growable: false, ).map((int i) => _envieddataC[i] ^ _enviedkeyC[i])); static const List _enviedkeyD = [1839925402]; static const List _envieddataD = [1839925443]; static final String D = String.fromCharCodes(List.generate( _envieddataD.length, (int i) => i, growable: false, ).map((int i) => _envieddataD[i] ^ _enviedkeyD[i])); static const List _enviedkeyE = [1455985570]; static const List _envieddataE = [1455985640]; static final String E = String.fromCharCodes(List.generate( _envieddataE.length, (int i) => i, growable: false, ).map((int i) => _envieddataE[i] ^ _enviedkeyE[i])); static const List _enviedkeyF = [1047134101]; static const List _envieddataF = [1047134144]; static final String F = String.fromCharCodes(List.generate( _envieddataF.length, (int i) => i, growable: false, ).map((int i) => _envieddataF[i] ^ _enviedkeyF[i])); static const List _enviedkeyG = [3892417735]; static const List _envieddataG = [3892417676]; static final String G = String.fromCharCodes(List.generate( _envieddataG.length, (int i) => i, growable: false, ).map((int i) => _envieddataG[i] ^ _enviedkeyG[i])); static const List _enviedkeyH = [865934818]; static const List _envieddataH = [865934773]; static final String H = String.fromCharCodes(List.generate( _envieddataH.length, (int i) => i, growable: false, ).map((int i) => _envieddataH[i] ^ _enviedkeyH[i])); static const List _enviedkeyI = [3782801626]; static const List _envieddataI = [3782801557]; static final String I = String.fromCharCodes(List.generate( _envieddataI.length, (int i) => i, growable: false, ).map((int i) => _envieddataI[i] ^ _enviedkeyI[i])); static const List _enviedkeyJ = [860165277]; static const List _envieddataJ = [860165336]; static final String J = String.fromCharCodes(List.generate( _envieddataJ.length, (int i) => i, growable: false, ).map((int i) => _envieddataJ[i] ^ _enviedkeyJ[i])); static const List _enviedkeyK = [3780868384]; static const List _envieddataK = [3780868455]; static final String K = String.fromCharCodes(List.generate( _envieddataK.length, (int i) => i, growable: false, ).map((int i) => _envieddataK[i] ^ _enviedkeyK[i])); static const List _enviedkeyL = [1982378567]; static const List _envieddataL = [1982378517]; static final String L = String.fromCharCodes(List.generate( _envieddataL.length, (int i) => i, growable: false, ).map((int i) => _envieddataL[i] ^ _enviedkeyL[i])); static const List _enviedkeyM = [1120129024]; static const List _envieddataM = [1120129102]; static final String M = String.fromCharCodes(List.generate( _envieddataM.length, (int i) => i, growable: false, ).map((int i) => _envieddataM[i] ^ _enviedkeyM[i])); static const List _enviedkeyN = [3577342690]; static const List _envieddataN = [3577342624]; static final String N = String.fromCharCodes(List.generate( _envieddataN.length, (int i) => i, growable: false, ).map((int i) => _envieddataN[i] ^ _enviedkeyN[i])); static const List _enviedkeyO = [3807693943]; static const List _envieddataO = [3807693886]; static final String O = String.fromCharCodes(List.generate( _envieddataO.length, (int i) => i, growable: false, ).map((int i) => _envieddataO[i] ^ _enviedkeyO[i])); static const List _enviedkeyP = [3355353777]; static const List _envieddataP = [3355353831]; static final String P = String.fromCharCodes(List.generate( _envieddataP.length, (int i) => i, growable: false, ).map((int i) => _envieddataP[i] ^ _enviedkeyP[i])); static const List _enviedkeyQ = [2038250624]; static const List _envieddataQ = [2038250689]; static final String Q = String.fromCharCodes(List.generate( _envieddataQ.length, (int i) => i, growable: false, ).map((int i) => _envieddataQ[i] ^ _enviedkeyQ[i])); static const List _enviedkeyR = [4026835158]; static const List _envieddataR = [4026835098]; static final String R = String.fromCharCodes(List.generate( _envieddataR.length, (int i) => i, growable: false, ).map((int i) => _envieddataR[i] ^ _enviedkeyR[i])); static const List _enviedkeyS = [3309984485]; static const List _envieddataS = [3309984447]; static final String S = String.fromCharCodes(List.generate( _envieddataS.length, (int i) => i, growable: false, ).map((int i) => _envieddataS[i] ^ _enviedkeyS[i])); static const List _enviedkeyT = [2410998883]; static const List _envieddataT = [2410998816]; static final String T = String.fromCharCodes(List.generate( _envieddataT.length, (int i) => i, growable: false, ).map((int i) => _envieddataT[i] ^ _enviedkeyT[i])); static const List _enviedkeyU = [4123622442]; static const List _envieddataU = [4123622498]; static final String U = String.fromCharCodes(List.generate( _envieddataU.length, (int i) => i, growable: false, ).map((int i) => _envieddataU[i] ^ _enviedkeyU[i])); static const List _enviedkeyV = [2664631239]; static const List _envieddataV = [2664631191]; static final String V = String.fromCharCodes(List.generate( _envieddataV.length, (int i) => i, growable: false, ).map((int i) => _envieddataV[i] ^ _enviedkeyV[i])); static const List _enviedkeyW = [3105440214]; static const List _envieddataW = [3105440130]; static final String W = String.fromCharCodes(List.generate( _envieddataW.length, (int i) => i, growable: false, ).map((int i) => _envieddataW[i] ^ _enviedkeyW[i])); static const List _enviedkeyX = [2305594320]; static const List _envieddataX = [2305594260]; static final String X = String.fromCharCodes(List.generate( _envieddataX.length, (int i) => i, growable: false, ).map((int i) => _envieddataX[i] ^ _enviedkeyX[i])); static const List _enviedkeyY = [2266378590]; static const List _envieddataY = [2266378509]; static final String Y = String.fromCharCodes(List.generate( _envieddataY.length, (int i) => i, growable: false, ).map((int i) => _envieddataY[i] ^ _enviedkeyY[i])); static const List _enviedkeyZ = [4281016674]; static const List _envieddataZ = [4281016623]; static final String Z = String.fromCharCodes(List.generate( _envieddataZ.length, (int i) => i, growable: false, ).map((int i) => _envieddataZ[i] ^ _enviedkeyZ[i])); static const List _enviedkeya = [3819752563]; static const List _envieddataa = [3819752450]; static final String a = String.fromCharCodes(List.generate( _envieddataa.length, (int i) => i, growable: false, ).map((int i) => _envieddataa[i] ^ _enviedkeya[i])); static const List _enviedkeyb = [3279865818]; static const List _envieddatab = [3279865762]; static final String b = String.fromCharCodes(List.generate( _envieddatab.length, (int i) => i, growable: false, ).map((int i) => _envieddatab[i] ^ _enviedkeyb[i])); static const List _enviedkeyc = [2702050004]; static const List _envieddatac = [2702049970]; static final String c = String.fromCharCodes(List.generate( _envieddatac.length, (int i) => i, growable: false, ).map((int i) => _envieddatac[i] ^ _enviedkeyc[i])); static const List _enviedkeyd = [3730998599]; static const List _envieddatad = [3730998590]; static final String d = String.fromCharCodes(List.generate( _envieddatad.length, (int i) => i, growable: false, ).map((int i) => _envieddatad[i] ^ _enviedkeyd[i])); static const List _enviedkeye = [3826033034]; static const List _envieddatae = [3826033120]; static final String e = String.fromCharCodes(List.generate( _envieddatae.length, (int i) => i, growable: false, ).map((int i) => _envieddatae[i] ^ _enviedkeye[i])); static const List _enviedkeyf = [1881927301]; static const List _envieddataf = [1881927408]; static final String f = String.fromCharCodes(List.generate( _envieddataf.length, (int i) => i, growable: false, ).map((int i) => _envieddataf[i] ^ _enviedkeyf[i])); static const List _enviedkeyg = [1156001031]; static const List _envieddatag = [1156001132]; static final String g = String.fromCharCodes(List.generate( _envieddatag.length, (int i) => i, growable: false, ).map((int i) => _envieddatag[i] ^ _enviedkeyg[i])); static const List _enviedkeyh = [1060697757]; static const List _envieddatah = [1060697834]; static final String h = String.fromCharCodes(List.generate( _envieddatah.length, (int i) => i, growable: false, ).map((int i) => _envieddatah[i] ^ _enviedkeyh[i])); static const List _enviedkeyi = [1267625729]; static const List _envieddatai = [1267625838]; static final String i = String.fromCharCodes(List.generate( _envieddatai.length, (int i) => i, growable: false, ).map((int i) => _envieddatai[i] ^ _enviedkeyi[i])); static const List _enviedkeyj = [3609401216]; static const List _envieddataj = [3609401317]; static final String j = String.fromCharCodes(List.generate( _envieddataj.length, (int i) => i, growable: false, ).map((int i) => _envieddataj[i] ^ _enviedkeyj[i])); static const List _enviedkeyk = [3581851696]; static const List _envieddatak = [3581851735]; static final String k = String.fromCharCodes(List.generate( _envieddatak.length, (int i) => i, growable: false, ).map((int i) => _envieddatak[i] ^ _enviedkeyk[i])); static const List _enviedkeyl = [2540206731]; static const List _envieddatal = [2540206841]; static final String l = String.fromCharCodes(List.generate( _envieddatal.length, (int i) => i, growable: false, ).map((int i) => _envieddatal[i] ^ _enviedkeyl[i])); static const List _enviedkeym = [1113073961]; static const List _envieddatam = [1113073991]; static final String m = String.fromCharCodes(List.generate( _envieddatam.length, (int i) => i, growable: false, ).map((int i) => _envieddatam[i] ^ _enviedkeym[i])); static const List _enviedkeyn = [3783724403]; static const List _envieddatan = [3783724305]; static final String n = String.fromCharCodes(List.generate( _envieddatan.length, (int i) => i, growable: false, ).map((int i) => _envieddatan[i] ^ _enviedkeyn[i])); static const List _enviedkeyo = [2007287074]; static const List _envieddatao = [2007287115]; static final String o = String.fromCharCodes(List.generate( _envieddatao.length, (int i) => i, growable: false, ).map((int i) => _envieddatao[i] ^ _enviedkeyo[i])); static const List _enviedkeyp = [770064759]; static const List _envieddatap = [770064641]; static final String p = String.fromCharCodes(List.generate( _envieddatap.length, (int i) => i, growable: false, ).map((int i) => _envieddatap[i] ^ _enviedkeyp[i])); static const List _enviedkeyq = [1035975926]; static const List _envieddataq = [1035975831]; static final String q = String.fromCharCodes(List.generate( _envieddataq.length, (int i) => i, growable: false, ).map((int i) => _envieddataq[i] ^ _enviedkeyq[i])); static const List _enviedkeyr = [3575839329]; static const List _envieddatar = [3575839245]; static final String r = String.fromCharCodes(List.generate( _envieddatar.length, (int i) => i, growable: false, ).map((int i) => _envieddatar[i] ^ _enviedkeyr[i])); static const List _enviedkeys = [708247410]; static const List _envieddatas = [708247304]; static final String s = String.fromCharCodes(List.generate( _envieddatas.length, (int i) => i, growable: false, ).map((int i) => _envieddatas[i] ^ _enviedkeys[i])); static const List _enviedkeyt = [1462885198]; static const List _envieddatat = [1462885165]; static final String t = String.fromCharCodes(List.generate( _envieddatat.length, (int i) => i, growable: false, ).map((int i) => _envieddatat[i] ^ _enviedkeyt[i])); static const List _enviedkeyu = [3739151416]; static const List _envieddatau = [3739151440]; static final String u = String.fromCharCodes(List.generate( _envieddatau.length, (int i) => i, growable: false, ).map((int i) => _envieddatau[i] ^ _enviedkeyu[i])); static const List _enviedkeyv = [2662581886]; static const List _envieddatav = [2662581774]; static final String v = String.fromCharCodes(List.generate( _envieddatav.length, (int i) => i, growable: false, ).map((int i) => _envieddatav[i] ^ _enviedkeyv[i])); static const List _enviedkeyw = [3498508020]; static const List _envieddataw = [3498507904]; static final String w = String.fromCharCodes(List.generate( _envieddataw.length, (int i) => i, growable: false, ).map((int i) => _envieddataw[i] ^ _enviedkeyw[i])); static const List _enviedkeyx = [907463890]; static const List _envieddatax = [907463862]; static final String x = String.fromCharCodes(List.generate( _envieddatax.length, (int i) => i, growable: false, ).map((int i) => _envieddatax[i] ^ _enviedkeyx[i])); static const List _enviedkeyy = [4234849242]; static const List _envieddatay = [4234849193]; static final String y = String.fromCharCodes(List.generate( _envieddatay.length, (int i) => i, growable: false, ).map((int i) => _envieddatay[i] ^ _enviedkeyy[i])); static const List _enviedkeyz = [993653623]; static const List _envieddataz = [993653530]; static final String z = String.fromCharCodes(List.generate( _envieddataz.length, (int i) => i, growable: false, ).map((int i) => _envieddataz[i] ^ _enviedkeyz[i])); static const List _enviedkeykeyOfApp = [ 737221370, 369145243, 1722608103, 319218073, 868553379, 1243027350, 305701998, 2799593867, 4161860662, 645216568, 2274517069, 3991029625, 633555885, 3526090868, 1017912832, 1378969199, 1984596014, 3743288617, 1050438536, 1625963056, 4294244547, 4098360146, 2396486816, 2776509622, 244712926, 3076306074, 2971868632, 1585392295, 2985921549, 834885838, 2460877066, 4260875487, 3855507550, 1038313282, 3524366194, 3994072033, 706315910, 2119621937, ]; static const List _envieddatakeyOfApp = [ 737221272, 369145338, 1722608011, 319218154, 868553414, 1243027424, 305701934, 2799593916, 4161860608, 645216513, 2274517115, 3991029517, 633555916, 3526090774, 1017912942, 1378969102, 1984596047, 3743288659, 1050438637, 1625963075, 4294244526, 4098360119, 2396486856, 2776509651, 244712876, 3076306175, 2971868607, 1585392349, 2985921661, 834885800, 2460877152, 4260875440, 3855507462, 1038313264, 3524366122, 3994071955, 706315972, 2119621955, ]; static final String keyOfApp = String.fromCharCodes(List.generate( _envieddatakeyOfApp.length, (int i) => i, growable: false, ).map((int i) => _envieddatakeyOfApp[i] ^ _enviedkeykeyOfApp[i])); static const List _enviedkeyinitializationVector = [ 3635815207, 453767232, 1182787676, 3136825516, 3577950102, 3014404719, 2793409857, 1752764365, 3187658772, 4016134702, 976749, 3514395586, 1983825889, 2267838664, 3172648930, 4191582625, 1892578606, 1448432109, 3928659209, 1151265388, 4200269382, 211740698, ]; static const List _envieddatainitializationVector = [ 3635815254, 453767224, 1182787642, 3136825557, 3577950204, 3014404634, 2793409834, 1752764346, 3187658875, 4016134731, 976650, 3514395568, 1983825807, 2267838634, 3172648843, 4191582679, 1892578678, 1448432031, 3928659281, 1151265310, 4200269316, 211740776, ]; static final String initializationVector = String.fromCharCodes( List.generate( _envieddatainitializationVector.length, (int i) => i, growable: false, ).map((int i) => _envieddatainitializationVector[i] ^ _enviedkeyinitializationVector[i])); static const List _enviedkeyemailService = [ 3757736252, 3530158478, 1690974045, 4047876702, 3547870269, 4237459698, 1140595114, 205393449, 742714358, 4221307462, 2269677427, 506590645, 4152850886, 389921230, 854624428, 3274461352, 2803926361, 4023450891, 3556696491, 4026930413, 3090981958, 3577906890, ]; static const List _envieddataemailService = [ 3757736271, 3530158571, 1690974011, 4047876667, 3547870287, 4237459585, 1140595151, 205393499, 742714240, 4221307439, 2269677328, 506590672, 4152850822, 389921193, 854624449, 3274461385, 2803926320, 4023450983, 3556696453, 4026930318, 3090981929, 3577906855, ]; static final String emailService = String.fromCharCodes(List.generate( _envieddataemailService.length, (int i) => i, growable: false, ).map((int i) => _envieddataemailService[i] ^ _enviedkeyemailService[i])); static const List _enviedkeysss_encryptionSalt = [ 1002437411, 1276596604, 3686199103, 3942226461, 1476043512, 3342451630, 3109239762, 1188176467, 148259435, 1479660765, 998215119, 3964599801, 3253374012, 447604137, 3347121049, 1946668561, 1357464645, 2710667364, 470836777, 3907619736, 2060266349, 636597406, 4142349334, 2604926716, 142934911, 2025191727, 3482668585, 2025098431, 2744045050, 2949710863, 4130944691, 3787627019, 399942557, 1923329033, 3028447935, 1087236179, 3289537550, 2381295466, 1293468443, 968018163, 2821762394, 3298370204, 4247843360, 823955713, 3568230274, 2300037345, 1309323818, 2885137547, 981224663, 736049254, 1977988263, 3414144505, 331044559, 1722930122, 2229941005, 4096792598, 3915006122, 1916175725, 1187133702, 686591299, 1270170285, 662310015, 915441541, ]; static const List _envieddatasss_encryptionSalt = [ 1002437465, 1276596507, 3686199058, 3942226539, 1476043411, 3342451650, 3109239739, 1188176438, 148259398, 1479660783, 998215075, 3964599752, 3253374054, 447604165, 3347121129, 1946668649, 1357464620, 2710667304, 470836835, 3907619758, 2060266266, 636597455, 4142349401, 2604926602, 142934813, 2025191757, 3482668573, 2025098475, 2744044948, 2949710924, 4130944650, 3787627091, 399942639, 1923329137, 3028447960, 1087236102, 3289537611, 2381295379, 1293468493, 968018082, 2821762323, 3298370281, 4247843350, 823955797, 3568230347, 2300037285, 1309323806, 2885137658, 981224583, 736049234, 1977988321, 3414144428, 331044506, 1722930107, 2229941090, 4096792645, 3915006111, 1916175669, 1187133812, 686591259, 1270170305, 662309949, 915441641, ]; static final String sss_encryptionSalt = String.fromCharCodes( List.generate( _envieddatasss_encryptionSalt.length, (int i) => i, growable: false, ).map((int i) => _envieddatasss_encryptionSalt[i] ^ _enviedkeysss_encryptionSalt[i])); static const List _enviedkeysss_pass = [ 2747931136, 2869758478, 2901687250, 3674333311, 2077515912, 1676896265, 2820997702, 2878017126, 1352680310, 388738787, 292462729, 2947139344, 3697171721, 2639866237, 1006707417, 3915118699, 2148369991, 333802985, 460129875, 1288609461, 2055047045, 568974885, 2329885766, 921811783, 1672294058, 1493692829, 722682121, 707970428, 1166456072, 3944730669, 48488915, 2985822875, ]; static const List _envieddatasss_pass = [ 2747931255, 2869758591, 2901687228, 3674333202, 2077516025, 1676896376, 2820997685, 2878017036, 1352680207, 388738709, 292462846, 2947139430, 3697171763, 2639866131, 1006707368, 3915118617, 2148369962, 333802928, 460129817, 1288609509, 2055047109, 568974868, 2329885809, 921811828, 1672294045, 1493692837, 722682193, 707970318, 1166456144, 3944730689, 48488849, 2985822967, ]; static final String sss_pass = String.fromCharCodes(List.generate( _envieddatasss_pass.length, (int i) => i, growable: false, ).map((int i) => _envieddatasss_pass[i] ^ _enviedkeysss_pass[i])); static const List _enviedkeyaddd = [ 1898037812, 672528233, 2411052927, 446276678, 1096083963, 3735439123, ]; static const List _envieddataaddd = [ 1898037878, 672528133, 2411052861, 446276650, 1096083893, 3735439231, ]; static final String addd = String.fromCharCodes(List.generate( _envieddataaddd.length, (int i) => i, growable: false, ).map((int i) => _envieddataaddd[i] ^ _enviedkeyaddd[i])); static const List _enviedkeypassnpassenger = [ 4267335078, 4204657130, 1281084306, 1822032932, 3175750404, 1137513229, 1624757084, 3717224503, 603175625, 3573758605, 1137882763, 1718864519, 2367410150, ]; static const List _envieddatapassnpassenger = [ 4267335118, 4204657032, 1281084405, 1822032966, 3175750509, 1137513337, 1624757054, 3717224559, 603175611, 3573758677, 1137882873, 1718864581, 2367410068, ]; static final String passnpassenger = String.fromCharCodes(List.generate( _envieddatapassnpassenger.length, (int i) => i, growable: false, ).map((int i) => _envieddatapassnpassenger[i] ^ _enviedkeypassnpassenger[i])); static const List _enviedkeynewId = [ 1708961613, 3143686563, 3680995221, ]; static const List _envieddatanewId = [ 1708961571, 3143686598, 3680995298, ]; static final String newId = String.fromCharCodes(List.generate( _envieddatanewId.length, (int i) => i, growable: false, ).map((int i) => _envieddatanewId[i] ^ _enviedkeynewId[i])); static const List _enviedkeyallowed = [ 2888874493, 1093801966, 3320064253, 1979931149, 3388111246, 2089115130, 301467299, 1358596359, 1608776289, 4172621919, 3279148932, 3240447191, ]; static const List _envieddataallowed = [ 2888874409, 1093801884, 3320064148, 1979931261, 3388111348, 2089115070, 301467345, 1358596462, 1608776215, 4172621882, 3279149046, 3240447213, ]; static final String allowed = String.fromCharCodes(List.generate( _envieddataallowed.length, (int i) => i, growable: false, ).map((int i) => _envieddataallowed[i] ^ _enviedkeyallowed[i])); static const List _enviedkeyallowedWallet = [ 3853938684, 1152968613, 3956190127, 2953498893, 1848046511, 577904594, 4200141909, 3520148177, 1954672960, 3846864451, 1165090405, 819178616, ]; static const List _envieddataallowedWallet = [ 3853938600, 1152968663, 3956190150, 2953499005, 1848046549, 577904517, 4200141876, 3520148157, 1954672940, 3846864422, 1165090321, 819178562, ]; static final String allowedWallet = String.fromCharCodes(List.generate( _envieddataallowedWallet.length, (int i) => i, growable: false, ).map((int i) => _envieddataallowedWallet[i] ^ _enviedkeyallowedWallet[i])); } ================================================== FILE PATH: ./lib/constant/char_map.dart ================================================== import '../env/env.dart'; Map cs = { "a": Env.a, "b": Env.b, "c": Env.c, "d": Env.d, "e": Env.e, "f": Env.f, "g": Env.g, "h": Env.h, "i": Env.i, "j": Env.j, "k": Env.k, "l": Env.l, "m": Env.m, "n": Env.n, "o": Env.o, "p": Env.p, "q": Env.q, "r": Env.r, "s": Env.s, "t": Env.t, "u": Env.u, "v": Env.v, "w": Env.w, "x": Env.x, "y": Env.y, "z": Env.z, }; Map cC = { "A": Env.A, "B": Env.B, "C": Env.C, "D": Env.D, "E": Env.E, "F": Env.F, "G": Env.G, "H": Env.H, "I": Env.I, "J": Env.J, "K": Env.K, "L": Env.L, "M": Env.M, "N": Env.N, "O": Env.O, "P": Env.P, "Q": Env.Q, "R": Env.R, "S": Env.S, "T": Env.T, "U": Env.U, "V": Env.V, "W": Env.W, "X": Env.X, "Y": Env.Y, "Z": Env.Z }; // // Map cn = { "0": "3", "1": "7", "2": "1", "3": "9", "4": "0", "5": "5", "6": "2", "7": "6", "8": "4", "9": "8" }; ================================================== FILE PATH: ./lib/constant/colors.dart ================================================== import 'package:flutter/material.dart'; class AppColor { static const Color primaryColor = Color(0xFF1DA1F2); static const Color writeColor = Color(0xff222359); static const Color bronze = Color(0xFFCD7F32); static const Color goldenBronze = Color(0xFFB87333); // Golden bronze color static const Color gold = Color(0xFFD4AF37); static const Color secondaryColor = Colors.white; static const Color accentColor = Colors.grey; static const Color greyColor = Colors.grey; static const Color twitterColor = Color(0xFF1DA1F2); // Twitter blue static const Color redColor = Color(0xFFEA4335); // Google Red static const Color greenColor = Color(0xFF34A853); // Google Green static const Color blueColor = Color(0xFF1DA1F2); // Google Blue static const Color yellowColor = Color(0xFFFBBC05); // Google Yellow static Color deepPurpleAccent = const Color.fromARGB(255, 123, 76, 254).withOpacity(0.3); // For dynamic elements like gradients static List gradientStartEnd = [ Color.fromARGB(255, 40, 158, 232), // Start with primary color Color.fromARGB( 255, 44, 63, 75), // End with a slightly darker shade of Twitter blue ]; static List secondaryGradientStartEnd = [ const Color(0xFF1DA1F2), // Start with Twitter blue const Color(0xFF0C7ABF), // End with a slightly darker shade of Twitter blue ]; } ================================================== FILE PATH: ./lib/constant/notification.dart ================================================== List syrianDriverMessages = [ // --- أوقات الذروة والطلبات الكتيرة --- "وقت الذروة: البلد مولّعة مشاوير! 🌃 افتح التطبيق بسرعة وبلّش أرباحك تدبّل.", "طلبات كتير حواليك: ⚠️ خليك أول كابتن بيلتقط الطلب وخلّي يومك رابح.", "الناس طالعة من الشغل: 🌇 الكل راجع عالبيت، خليك جاهز لرحلات كتيرة!", "زحمة المساء: ⏳ الزباين عم تزيد بهالوقت، لا تضيّع الفرصة واشتغل معنا!", // --- التركيز عالربح والمصاري --- "ضاعف ربحك: 💰 كل مشوار بيقربك من هدفك اليومي. جاهز تنطلق؟", "مصاري أكتر: جزدانك ناطر تعبك، كل دقيقة شغل هي ربح مضمون. 💪", "خليك بالواجهة: الطلب الجاي ممكن يكون إلك، كبسة زر بتجيبلك رزقة اليوم.", "رزقتك جاهزة: 💸 لا تخلّي الزباين يستنّوا، افتح التطبيق وخليك متأهّب.", // --- التقدير والشكر --- "شكراً إلك: 🙏 إنت مو بس سائق، إنت أساس نجاح تطبيق انطلق.", "نفتخر فيك: 🌟 الكباتن متلك هنن يلي رافعين اسمنا بالعالي.", "أداء ممتاز: 👍 استمر بنفس الروح الحلوة، زباينك مبسوطين منك.", "نجاح مشترك: 🗺️ كل توصيلة بتعملها بتكبر فيها شركتنا وانت كمان.", // --- التحفيز والتشجيع --- "صباح النشاط: ☀️ بلّش نهارك بطاقة إيجابية وانطلق لتكسب أكتر.", "كل مشوار فرصة: 🏁 لا توقف، الطريق لإلك والنجاح ناطرك.", "يوم مربح: 💼 السوق ناشط اليوم، لا تفوّت الفرصة!", "جاهز للطلب الجاي: 🔔 الزبون الجاي ممكن يكون أوفر ممتاز، خليك مستعد.", // --- نصايح ومعلومات --- "نصيحة اليوم: روح صوب الأسواق والمطاعم، الطلب هناك عالي هالفترة. 🏙️", "حافظ على تقييمك: 😊 الزبون بينجذب للكابتن يلي عنده تقييم عالي وابتسامة.", "جو ممطر: 🌧️ المطر يعني طلبات أكتر، خليك شغّال بهالوقت!", "حدث اليوم: 🎆 في فعالية بالبلد، المشاوير كتيرة بهالمنطقة، استغلها!" ]; ================================================== FILE PATH: ./lib/constant/box_name.dart ================================================== class BoxName { static const String driverID = "driverID"; static const String countryCode = "countryCode"; static const String googlaMapApp = "googlaMapApp"; static const String keyOfApp = 'keyOfApp'; static const String initializationVector = 'initializationVector'; static const String firstTimeLoadKey = 'firstTimeLoadKey'; static const String jwt = "jwt"; static const String rideId = "rideId"; static const String rideArgumentsFromBackground = "rideArgumentsFromBackground"; static const String FCM_PRIVATE_KEY = "FCM_PRIVATE_KEY"; static const String hmac = "hmac"; static const String ttsEnabled = "ttsEnabled"; static const String walletType = "walletType"; static const String fingerPrint = "fingerPrint"; static const String updateInterval = "updateInterval"; static const String payMobApikey = "payMobApikey"; static const String refreshToken = "refreshToken"; static const String lang = "lang"; static const String isvibrate = "isvibrate"; static const String myListString = "myListString"; static const String myList = "myList"; static const String bodyOrder = "bodyOrder"; static const String gender = "gender"; static const String phoneWallet = "phoneWallet"; static const String locationName = "locationName"; static const String basicLink = "basicLink"; static const String paymentLink = "paymentLink"; static const String isSavedPhones = "IsSavedPhones"; static const String isTest = "isTest"; static const String carType = "carType"; static const String carTypeOfDriver = "carTypeOfDriver"; static const String isFirstTime = "isFirstTime"; static const String deviceInfo = "deviceInfo"; static const String packagInfo = "packagInfo"; static const String phoneVerified = "phoneVerified"; static const String carPlate = "carPlate"; static const String statusDriverLocation = "statusDriverLocation"; static const String rideStatus = "rideStatus"; static const String nameArabic = "nameArabic"; static const String carYear = "carYear"; static const String password = "password"; static const String isVerified = '0'; static const String arrivalTime = "arrivalTime"; static const String locationPermission = "locationPermission"; static const String passwordDriver = "passwordDriver"; static const String agreeTerms = "agreeTerms"; static const String addWork = 'addWork'; static const String addHome = 'addHome'; static const String rideArguments = 'rideArguments'; static const String durationData = 'durationData'; static const String rideStaticDriverData = 'rideStaticDriverData'; static const String lastTimeStaticThrottle = 'lastTimeStaticThrottle'; static const String lastTimeCaptainWalletCashOut = 'lastTimeCaptainWalletCashOut'; static const String tipPercentage = 'tipPercentage'; static const String accountIdStripeConnect = "accountIdStripeConnect"; static const String faceDetectTimes = "faceDetectTimes"; static const String sosPhonePassenger = "sosPhonePassenger"; static const String sosPhoneDriver = "sosPhoneDriver"; static const String passengerID = "pasengerID"; static const String phone = "phone"; static const String phoneDriver = "phoneDriver"; static const String is_claimed = "is_claimed"; static const String isInstall = "isInstall"; static const String isGiftToken = "isGiftToken"; static const String lastOtpTime = "lastOtpTime"; static const String bankCodeDriver = "bankCodeDriver"; static const String accountBankNumberDriver = "accountBankNumberDriver"; static const String dobDriver = "dobDriver"; static const String sexDriver = "sexDriver"; static const String lastNameDriver = "lastNameDriver"; static const String name = "name"; static const String nameDriver = "nameDriver"; static const String driverPhotoUrl = "driverPhotoUrl"; static const String email = "email"; static const String emailDriver = "emailDriver"; static const String tokens = "tokens"; static const String tokenFCM = "tokenFCM"; static const String tokenDriver = "tokenDriver"; static const String cardNumber = "cardNumber"; static const String cardNumberDriver = "cardNumberDriver"; static const String cardHolderName = "cardHolderName"; static const String cardHolderNameDriver = "cardHolderNameDriver"; static const String expiryDate = "expiryDate"; static const String expiryDateDriver = "expiryDateDriver"; static const String cvvCode = "cvvCode"; static const String cvvCodeDriver = "cvvCodeDriver"; static const String passengerWalletDetails = "passengerWalletDetails"; static const String passengerWalletTotal = "passengerWalletTotal"; static const String passengerWalletFound = "passengerWalletFound"; static const String periods = 'periods'; static const String onBoarding = 'onBoarding'; static const String stripePublishableKey = 'stripe_publishableKe'; static const String apiKeyRun = 'apiKeyRun'; static const String serverAPI = 'serverAPI'; static const String serverChosen = 'serverChosen'; static const String secretKey = 'secretKey'; static const String basicAuthCredentials = 'basicAuthCredentials'; static const String mapAPIKEY = 'mapAPIKEY'; static const String twilloRecoveryCode = 'twilloRecoveryCode'; static const String accountSIDTwillo = 'accountSIDTwillo'; static const String authTokenTwillo = 'authTokenTwillo'; static const String chatGPTkey = 'chatGPTkey'; static const String chatGPTkeySefer = 'chatGPTkeySefer'; static const String transactionCloude = 'transactionCloude'; static const String visionApi = 'visionApi'; static const String vin = "vin"; static const String make = "make"; static const String model = "model"; static const String year = "year"; static const String expirationDate = "expirationDate"; static const String color = "color"; static const String owner = "owner"; static const String registrationDate = "registrationDate"; static const String recentLocations = 'recentLocations'; static const String tripData = 'tripData'; } ================================================== FILE PATH: ./lib/constant/info.dart ================================================== class AppInformation { static const String companyName = 'Intaleq'; static const String appName = 'Intaleq DRIVER'; static const String appVersion = 'Intaleq DRIVER'; static const String phoneNumber = '962798583052'; static const String linkedInProfile = 'https://www.linkedin.com/in/hamza-ayed/'; static const String website = 'https://intaleqapp.com'; static const String email = 'hamzaayed@intaleqapp.com'; static const String complaintPrompt = 'for this data for complaint from driver or passenger i collect all data i want you analyze this complaint and show what is reason and what is solution .this data collected from many table to find solution if payment in visa not complete and if ride status is finished it will be paymnet in payment table if ride status is not finished there is no need to pay and payment table is null for this ride and if paymentFromPaymentTable not null and visa type not cash the payment sucssessed . if ratingpassenger is low or passengr rating drivers low grade then dont mine of this passenger ,look at driver too like passengerratingdriver with rating or ratingtopassenger .in json add status of complaint and message to passenger and message to driver and message to call center write in arabic in json output with key in english .for output please just json i want'; static const String addd = 'BlBlNl'; static const String privacyPolicy = ''' Intaleq - Privacy Policy & Terms of Use

Privacy Policy & Terms of Use

Effective Date: August 9, 2025

Last Updated: August 9, 2025

1. Introduction and Acceptance

By downloading, registering, or using the Intaleq application ("App"), you agree to be bound by this Privacy Policy and our Terms of Use. If you do not agree, you must stop using the App immediately. Your continued use constitutes acceptance of these terms and any future updates.

2. Definitions

  • "Intaleq", "we", "us": Refers to the Intaleq for Ride Hailing company, Damascus – Syria (Owner & operator), which provides the technology platform.
  • "Driver": An independent service provider who uses the App to offer transportation services.
  • "Passenger", "you": An individual who uses the App to request transportation services.
  • "Services": The connection between Passengers and Drivers facilitated by our App.

3. Privacy Policy

3.1 Information We Collect

We collect information necessary to provide and improve our Services.

A. Information You Provide:

  • For Drivers: To ensure safety and compliance, we collect identity information, including your full name, phone number, personal photo, and official documents (e.g., driver's license, vehicle registration).
  • For Passengers: We only require a phone number for registration and communication. We are not authorized to request or view official identity documents for passengers.

B. Information Collected Automatically:

  • Location Data: We collect precise location data when the App is in use to facilitate ride matching, navigation, and for safety purposes.
  • Device Data: We collect information about your device, such as model, operating system, and unique identifiers, to ensure App functionality and for security verification.
  • Usage Data: We log how you interact with our App, including trip history and features used, to improve our services.

3.2 Payment Information

We do not collect, process, or store any sensitive payment information like credit/debit card numbers. We facilitate payments by connecting you to licensed, local third-party providers:

  • Mobile Carrier Billing: Payments via MTN and Syriatel are processed directly by them based on your registered phone number. A one-time password (OTP) sent by the carrier is required to confirm the transaction.
  • Bank Card Payments: We connect you with the Syrian company "eCash" to process card payments. They handle the transaction, and your bank will send an OTP to your phone to authorize it.

3.3 How We Use Your Information

  • To operate and maintain the Services (e.g., connect Drivers and Passengers).
  • To verify Driver identity and eligibility.
  • To improve App security and prevent fraud.
  • To provide customer support.
  • To comply with legal obligations.

3.4 Data Sharing

We do not sell your personal data. We only share it in the following limited circumstances:

  • Between Passenger and Driver: To facilitate a ride, we share necessary information like name, photo, and real-time location.
  • With Service Providers: For services like payment processing and mapping. These providers are contractually obligated to protect your data.
  • For Legal Reasons: If required by law or a valid legal order.

3.5 Policy for Minors

Our services are intended for individuals over the age of 18. For Drivers: We strictly verify the identity and age of all drivers to ensure no minors are operating on our platform. For Passengers: While we do not verify passenger identity, the service is not directed at children under 18. If a parent or guardian becomes aware that their child has provided us with information without their consent, they should contact us immediately.

4. User Obligations & Conduct

  • You must provide accurate and current information during registration.
  • You are responsible for maintaining the security of your account.
  • You agree not to use the App for any illegal activities, to harass others, or to cause damage to a Driver's vehicle.

5. Disclaimer of Liability

The App is provided "as is". Intaleq is an intermediary platform and is not liable for the actions of Drivers or Passengers, accidents, delays, or any disputes between users. Our liability is limited to the fullest extent permitted by law.

6. Policy Updates

We may update these terms. If we make significant changes, we will notify you within the App. You will be required to review and accept the new terms to continue using the Services, ensuring your consent is active and informed.

7. Account Deletion & Contact

You have the right to request the deletion of your account and personal data. To do so, or for any other questions, please contact us. We will respond to deletion requests within 30 days.

Email: support@intaleqapp.com

'''; static const String privacyPolicyArabic = ''' انطلق - سياسة الخصوصية وشروط الاستخدام

سياسة الخصوصية وشروط الاستخدام

تاريخ النفاذ: 9 أغسطس 2025

آخر تحديث: 9 أغسطس 2025

1. المقدمة والقبول

عبر تحميل أو تسجيل أو استخدام تطبيق "انطلق" ("التطبيق")، فإنك توافق على الالتزام بسياسة الخصوصية وشروط الاستخدام هذه. إذا كنت لا توافق، يجب عليك التوقف فورًا عن استخدام التطبيق. استمرارك في الاستخدام يُعد قبولاً لهذه الشروط وأي تحديثات مستقبلية لها.

2. التعريفات

  • "انطلق"، "نحن": تشير إلى شركة انطلق لنقل الركاب، دمشق – سوريا (مالك ومشغل التطبيق)، التي توفر المنصة التقنية.
  • "السائق": مقدم خدمة مستقل يستخدم التطبيق لتقديم خدمات النقل.
  • "الراكب"، "أنت": الفرد الذي يستخدم التطبيق لطلب خدمات النقل.
  • "الخدمات": عملية الربط بين الركاب والسائقين التي يسهلها تطبيقنا.

3. سياسة الخصوصية

3.1 المعلومات التي نجمعها

نحن نجمع المعلومات الضرورية لتقديم خدماتنا وتحسينها.

أ. المعلومات التي تقدمها بنفسك:

  • بالنسبة للسائقين: لضمان السلامة والامتثال للقوانين، نجمع بيانات الهوية الشخصية، بما في ذلك الاسم الكامل، رقم الهاتف، صورة شخصية، والوثائق الرسمية (مثل رخصة القيادة وتسجيل المركبة).
  • بالنسبة للركاب: نطلب فقط رقم هاتف للتسجيل والتواصل. نحن غير مخولين بطلب أو الاطلاع على وثائق الهوية الرسمية للركاب.

ب. المعلومات التي تُجمع تلقائيًا:

  • بيانات الموقع: نجمع بيانات الموقع الجغرافي الدقيقة عند استخدام التطبيق لتسهيل تحديد أماكن الانطلاق والوصول، الملاحة، ولأغراض السلامة.
  • بيانات الجهاز: نجمع معلومات عن جهازك (طراز، نظام تشغيل، معرفات فريدة) لضمان عمل التطبيق وللتحقق الأمني.
  • بيانات الاستخدام: نسجل كيفية تفاعلك مع التطبيق، بما في ذلك سجل الرحلات والميزات المستخدمة، بهدف تحسين خدماتنا.

3.2 معلومات الدفع

نحن لا نجمع أو نعالج أو نخزن أي معلومات دفع حساسة مثل أرقام بطاقات الائتمان/الخصم. نحن نسهل عمليات الدفع عبر ربطك بمزودي خدمات محليين مرخصين:

  • الدفع عبر رصيد الهاتف المحمول: تتم معالجة الدفعات عبر شركتي MTN و Syriatel مباشرة من خلالهما بناءً على رقم هاتفك المسجل لديهم. يتطلب تأكيد العملية إدخال رمز تحقق (OTP) يُرسل من قبل شركة الاتصالات.
  • الدفع عبر البطاقات البنكية: نربطك بشركة "eCash" السورية لمعالجة الدفعات بالبطاقات. هي التي تتولى المعاملة، وسيقوم البنك الذي تتعامل معه بإرسال رمز تحقق (OTP) إلى هاتفك لتفويض العملية.

3.3 كيف نستخدم معلوماتك

  • لتشغيل وصيانة الخدمات (مثل الربط بين السائقين والركاب).
  • للتحقق من هوية السائقين وأهليتهم.
  • لتحسين أمان التطبيق ومنع الاحتيال.
  • لتقديم الدعم الفني للعملاء.
  • للامتثال للالتزامات القانونية.

3.4 مشاركة البيانات

نحن لا نبيع بياناتك الشخصية. نشاركها فقط في الحالات المحدودة التالية:

  • بين الراكب والسائق: لتسهيل الرحلة، نشارك المعلومات الضرورية مثل الاسم، الصورة، والموقع المباشر.
  • مع مزودي الخدمات: مثل معالجي الدفع وخدمات الخرائط. هؤلاء المزودون ملزمون تعاقديًا بحماية بياناتك.
  • لأسباب قانونية: إذا طُلب ذلك بموجب القانون أو أمر قضائي ساري المفعول.

3.5 سياسة القاصرين

خدماتنا موجهة للأفراد الذين تزيد أعمارهم عن 18 عامًا. بالنسبة للسائقين: نحن نتحقق بدقة من هوية وعمر جميع السائقين لضمان عدم وجود قاصرين يعملون على منصتنا. بالنسبة للركاب: على الرغم من أننا لا نتحقق من هوية الركاب، فإن الخدمة غير موجهة للأطفال دون سن 18. إذا علم ولي الأمر أن طفله قد زودنا بمعلومات دون موافقته، فيجب عليه الاتصال بنا على الفور.

4. التزامات المستخدم وسلوكه

  • يجب عليك تقديم معلومات دقيقة وحديثة عند التسجيل.
  • أنت مسؤول عن الحفاظ على أمان حسابك.
  • أنت توافق على عدم استخدام التطبيق لأي أنشطة غير قانونية، أو لمضايقة الآخرين، أو التسبب في ضرر لمركبة السائق.

5. إخلاء المسؤولية

يتم تقديم التطبيق "كما هو". "انطلق" هي منصة وسيطة وليست مسؤولة عن تصرفات السائقين أو الركاب، أو الحوادث، أو التأخير، أو أي نزاعات بين المستخدمين. مسؤوليتنا محدودة إلى أقصى حد يسمح به القانون.

6. تحديثات السياسة

قد نقوم بتحديث هذه الشروط. في حال إجراء تغييرات جوهرية، سنقوم بإعلامك داخل التطبيق. سيُطلب منك مراجعة الشروط الجديدة وقبولها لمواصلة استخدام الخدمات، لضمان أن موافقتك فعالة ومبنية على معرفة.

7. حذف الحساب والتواصل

لديك الحق في طلب حذف حسابك وبياناتك الشخصية. للقيام بذلك، أو لأي استفسارات أخرى، يرجى التواصل معنا. سنرد على طلبات الحذف في غضون 30 يومًا.

البريد الإلكتروني: support@intaleqapp.com

'''; } ================================================== FILE PATH: ./lib/constant/links.dart ================================================== // import 'package:sefer_driver/env/env.dart'; import '../main.dart'; import 'box_name.dart'; class AppLink { static String serverPHP = box.read('serverPHP'); static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main'; static String locationServer = 'https://location.intaleq.xyz/intaleq/ride/location'; static final String endPoint = 'https://api.intaleq.xyz/intaleq'; static final String syria = 'https://syria.intaleq.xyz/intaleq'; static final String server = endPoint; static String ride = '$endPoint/ride'; static String rideServer = 'https://rides.intaleq.xyz/intaleq/ride'; static String seferCairoServer = endPoint; static String seferGizaServer = box.read('Giza') ?? box.read(BoxName.serverChosen); static String seferAlexandriaServer = box.read('Alexandria') ?? box.read(BoxName.serverChosen); // static final String server = Env.serverPHP; static String loginJwtDriver = "$server/loginJwtDriver.php"; static String loginJwtWalletDriver = "$server/loginJwtWalletDriver.php"; static String loginFirstTimeDriver = "$server/loginFirstTimeDriver.php"; static String googleMapsLink = 'https://maps.googleapis.com/maps/api/'; static String llama = 'https://api.llama-api.com/chat/completions'; static String gemini = 'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText'; static String test = "$server/test.php"; //===============contact========================== static String savePhones = "$ride/egyptPhones/add.php"; static String savePhonesSyria = "$ride/egyptPhones/syrianAdd.php"; static String getPhones = "$ride/egyptPhones/get.php"; ////===============firebase========================== static String getTokens = "$ride/firebase/get.php"; static String getDriverToken = "$ride/firebase/getDriverToken.php"; static String addTokens = "$ride/firebase/add.php"; static String addTokensDriver = "$ride/firebase/addDriver.php"; static String addTokensDriverWallet = "$paymentServer/ride/firebase/addDriver.php"; //=======================Wallet=================== static String wallet = '$paymentServer/ride/passengerWallet'; static String walletDriver = '$paymentServer/ride/driverWallet'; static String getAllPassengerTransaction = "$wallet/getAllPassengerTransaction.php"; static String payWithMTNConfirm = "$paymentServer/ride/mtn/driver/confirm_payment.php"; static String payWithMTNStart = "$paymentServer/ride/mtn/driver/mtn_start.php"; static String payWithSyriatelConfirm = "$paymentServer/ride/syriatel/driver/confirm_payment.php"; static String payWithSyriatelStart = "$paymentServer/ride/syriatel/driver/start_payment.php"; static String payWithEcashDriver = "$paymentServer/ride/ecash/driver/payWithEcash.php"; static String payWithEcashPassenger = "$paymentServer/ride/ecash/passenger/payWithEcash.php"; // wl.tripz-egypt.com/v1/main/ride/ecash/driver static String getWalletByPassenger = "$wallet/getWalletByPassenger.php"; static String getPassengersWallet = "$wallet/get.php"; static String getPassengerWalletArchive = "$wallet/getPassengerWalletArchive.php"; static String addPassengersWallet = "$wallet/add.php"; static String deletePassengersWallet = "$wallet/delete.php"; static String updatePassengersWallet = "$wallet/update.php"; static String getWalletByDriver = "$walletDriver/getWalletByDriver.php"; static String driverStatistic = "$endPoint/ride/driverWallet/driverStatistic.php"; static String getDriverDetails = "$seferCairoServer/ride/driverWallet/getDriverDetails.php"; static String getDriverWeekPaymentMove = "$walletDriver/getDriverWeekPaymentMove.php"; static String getDriversWallet = "$walletDriver/get.php"; static String addDriversWalletPoints = "$walletDriver/add.php"; static String addpromotionDriver = "$walletDriver/promotionDriver.php"; static String deleteDriversWallet = "$walletDriver/delete.php"; static String updateDriversWallet = "$walletDriver/update.php"; //=======================promo===================ride.mobile-app.store/ride/promo/get.php static String promo = '$server/ride/promo'; static String getPassengersPromo = "$promo/get.php"; static String getPromoBytody = "$promo/getPromoBytody.php"; static String addPassengersPromo = "$promo/add.php"; static String deletePassengersPromo = "$promo/delete.php"; static String updatePassengersPromo = "$promo/update.php"; ////=======================cancelRide=================== static String addCancelRideFromPassenger = "$rideServer/cancelRide/add.php"; static String addCancelTripFromDriverAfterApplied = "$rideServer/cancelRide/addCancelTripFromDriverAfterApplied.php"; static String cancelRide = "$rideServer/cancelRide/get.php"; //-----------------ridessss------------------ static String addRides = "$rideServer/rides/add.php"; static String getRides = "$rideServer/rides/get.php"; static String getPlacesSyria = "$rideServer/places_syria/get.php"; static String getMishwari = "$rideServer/mishwari/get.php"; static String getMishwariDriver = "$rideServer/mishwari/getDriver.php"; static String getTripCountByCaptain = "$rideServer/rides/getTripCountByCaptain.php"; static String getRideOrderID = "$rideServer/rides/getRideOrderID.php"; static String getRideStatus = "$rideServer/rides/getRideStatus.php"; static String getOverLayStatus = "$ride/overLay/get.php"; static String getArgumentAfterAppliedFromBackground = "$ride/overLay/getArgumentAfterAppliedFromBackground.php"; static String addOverLayStatus = "$ride/overLay/add.php"; static String getapiKey = "$ride/apiKey/get.php"; static String getapiKeySefer = "$ride/apiKey/get.php"; static String getRideStatusBegin = "$rideServer/rides/getRideStatusBegin.php"; static String getRideStatusFromStartApp = "$rideServer/rides/getRideStatusFromStartApp.php"; static String updateRides = "$rideServer/rides/update.php"; static String updateRideAndCheckIfApplied = "$rideServer/rides/updateRideAndCheckIfApplied.php"; static String updateStausFromSpeed = "$rideServer/rides/updateStausFromSpeed.php"; static String deleteRides = "$rideServer/rides/delete.php"; //-----------------DriverPayment------------------ static String addDriverScam = "$ride/driver_scam/add.php"; static String getDriverScam = "$ride/driver_scam/get.php"; /////////---getKazanPercent===//////////// static String getKazanPercent = "$ride/kazan/get.php"; static String addKazanPercent = "$ride/kazan/add.php"; ////-----------------DriverPayment------------------ static String addDrivePayment = "$paymentServer/ride/payment/add.php"; static String payWithPayMobCardDriver = "$paymentServer/ride/payMob/paymob_driver/payWithCard.php"; static String payWithWallet = "$paymentServer/ride/payMob/paymob_driver/payWithWallet.php"; static String paymetVerifyDriver = "$paymentServer/ride/payMob/paymob_driver/paymet_verfy.php"; static String updatePaymetToPaid = "$paymentServer/ride/payment/updatePaymetToPaid.php"; static String paymobPayoutDriverWallet = "$paymentServer/ride/payMob/paymob_driver/paymob_payout.php'"; static String addSeferWallet = "$paymentServer/ride/seferWallet/add.php"; static String getSeferWallet = "$paymentServer/ride/seferWallet/get.php"; static String addDriverPaymentPoints = "$paymentServer/ride/driverPayment/add.php"; static String addPaymentTokenDriver = "$paymentServer/ride/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php static String addPaymentTokenPassenger = "$paymentServer/ride/passengerWallet/addPaymentTokenPassenger.php"; static String getDriverPaymentPoints = "$paymentServer/ride/driverWallet/get.php"; static String getDriverPaymentToday = "$paymentServer/ride/payment/get.php"; static String getCountRide = "$rideServer/payment/getCountRide.php"; static String getAllPaymentFromRide = "$paymentServer/ride/payment/getAllPayment.php"; static String getAllPaymentVisa = "$paymentServer/ride/payment/getAllPaymentVisa.php"; //-----------------Passenger NotificationCaptain------------------ static String addNotificationPassenger = "$ride/notificationPassenger/add.php"; static String getNotificationPassenger = "$ride/notificationPassenger/get.php"; static String updateNotificationPassenger = "$ride/notificationPassenger/update.php"; //-----------------Driver NotificationCaptain------------------ static String addNotificationCaptain = "$ride/notificationCaptain/add.php"; static String addWaitingRide = "$ride/notificationCaptain/addWaitingRide.php"; static String deleteAvailableRide = "$ride/notificationCaptain/deleteAvailableRide.php"; static String updateWaitingRide = "$ride/notificationCaptain/updateWaitingTrip.php"; static String getRideWaiting = "$endPoint/ride/notificationCaptain/getRideWaiting.php"; static String getNotificationCaptain = "$ride/notificationCaptain/get.php"; static String updateNotificationCaptain = "$ride/notificationCaptain/update.php"; static String deleteNotificationCaptain = "$ride/notificationCaptain/delete.php"; //-----------------Api Key------------------ static String addApiKey = "$ride/apiKey/add.php"; static String getApiKey = "$ride/apiKey/get.php"; static String getCnMap = "$server/auth/cnMap.php"; static String getPromptDriverDocumentsEgypt = "$server/auth/captin/getPromptDriverDocumentsEgypt.php"; static String updateApiKey = "$ride/apiKey/update.php"; static String deleteApiKey = "$ride/apiKey/delete.php"; static String checkPhoneNumberISVerfiedDriver = "$auth/checkPhoneNumberISVerfiedDriver.php"; static String getTesterApp = "$auth/Tester/getTesterApp.php"; static String updateTesterApp = "$auth/Tester/updateTesterApp.php"; //-----------------healthInsuranceProvider------------------ static String addHealthInsuranceProvider = "$server/driver_assurance/add.php"; static String getHealthInsuranceProvider = "$server/driver_assurance/get.php"; //-----------------Feed Back------------------ static String addFeedBack = "$ride/feedBack/add.php"; static String getFeedBack = "$ride/feedBack/get.php"; static String updateFeedBack = "$ride/feedBack/updateFeedBack.php"; //-----------------Tips------------------ static String addTips = "$ride/tips/add.php"; static String getTips = "$ride/tips/get.php"; static String updateTips = "$ride/tips/update.php"; //-----------------Help Center------------------ static String addhelpCenter = "$ride/helpCenter/add.php"; static String gethelpCenter = "$ride/helpCenter/get.php"; static String getByIdhelpCenter = "$ride/helpCenter/getById.php"; static String updatehelpCenter = "$ride/helpCenter/update.php"; static String deletehelpCenter = "$ride/helpCenter/delete.php"; //-----------------license------------------ static String addLicense = "$ride/license/add.php"; static String getLicense = "$ride/license/get.php"; static String updateLicense = "$ride/license/updateFeedBack.php"; //-----------------RegisrationCar------------------ static String addRegisrationCar = "$ride/RegisrationCar/add.php"; static String getRegisrationCar = "$endPoint/ride/RegisrationCar/get.php"; static String updateRegisrationCar = "$ride/RegisrationCar/update.php"; static String makeDefaultCar = "$ride/RegisrationCar/makeDefaultCar.php"; //-----------------DriverOrder------------------ static String addDriverOrder = "$ride/driver_order/add.php"; static String getDriverOrder = "$ride/driver_order/get.php"; static String getOrderCancelStatus = "$ride/driver_order/getOrderCancelStatus.php"; static String updateDriverOrder = "$ride/driver_order/update.php"; static String deleteDriverOrder = "$ride/driver_order/delete.php"; // ===================================== static String addRateToPassenger = "$ride/rate/add.php"; static String addRateToDriver = "$ride/rate/addRateToDriver.php"; static String addRateApp = "$ride/rate/add_rate_app.php"; static String sendEmailRateingApp = "$ride/rate/sendEmailRateingApp.php"; static String getDriverRate = "$ride/rate/getDriverRate.php"; static String getPassengerRate = "$ride/rate/getPassengerRate.php"; ////////////////emails ============// static String sendEmailToPassengerForTripDetails = "$ride/rides/emailToPassengerTripDetail.php"; static String sendEmailToDrivertransaction = "$server/Admin/sendEmailToDrivertransaction.php"; // =========================================== static String pathImage = "$server/upload/types/"; static String uploadImage = "$server/uploadImage.php"; static String uploadImage1 = "$server/uploadImage1.php"; static String uploadImagePortrate = "$server/uploadImagePortrate.php"; static String uploadSyrianDocs = "$syria/auth/syria/uploadSyrianDocs.php"; static String uploadImageType = "$server/uploadImageType.php"; //=============egypt documents ============== static String uploadEgyptidFront = "$server/EgyptDocuments/uploadEgyptidFront.php"; static String uploadEgypt = "$server/uploadEgypt.php"; static String uploadEgypt1 = "$server/uploadEgypt1.php"; //==================certifcate========== // static String location = '$endPoint/ride/location'; static String getCarsLocationByPassenger = "$locationServer/get.php"; static String addpassengerLocation = "$locationServer/addpassengerLocation.php"; static String getLocationAreaLinks = "$locationServer/get_location_area_links.php"; static String getLatestLocationPassenger = "$locationServer/getLatestLocationPassenger.php"; static String getFemalDriverLocationByPassenger = "$locationServer/getFemalDriver.php"; static String getDriverCarsLocationToPassengerAfterApplied = "$locationServer/getDriverCarsLocationToPassengerAfterApplied.php"; static String addCarsLocationByPassenger = "$locationServer/add.php"; static String saveBehavior = "$locationServer/save_behavior.php"; static String addCarsLocationGizaEndpoint = "$locationServer/add.php"; static String addCarsLocationAlexandriaEndpoint = "$locationServer/add.php"; static String addCarsLocationCairoEndpoint = "$locationServer/add.php"; static String deleteCarsLocationByPassenger = "$locationServer/delete.php"; static String updateCarsLocationByPassenger = "$locationServer/update.php"; static String getTotalDriverDuration = "$locationServer/getTotalDriverDuration.php"; static String getRidesDriverByDay = "$locationServer/getRidesDriverByDay.php"; static String getTotalDriverDurationToday = "$locationServer/getTotalDriverDurationToday.php"; //==================get_driver_behavior.php============= static String get_driver_behavior = '$ride/driver_behavior/get_driver_behavior.php'; //==================cars new drivers============= static String addNewCarsDrivers = '$ride/carDrivers/add.php'; static String getNewCarsDrivers = '$ride/carDrivers/get.php'; static String deleteNewCarsDrivers = '$ride/carDrivers/delete.php'; //==================Blog============= static String profile = '$ride/profile'; static String getprofile = "$profile/get.php"; static String getCaptainProfile = "$profile/getCaptainProfile.php"; static String addprofile = "$profile/add.php"; static String deleteprofile = "$profile/delete.php"; static String updateprofile = "$profile/update.php"; static String updateDriverEmail = "$profile/updateDriverEmail.php"; //===================Auth============ static String addInviteDriver = "$ride/invitor/add.php"; static String addInvitationPassenger = "$ride/invitor/addInvitationPassenger.php"; static String getInviteDriver = "$ride/invitor/get.php"; static String getDriverInvitationToPassengers = "$ride/invitor/getDriverInvitationToPassengers.php"; static String updateInviteDriver = "$ride/invitor/update.php"; static String updatePassengerGift = "$ride/invitor/updatePassengerGift.php"; static String updateInvitationCodeFromRegister = "$ride/invitor/updateInvitationCodeFromRegister.php"; static String register_driver_and_car = "$auth/syria/driver/register_driver_and_car.php"; static String updateDriverInvitationDirectly = "$ride/invitor/updateDriverInvitationDirectly.php"; static String updatePassengersInvitation = "$ride/invitor/updatePassengersInvitation.php"; //===================Auth============ static String auth = '$server/auth'; static String login = "$auth/login.php"; static String signUp = "$auth/signup.php"; static String updateDriverClaim = "$auth/captin/updateDriverClaim.php"; static String updateShamCashDriver = "$auth/captin/updateShamCashDriver.php"; static String sendVerifyEmail = "$auth/sendVerifyEmail.php"; static String passengerRemovedAccountEmail = "$auth/passengerRemovedAccountEmail.php"; static String verifyEmail = "$auth/verifyEmail.php"; //===================Auth Captin============ static String authCaptin = '$server/auth/captin'; static String loginCaptin = "$authCaptin/login.php"; static String loginFromGoogleCaptin = "$authCaptin/loginFromGoogle.php"; static String loginUsingCredentialsWithoutGoogle = "$authCaptin/loginUsingCredentialsWithoutGoogle.php"; static String packageInfo = "$server/auth/packageInfo.php"; static String signUpCaptin = "$authCaptin/register.php"; static String addCriminalDocuments = "$authCaptin/addCriminalDocuments.php"; static String sendVerifyEmailCaptin = "$authCaptin/sendVerifyEmail.php"; static String sendVerifyOtpMessage = "$server/auth/captin/sendOtpMessageDriver.php"; static String verifyOtpMessage = "$server/auth/verifyOtpMessage.php"; static String verifyOtpDriver = "$server/auth/captin/verifyOtpDriver.php"; static String verifyEmailCaptin = "$authCaptin/verifyEmail.php"; static String removeUser = "$authCaptin/removeAccount.php"; static String deletecaptainAccounr = "$authCaptin/deletecaptainAccounr.php"; static String updateAccountBank = "$authCaptin/updateAccountBank.php"; static String getAccount = "$authCaptin/getAccount.php"; static String uploadImageToAi = "$auth/document_syria/ai_document.php"; static String isPhoneVerified = "$auth/syria/driver/isPhoneVerified.php"; //===================Admin Captin============ static String getPassengerDetailsByPassengerID = "$server/Admin/getPassengerDetailsByPassengerID.php"; static String getPassengerDetails = "$server/Admin/getPassengerDetails.php"; static String getPassengerbyEmail = "$server/Admin/getPassengerbyEmail.php"; static String addAdminUser = "$server/Admin/adminUser/add.php"; static String addError = "$server/Admin/errorApp.php"; static String getAdminUser = "$server/Admin/adminUser/get.php"; static String getCaptainDetailsByEmailOrIDOrPhone = "$server/Admin/AdminCaptain/getCaptainDetailsByEmailOrIDOrPhone.php"; static String getCaptainDetails = "$server/Admin/AdminCaptain/get.php"; static String getRidesPerMonth = "$server/Admin/AdminRide/getRidesPerMonth.php"; static String getRidesDetails = "$server/Admin/AdminRide/get.php"; //////////Sms egypt/////////// static String sendSms = "https://sms.kazumi.me/api/sms/send-sms"; static String senddlr = "https://sms.kazumi.me/api/sms/send-dlr"; static String sendvalidity = "https://sms.kazumi.me/api/sms/send-validity"; static String sendmany = "https://sms.kazumi.me/api/sms/send-many"; static String checkCredit = "https://sms.kazumi.me/api/sms/check-credit"; static String checkStatus = "https://sms.kazumi.me/api/sms/check-status"; static String getSender = "$server/auth/sms/getSender.php"; static String updatePhoneInvalidSMS = "$server/auth/sms/updatePhoneInvalidSMS.php"; //////////////service/////////// static String serviceApp = "$server/serviceapp"; static String getComplaintAllData = "$serviceApp/getComplaintAllData.php"; static String getComplaintAllDataForDriver = "$serviceApp/getComplaintAllDataForDriver.php"; } ================================================== FILE PATH: ./lib/constant/credential.dart ================================================== import 'dart:convert'; import 'package:crypto/crypto.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../controller/functions/crud.dart'; import '../main.dart'; import 'box_name.dart'; import 'char_map.dart'; import 'links.dart'; class AC { gAK() async { if (box.read(BoxName.apiKeyRun).toString() != 'run') { var res = await CRUD().get(link: AppLink.getApiKey, payload: {}); var decod = jsonDecode(res); // print(decod); Map jsonData = {}; for (var i = 0; i < decod['message'].length; i++) { String h = decod['message'][i]['hashed_key'].toString(); String retrievedString = X.r(X.r(X.r(h, cn), cC), cs); await storage.write( key: decod['message'][i]['name'].toString(), value: retrievedString.toString(), ); // String name = decod['message'][i]['name'].toString(); String value = decod['message'][i]['hashed_key'].toString(); jsonData[name] = value; } String jsonString = json.encode(jsonData); print(jsonString); box.write(BoxName.apiKeyRun, 'run'); } } String q(String b, String c) { final d = utf8.encode(c); final e = utf8.encode(b); final f = Hmac(sha256, d); final g = f.convert(e); final h = g.bytes; final i = base64Url.encode(h); return i; } String j(String k, String l) { final m = utf8.encode(l); final n = base64Url.decode(k); final o = Hmac(sha256, m); final p = o.convert(n); final q = utf8.decode(p.bytes); return q; } String a(String b, String c) { int d = b.length; int e = d ~/ 4; List f = []; for (int g = 0; g < d; g += e) { int h = g + e; if (h > d) { h = d; } String i = b.substring(g, h); f.add(i); } print(f); Map j = {}; j['birinci'] = f[4]; j['ikinci'] = f[2]; j['üçüncü'] = c + f[1]; j['dördüncü'] = f[0]; j['beş'] = f[3]; String k = ''; j.forEach((l, m) { k += m; }); return k; } Map n(String o, String c) { String p = o.replaceAll(c, ''); Map q = {}; q['birinci'] = p[p.length - 5] + p[p.length - 3]; q['ikinci'] = p[p.length - 1] + p[p.length - 15]; q['üçüncü'] = p[p.length - 9] + p[p.length - 12]; q['dördüncü'] = p[p.length - 11] + p[p.length - 6]; q['beş'] = p[p.length - 2] + p[p.length - 8]; return q; } } ================================================== FILE PATH: ./lib/constant/api_key.dart ================================================== import 'package:secure_string_operations/secure_string_operations.dart'; import '../env/env.dart'; import 'char_map.dart'; class AK { static final String sss_pass = X.r(X.r(X.r(Env.sss_pass, cn), cC), cs); static final String allowed = Env.allowed; static final String allowedWallet = Env.allowedWallet; static final String passnpassenger = X .r(X.r(X.r(Env.passnpassenger, cn), cC), cs) .toString() .split(Env.addd)[0]; static final String newId = Env.newId; static final String sss_encryptionSalt = X.r(X.r(X.r(Env.sss_encryptionSalt, cn), cC), cs); static final String publishableKeyStripe = X.r(X.r(X.r(Env.stripePublishableKe, cn), cC), cs); static final String secretKeyStripe = X.r(X.r(X.r(Env.secretKey, cn), cC), cs); static final String basicAuthCredentials = X.r(X.r(X.r(Env.basicAuthCredentials, cn), cC), cs); static final String basicCompareFaces = X.r(X.r(X.r(Env.basicCompareFaces, cn), cC), cs); static final String accountSIDTwillo = X.r(X.r(X.r(Env.accountSIDTwillo, cn), cC), cs); static final String serverAPI = X.r(X.r(X.r(Env.serverAPI, cn), cC), cs); static final String mapAPIKEY = Env.mapAPIKEY; static final String twilloRecoveryCode = X.r(X.r(X.r(Env.twilloRecoveryCode, cn), cC), cs); static final String authTokenTwillo = X.r(X.r(X.r(Env.authTokenTwillo, cn), cC), cs); static final String chatGPTkey = X.r(X.r(X.r(Env.chatGPTkey, cn), cC), cs); static final String transactionCloude = X.r(X.r(X.r(Env.transactionCloude, cn), cC), cs); static final String visionApi = X.r(X.r(X.r(Env.visionApi, cn), cC), cs); static final String chatGPTkeySefer = X.r(X.r(X.r(Env.chatGPTkeySefer, cn), cC), cs); static final String chatGPTkeySeferNew = X.r(X.r(X.r(Env.chatGPTkeySeferNew, cn), cC), cs); static final String serverPHP = Env.serverPHP; static final String llamaKey = X.r(X.r(X.r(Env.llamaKey, cn), cC), cs); static final String cohere = X.r(X.r(X.r(Env.cohere, cn), cC), cs); static final String claudeAiAPI = X.r(X.r(X.r(Env.claudeAiAPI, cn), cC), cs); static final String payPalClientId = X.r(X.r(X.r(Env.payPalClientId, cn), cC), cs); static final String payPalSecret = X.r(X.r(X.r(Env.payPalSecret, cn), cC), cs); static final String geminiApi = X.r(X.r(X.r(Env.geminiApi, cn), cC), cs); static final String agoraAppId = X.r(X.r(X.r(Env.agoraAppId, cn), cC), cs); static final String agoraAppCertificate = X.r(X.r(X.r(Env.agoraAppCertificate, cn), cC), cs); static final String payPalClientIdLive = X.r(X.r(X.r(Env.payPalClientIdLive, cn), cC), cs); static final String payPalSecretLive = X.r(X.r(X.r(Env.payPalSecretLive, cn), cC), cs); static final String integrationIdPayMob = X.r(X.r(X.r(Env.integrationIdPayMob, cn), cC), cs); static final String passwordPayMob = X.r(X.r(X.r(Env.passwordPayMob, cn), cC), cs); static final String usernamePayMob = X.r(X.r(X.r(Env.usernamePayMob, cn), cC), cs); static final String payMobApikey = X.r(X.r(X.r(Env.payMobApikey, cn), cC), cs); static final String integrationIdPayMobWallet = X.r(X.r(X.r(Env.integrationIdPayMobWallet, cn), cC), cs); static final String smsPasswordEgypt = X.r(X.r(X.r(Env.smsPasswordEgypt, cn), cC), cs); static final String ocpApimSubscriptionKey = Env.ocpApimSubscriptionKey; static final String chatGPTkeySeferNew4 = X.r(X.r(X.r(Env.chatGPTkeySeferNew4, cn), cC), cs); static final String anthropicAIkeySeferNew = X.r(X.r(X.r(Env.anthropicAIkeySeferNew, cn), cC), cs); static final String llama3Key = X.r(X.r(X.r(Env.llama3Key, cn), cC), cs); static final String payMobOutPassword = X.r(X.r(X.r(Env.payMobOutPassword, cn), cC), cs); // static final String privateKeyFCM = Env.privateKeyFCM; static final String payMobOutUserName = X.r(X.r(X.r(Env.payMobOutUserName, cn), cC), cs); /////////// static final String keyOfApp = X.r(X.r(X.r(Env.keyOfApp, cn), cC), cs); } class KN { static const String pmobsec = 'PAYMOBOUTCLIENTSECRET'; static const String pmobid = 'PAYMOBOUTCLIENT_ID'; } ================================================== FILE PATH: ./lib/constant/table_names.dart ================================================== class TableName { static const String placesFavorite = "placesFavorite"; static const String recentLocations = "recentLocations"; static const String carLocations = "carLocations"; static const String driverOrdersRefuse = "driverOrdersRefuse"; static const String rideLocation = "rideLocation"; static const String faceDetectTimes = "faceDetectTimes"; static const String behavior = "behavior"; static const String captainNotification = "captainNotification"; static const String applyRideFromOverLay = "applyRideFromOverLay"; } class Driver { static const String driverPass = 'MG6DEJZSczBT6Rx0jOlehQ=='; static const String payMobApikey = 'payMobApikey'; static const String initializationVector = 'initializationVector'; static const String keyOfApp = 'keyOfApp'; static const String FCM_PRIVATE_KEY = 'FCM_PRIVATE_KEY'; } ================================================== FILE PATH: ./lib/constant/country_polygons.dart ================================================== // في ملف: constant/country_polygons.dart import 'package:google_maps_flutter/google_maps_flutter.dart'; class CountryPolygons { // ========================================================== // 1. الأردن: تغطية الممر الحضري الرئيسي (من إربد شمالاً حتى العقبة جنوباً) // حوالي 12 نقطة // ========================================================== static final List jordanBoundary = [ // شمال إربد (قرب الحدود) const LatLng(32.65, 35.80), // شمال شرق المفرق const LatLng(32.35, 37.00), // شرق الزرقاء / الأزرق const LatLng(31.85, 36.80), // جنوب شرق (نهاية الزحف السكاني) const LatLng(31.00, 36.50), // جنوب / معان const LatLng(30.30, 35.75), // العقبة const LatLng(29.50, 35.00), // البحر الأحمر / الحدود الغربية const LatLng(29.50, 34.85), // غرب وادي عربة const LatLng(30.80, 35.25), // منطقة البحر الميت / السلط const LatLng(32.00, 35.50), // العودة عبر وادي الأردن إلى الشمال const LatLng(32.45, 35.60), // العودة لنقطة إربد const LatLng(32.65, 35.80), ]; // ========================================================== // 2. سوريا: تغطية الممر الغربي والساحلي (درعا، دمشق، حمص، حماة، حلب، الساحل) // حوالي 14 نقطة // ========================================================== static final List syriaBoundary = [ // درعا / الجنوب const LatLng(32.65, 35.95), // شرق السويداء (حدود المنطقة المأهولة) const LatLng(32.85, 37.10), // أطراف دمشق الشرقية const LatLng(33.50, 36.65), // تدمر (أقصى امتداد شرقي للمضلع) const LatLng(34.50, 38.30), // الرقة (شمال شرق) const LatLng(35.95, 38.80), // حلب (الشمال) const LatLng(36.45, 37.15), // الحدود الشمالية الغربية (إدلب / تركيا) const LatLng(36.50, 36.50), // اللاذقية (الساحل) const LatLng(35.50, 35.75), // طرطوس (الساحل) const LatLng(34.80, 35.85), // حمص const LatLng(34.70, 36.70), // حماة const LatLng(35.10, 36.70), // العودة إلى منطقة دمشق const LatLng(33.40, 36.30), // العودة إلى درعا const LatLng(32.65, 35.95), ]; // ========================================================== // 3. مصر: تغطية القاهرة الكبرى، الدلتا، والإسكندرية والإسماعيلية // حوالي 10 نقاط // ========================================================== static final List egyptBoundary = [ // جنوب الفيوم (أقصى امتداد جنوبي غربي) const LatLng(29.20, 30.60), // جنوب القاهرة (العياط) const LatLng(29.80, 31.30), // شرق السويس const LatLng(29.95, 32.70), // الإسماعيلية / القناة const LatLng(30.60, 32.25), // بورسعيد / أطراف الدلتا الشمالية الشرقية const LatLng(31.30, 31.80), // دمياط / ساحل الدلتا const LatLng(31.50, 31.25), // الإسكندرية (أقصى الشمال الغربي) const LatLng(31.20, 29.80), // غرب الدلتا const LatLng(30.50, 30.20), // العودة لنقطة البداية const LatLng(29.20, 30.60), ]; // دالة تُرجع رابط API بناءً على اسم الدولة static String getRoutingApiUrl(String countryName) { switch (countryName) { case 'Jordan': return 'https://routec.intaleq.xyz/route-jo'; case 'Syria': return 'https://routec.intaleq.xyz/route'; case 'Egypt': return 'https://routec.intaleq.xyz/route-eg'; default: // الافتراضي في حالة لم يقع الموقع ضمن أي من المضلعات return 'https://routec.intaleq.xyz/route'; } } } ================================================== FILE PATH: ./lib/constant/style.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'colors.dart'; class AppStyle { static TextStyle headTitle = TextStyle( fontWeight: FontWeight.bold, fontSize: 36, color: AppColor.accentColor, fontFamily: box.read(BoxName.lang) == 'ar' // ?GoogleFonts.markaziText().fontFamily ? GoogleFonts.markaziText().fontFamily : GoogleFonts.inter().fontFamily); static TextStyle headTitle2 = TextStyle( fontWeight: FontWeight.bold, fontSize: 24, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.markaziText().fontFamily : GoogleFonts.inter().fontFamily); static TextStyle title = TextStyle( fontWeight: FontWeight.normal, fontSize: 16, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.markaziText().fontFamily : GoogleFonts.inter().fontFamily); static TextStyle subtitle = TextStyle( fontWeight: FontWeight.bold, fontSize: 12, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.markaziText().fontFamily : GoogleFonts.inter().fontFamily); static TextStyle number = const TextStyle( fontWeight: FontWeight.bold, fontSize: 14, color: AppColor.writeColor, fontFamily: 'digit'); static BoxDecoration boxDecoration = const BoxDecoration( boxShadow: [ BoxShadow( color: AppColor.accentColor, blurRadius: 5, offset: Offset(2, 4)), BoxShadow( color: AppColor.accentColor, blurRadius: 5, offset: Offset(-2, -2)) ], color: AppColor.secondaryColor, borderRadius: BorderRadius.all( Radius.elliptical(15, 30), )); static BoxDecoration boxDecoration1 = const BoxDecoration( boxShadow: [ BoxShadow( color: Color.fromARGB(255, 237, 230, 230), blurRadius: 5, offset: Offset(2, 4)), BoxShadow( color: Color.fromARGB(255, 242, 237, 237), blurRadius: 5, offset: Offset(-2, -2)) ], color: AppColor.secondaryColor, borderRadius: BorderRadius.all( Radius.elliptical(15, 30), ), ); } ================================================== FILE PATH: ./lib/views/home/on_boarding_page.dart ================================================== import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/auth/onboarding_controller.dart'; import 'package:sefer_driver/onbording_page.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class OnBoardingPage extends StatelessWidget { OnBoardingControllerImp onBoardingControllerImp = Get.put(OnBoardingControllerImp()); OnBoardingPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.secondaryColor, body: SafeArea( child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( height: Get.height * .7, child: const CustomSliderOnBoarding(), ), const CustomDotControllerOnBoarding(), // const Spacer(flex: 2), const SizedBox(height: 20), MyElevatedButton( onPressed: () => onBoardingControllerImp.next(), title: 'Next'.tr, ) ]), )); } } ================================================== FILE PATH: ./lib/views/home/Captin/maintain_center_page.dart ================================================== import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/captin/help/maintain_center_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; // class MaintainCenterPage extends StatelessWidget { // MaintainCenterPage({super.key}); // MaintainCenterController maintainCenterController = // Get.put(MaintainCenterController()); // @override // Widget build(BuildContext context) { // return MyScafolld( // title: "Maintenance Center".tr, // body: [ // GetBuilder( // builder: (maintainCenterController) { // return Padding( // padding: const EdgeInsets.all(8.0), // child: Column( // children: [ // Text( // "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car." // .tr), // const SizedBox( // height: 10, // ), // Row( // mainAxisAlignment: MainAxisAlignment.spaceAround, // children: [ // MyElevatedButton( // title: "Show My Trip Count".tr, // onPressed: () async { // maintainCenterController.getTripCountByCaptain(); // }), // _buildPriceAvatar( // maintainCenterController.tripCount['count'] == null // ? '0' // : maintainCenterController.tripCount['count'] // .toString()) // ], // ), // const SizedBox( // height: 10, // ), // Container( // decoration: AppStyle.boxDecoration, // child: Padding( // padding: const EdgeInsets.all(14), // child: Text( // "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family." // .tr, // style: AppStyle.title, // ), // ), // ), // const SizedBox( // height: 10, // ), // MyElevatedButton( // title: 'Show maintenance center near my location'.tr, // onPressed: () { // if (maintainCenterController.tripCount['count'] > 600) { // } else { // Get.snackbar("You should complete 600 trips".tr, '', // backgroundColor: AppColor.yellowColor); // } // }) // ], // ), // ); // }) // ], // isleading: true); // } // Widget _buildPriceAvatar(String count) { // return Container( // width: 80, // height: 80, // decoration: BoxDecoration( // shape: BoxShape.circle, // gradient: const RadialGradient( // colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)], // center: Alignment.center, // radius: 0.8, // ), // boxShadow: [ // BoxShadow( // color: Colors.black.withOpacity(0.2), // blurRadius: 8, // offset: const Offset(0, 4), // ), // ], // ), // child: Center( // child: Text( // count, // style: const TextStyle( // fontSize: 22, // fontWeight: FontWeight.bold, // color: Colors.white, // ), // ), // ), // ); // } // } class MaintainCenterPage extends StatelessWidget { MaintainCenterPage({super.key}); final MaintainCenterController maintainCenterController = Get.put(MaintainCenterController()); @override Widget build(BuildContext context) { return MyScafolld( title: "Maintenance Center".tr, body: [ GetBuilder( builder: (controller) { return Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Introduction Text with better styling Text( "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car." .tr, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: Colors.grey[700], height: 1.4, ), ), const SizedBox(height: 20), // Trip Count Section in a Card Card( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: MyElevatedButton( title: "Show My Trip Count".tr, onPressed: () async { controller.getTripCountByCaptain(); }, ), ), const SizedBox(width: 16), _buildPriceAvatar( controller.tripCount['count'] == null ? '0' : controller.tripCount['count'].toString(), ), ], ), ), ), const SizedBox(height: 20), // Maintenance Offer Information in a Card Card( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Maintenance Offer".tr, style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family." .tr, style: Theme.of(context) .textTheme .bodyMedium! .copyWith( color: Colors.grey[800], height: 1.5, ), ), ], ), ), ), const SizedBox(height: 20), // Show Maintenance Center Button SizedBox( width: double.infinity, child: MyElevatedButton( title: 'Show maintenance center near my location'.tr, onPressed: () { if (controller.tripCount['count'] != null && controller.tripCount['count'] >= 600) { // Implement navigation or action to show maintenance centers // For now, let's print a message print("Navigating to maintenance centers..."); } else { Get.snackbar( "Ineligible for Offer".tr, "You should complete 500 trips to unlock this feature." .tr, backgroundColor: AppColor.yellowColor, colorText: Colors.black, snackPosition: SnackPosition.BOTTOM, ); } }, ), ), ], ), ); }, ), ], isleading: true, ); } Widget _buildPriceAvatar(String count) { return Container( width: 70, // Slightly reduced size height: 70, decoration: BoxDecoration( shape: BoxShape.circle, gradient: const LinearGradient( // Changed to LinearGradient colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), // Reduced opacity blurRadius: 6, // Slightly reduced blur offset: const Offset(0, 3), ), ], ), child: Center( child: Text( count, style: const TextStyle( fontSize: 20, // Slightly reduced size fontWeight: FontWeight.bold, color: Colors.white, ), ), ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/text_scanner.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/functions/ocr_controller.dart'; class TextRecognizerAPI extends StatelessWidget { const TextRecognizerAPI({super.key}); @override Widget build(BuildContext context) { Get.put(ScanDocumentsByApi()); return GetBuilder( builder: (controller) => Scaffold( appBar: AppBar( title: Text('Api'), actions: [ IconButton( onPressed: () { controller.matchFaceApi(); }, icon: const Icon(Icons.face), ), ], ), body: Center( child: controller.isLoading ? const MyCircularProgressIndicator() : SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Image.memory( controller.imagePortrait, width: 60, ), Image.memory( controller.imageSignature, width: 60, ), Image.memory( controller.imageDocumentFrontSide, width: 250, ), ], ), Text(controller.responseMap['authenticity_meta'] .toString()), Text( 'countryName: ${controller.responseMap['data']['countryName'].toString()}'), Text( 'Expiry Date: ${controller.responseMap['data']['ocr']['dateOfExpiry'].toString()}'), // Add more Text widgets to display other record values Text( 'Address: ${controller.responseMap['data']['ocr']['address'].toString()}'), Text( 'City: ${controller.responseMap['data']['ocr']['addressCity'].toString()}'), Text( 'Jurisdiction Code: ${controller.responseMap['data']['ocr']['addressJurisdictionCode'].toString()}'), Text( 'Postal Code: ${controller.responseMap['data']['ocr']['addressPostalCode'].toString()}'), Text( 'Street: ${controller.responseMap['data']['ocr']['addressStreet'].toString()}'), Text( 'Date of Birth: ${controller.responseMap['data']['ocr']['dateOfBirth'].toString()}'), Text( 'Date of Issue: ${controller.responseMap['data']['ocr']['dateOfIssue'].toString()}'), Text( 'Drivers License Class: ${controller.responseMap['data']['ocr']['dlClass'].toString()}'), Text( 'Document Number: ${controller.responseMap['data']['ocr']['documentNumber'].toString()}'), Text( 'Eye Color: ${controller.responseMap['data']['ocr']['eyesColor'].toString()}'), Text( 'Given Names: ${controller.responseMap['data']['ocr']['givenNames'].toString()}'), Text( 'Height: ${controller.responseMap['data']['ocr']['height'].toString()}'), Text( 'Issuing State Code: ${controller.responseMap['data']['ocr']['issuingStateCode'].toString()}'), Text( 'Name: ${controller.responseMap['data']['ocr']['name'].toString()}'), Text( 'Sex: ${controller.responseMap['data']['ocr']['sex'].toString()}'), Text( 'Surname: ${controller.responseMap['data']['ocr']['surname'].toString()}'), Text( 'Valid State: ${controller.responseMap['data']['ocr']['validState'].toString()}'), ], ), )))); } } // class TextExtractionView extends StatelessWidget { // TextExtractionView({super.key}); // // @override // Widget build(BuildContext context) { // Get.put(TextExtractionController()); // return Scaffold( // appBar: AppBar( // title: const Text('Text Extraction'), // ), // body: GetBuilder(builder: (controller) { // return Center( // child: Column( // mainAxisAlignment: MainAxisAlignment.center, // children: [ // ElevatedButton( // onPressed: () {}, // child: const Text('Pick Image and Extract Text'), // ), // const SizedBox(height: 20), // controller.isloading // ? const MyCircularProgressIndicator() // : Text(controller.extractedText), // ], // ), // ); // }), // ); // } // } // class TextRecognizerWidget extends StatelessWidget { // const TextRecognizerWidget({super.key}); // // @override // Widget build(BuildContext context) { // Get.put(TextMLGoogleRecognizerController()); // return GetBuilder( // builder: (controller) => Scaffold( // appBar: AppBar(), // body: Center( // child: Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // Text('${controller.decode['DRIVER_LICENSE'].toString()}'), // Text('DL: ${controller.decode['dl_number'].toString()}'), // Text( // 'Expiry Date: ${controller.decode['expiry_date'].toString()}'), // Text('Last Name: ${controller.decode['lastName'].toString()}'), // Text( // 'First Name: ${controller.decode['firstName'].toString()}'), // Text('Address: ${controller.decode['address'].toString()}'), // Text('Date of Birth: ${controller.decode['dob'].toString()}'), // Text('RSTR: ${controller.decode['rstr'].toString()}'), // Text('Class: ${controller.decode['class'].toString()}'), // Text('End: ${controller.decode['end'].toString()}'), // Text('DD: ${controller.decode['dd'].toString()}'), // Text('Sex: ${controller.decode['sex'].toString()}'), // Text('Hair: ${controller.decode['hair'].toString()}'), // Text('Eyes: ${controller.decode['eyes'].toString()}'), // // and so on for other fields // ], // )))); // } // } // class PassportPage extends StatelessWidget { // PassportPage({super.key}); // PassportRecognizerController passportRecognizerController = // Get.put(PassportRecognizerController()); // @override // Widget build(BuildContext context) { // return Scaffold( // appBar: AppBar( // title: const Text('Driver License'), // ), // body: const Center(child: Text('data'))); // } // } ================================================== FILE PATH: ./lib/views/home/Captin/passportimage.dart ================================================== // import 'dart:io'; // // import 'package:flutter/material.dart'; // import 'package:get/get.dart'; // import '../../../controller/functions/ocr_controller.dart'; // // class PassportDataExtractorWidget extends StatelessWidget { // final PassportDataExtractor passportDataExtractor = // Get.put(PassportDataExtractor()); // final PassportDataController controller = Get.put(PassportDataController()); // // @override // Widget build(BuildContext context) { // return Scaffold( // appBar: AppBar( // title: const Text('Passport Data Extractor'), // ), // body: Column( // children: [ // ElevatedButton( // onPressed: controller.extractDataAndDrawBoundingBoxes, // child: const Text('Extract Data'), // ), // Expanded( // child: Center( // child: Stack( // children: [ // GetBuilder( // builder: (controller) => CustomPaint( // painter: BoundingBoxPainter( // controller.extractedTextWithCoordinates), // child: GetBuilder( // builder: (controller) => // Image.file(File(passportDataExtractor.image!.path)), // ), // ), // ), // ], // ), // ), // ), // ], // ), // ); // } // } ================================================== FILE PATH: ./lib/views/home/Captin/bottom_bar.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; class BottomBarController extends GetxController { var currentIndex = 0.obs; void changePage(int index) { currentIndex.value = index; } } class HomeScreen extends StatelessWidget { final BottomBarController controller = Get.put(BottomBarController()); HomeScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Bottom Bar Example'.tr), ), body: Obx(() => IndexedStack( index: controller.currentIndex.value, children: const [ HomeView(), ProfileView(), StatisticsView(), WalletView(), ], )), bottomNavigationBar: Obx(() => BottomNavigationBar( backgroundColor: Colors.greenAccent, currentIndex: controller.currentIndex.value, onTap: controller.changePage, items: [ BottomNavigationBarItem( icon: const Icon( Icons.home, color: AppColor.primaryColor, ), label: 'Home'.tr, ), BottomNavigationBarItem( icon: const Icon( Icons.person, color: AppColor.primaryColor, ), label: 'Profile'.tr, ), BottomNavigationBarItem( icon: const Icon( Icons.bar_chart, color: AppColor.primaryColor, ), label: 'Statistics'.tr, ), BottomNavigationBarItem( icon: const Icon( Icons.account_balance_wallet, color: AppColor.primaryColor, ), label: 'Wallet'.tr, ), ], )), ); } } class HomeView extends StatelessWidget { const HomeView({super.key}); @override Widget build(BuildContext context) { Map data; return const Center( child: Column( children: [ Text('Home View'), ], ), ); } } class ProfileView extends StatelessWidget { const ProfileView({super.key}); @override Widget build(BuildContext context) { return const Center( child: Text('Profile View'), ); } } class StatisticsView extends StatelessWidget { const StatisticsView({super.key}); @override Widget build(BuildContext context) { return const Center( child: Text('Statistics View'), ); } } class WalletView extends StatelessWidget { const WalletView({super.key}); @override Widget build(BuildContext context) { return const Center( child: Text('Wallet View'), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/assurance_health_page.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../constant/colors.dart'; import '../../../controller/home/captin/help/assurance_controller.dart'; import 'package:flutter/cupertino.dart'; class AssuranceHealthPage extends StatelessWidget { AssuranceHealthPage({super.key}); AssuranceHealthController assuranceHealthController = Get.put(AssuranceHealthController()); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text("Health Insurance".tr), ), child: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: GetBuilder( builder: (assuranceHealthController) { return Column( children: [ Text( "When you complete 500 trips, you will be eligible for exclusive health insurance offers." .tr, textAlign: TextAlign.center, style: CupertinoTheme.of(context).textTheme.navTitleTextStyle, ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ CupertinoButton.filled( child: Text("Show My Trip Count".tr), onPressed: () async { assuranceHealthController.getTripCountByCaptain(); }, ), _buildTripCountAvatar( assuranceHealthController.tripCount['count'] == null ? '0' : assuranceHealthController.tripCount['count'] .toString(), ), ], ), const SizedBox(height: 10), Container( decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(10), ), child: Padding( padding: const EdgeInsets.all(14), child: Text( "We have partnered with health insurance providers to offer you special health coverage. Complete 500 trips and receive a 20% discount on health insurance premiums." .tr, style: CupertinoTheme.of(context) .textTheme .textStyle .copyWith(fontWeight: FontWeight.w600), textAlign: TextAlign.center, ), ), ), const SizedBox(height: 10), CupertinoButton.filled( disabledColor: AppColor.blueColor, padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15), borderRadius: BorderRadius.circular(12), child: Text( "Would you like to proceed with health insurance?".tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold), ), onPressed: () async { // Show confirmation dialog before proceeding showCupertinoDialog( context: context, builder: (BuildContext context) { // Variable to store the health insurance provider chosen by the driver TextEditingController providerController = TextEditingController(); return CupertinoAlertDialog( title: Text( "Confirmation".tr, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 18), ), content: Column( children: [ Text( "Would you like to proceed with health insurance?" .tr, style: const TextStyle(fontSize: 14), ), const SizedBox(height: 20), CupertinoTextField( controller: providerController, placeholder: "Do you have a disease for a long time?".tr, padding: const EdgeInsets.all(12), decoration: BoxDecoration( border: Border.all( color: CupertinoColors.systemGrey, width: 1), borderRadius: BorderRadius.circular(8), ), ), ], ), actions: [ CupertinoDialogAction( isDefaultAction: true, child: Text( "Yes".tr, style: const TextStyle( color: CupertinoColors.activeBlue), ), onPressed: () async { // Ensure the provider name is not empty if (providerController.text.isNotEmpty) { // Call the function to insert data into the database await assuranceHealthController .addDriverHealthAssurance( healthInsuranceProvider: providerController.text, ); // Close the dialog and navigate to a success screen or show a snackbar Navigator.of(context).pop(); } else { // Show an alert if the provider name is empty showCupertinoDialog( context: context, builder: (_) => CupertinoAlertDialog( title: Text("Error".tr), content: Text( "Do you have a disease for a long time?" .tr), actions: [ CupertinoDialogAction( child: Text("OK".tr), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } }, ), CupertinoDialogAction( child: Text( "No".tr, style: const TextStyle( color: CupertinoColors.destructiveRed), ), onPressed: () { Navigator.of(context) .pop(); // Just close the dialog // Optionally show feedback if the driver opts out // Get.snackbar( // "Opted out".tr, // "You have chosen not to proceed with health insurance." // .tr, // backgroundColor: // CupertinoColors.systemGrey); mySnackeBarError( "You have chosen not to proceed with health insurance." .tr); }, ), ], ); }, ); }, ), ], ); }), ), ), ); } Widget _buildTripCountAvatar(String count) { return Container( width: 80, height: 80, decoration: BoxDecoration( shape: BoxShape.circle, gradient: const RadialGradient( colors: [ Color(0xFF42A5F5), Color(0xFF1976D2), ], // Health theme colors center: Alignment.center, radius: 0.8, ), boxShadow: [ BoxShadow( color: CupertinoColors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Center( child: Text( count, style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: CupertinoColors.white, ), ), ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/driver_map_page.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart'; import '../../../constant/colors.dart'; import '../../../controller/functions/location_controller.dart'; import '../../../main.dart'; import '../../Rate/rate_passenger.dart'; import '../../widgets/my_textField.dart'; import 'mapDriverWidgets/driver_end_ride_bar.dart'; import 'mapDriverWidgets/google_driver_map_page.dart'; import 'mapDriverWidgets/google_map_app.dart'; import 'mapDriverWidgets/passenger_info_window.dart'; import 'mapDriverWidgets/sos_connect.dart'; class PassengerLocationMapPage extends StatelessWidget { PassengerLocationMapPage({super.key}); final LocationController locationController = Get.put(LocationController()); final MapDriverController mapDriverController = Get.put(MapDriverController()); // Helper function to show exit confirmation dialog Future showExitDialog() async { bool? result = await Get.defaultDialog( title: "Warning".tr, titleStyle: AppStyle.title.copyWith(color: AppColor.redColor), middleText: "You are in an active ride. Leaving this screen might stop tracking. Are you sure you want to exit?" .tr, middleTextStyle: AppStyle.title, barrierDismissible: false, confirm: MyElevatedButton( title: 'Stay'.tr, kolor: AppColor.greenColor, onPressed: () => Get.back(result: false), // Return false (Don't pop) ), cancel: MyElevatedButton( title: 'Exit'.tr, kolor: AppColor.redColor, onPressed: () => Get.back(result: true), // Return true (Allow pop) ), ); return result ?? false; } @override Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { if (Get.arguments != null && Get.arguments is Map) { mapDriverController.argumentLoading(); mapDriverController.startTimerToShowPassengerInfoWindowFromDriver(); } }); // ✅ Added PopScope to intercept back button return PopScope( canPop: false, // Prevents immediate popping onPopInvokedWithResult: (didPop, result) async { if (didPop) { return; } // Show dialog final shouldExit = await showExitDialog(); if (shouldExit) { Get.back(); // Manually pop if confirmed } }, child: Scaffold( body: SafeArea( child: Stack( children: [ // 1. Map GoogleDriverMap(locationController: locationController), // 2. Instructions const InstructionsOfRoads(), // 3. Passenger Info Positioned( top: 0, left: 0, right: 0, child: PassengerInfoWindow(), ), // 4. Cancel Widget CancelWidget(mapDriverController: mapDriverController), // 5. End Ride Bar driverEndRideBar(), // 6. SOS SosConnect(), // 7. Speed speedCircle(), // 8. External Map Positioned( bottom: 100, right: 10, child: GoogleMapApp(), ), // 9. Prices Window const PricesWindow(), ], ), )), ); } } // ... The rest of your widgets (InstructionsOfRoads, CancelWidget, etc.) remain unchanged ... // ... Keep the code below exactly as you had it in the previous snippet ... class InstructionsOfRoads extends StatelessWidget { const InstructionsOfRoads({super.key}); @override Widget build(BuildContext context) { return Positioned( bottom: 10, left: MediaQuery.of(context).size.width * 0.15, right: MediaQuery.of(context).size.width * 0.15, child: GetBuilder( builder: (controller) => controller.currentInstruction.isNotEmpty ? AnimatedContainer( duration: const Duration(milliseconds: 300), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.directions, color: AppColor.primaryColor), const SizedBox(width: 10), Expanded( child: Text( controller.currentInstruction, style: AppStyle.title.copyWith(fontSize: 16), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 10), InkWell( onTap: () { controller.toggleTts(); }, child: Icon( controller.isTtsEnabled ? Icons.volume_up : Icons.volume_off, color: controller.isTtsEnabled ? AppColor.greenColor : Colors.grey, ), ), ], ), ) : const SizedBox(), ), ); } } class CancelWidget extends StatelessWidget { const CancelWidget({ super.key, required this.mapDriverController, }); final MapDriverController mapDriverController; @override Widget build(BuildContext context) { return Positioned( top: 70, left: 10, child: GetBuilder( builder: (controller) { if (controller.isRideFinished) return const SizedBox.shrink(); return GestureDetector( onTap: () { Get.defaultDialog( title: "Are you sure you want to cancel this trip?".tr, titleStyle: AppStyle.title, content: Column( children: [ Text("Why do you want to cancel this trip?".tr), Form( key: mapDriverController.formKeyCancel, child: MyTextForm( controller: mapDriverController.cancelTripCotroller, label: "Write the reason for canceling the trip".tr, hint: "Write the reason for canceling the trip".tr, type: TextInputType.name, )) ], ), confirm: MyElevatedButton( title: 'Ok'.tr, kolor: AppColor.redColor, onPressed: () async { await mapDriverController .cancelTripFromDriverAfterApplied(); Get.back(); }), cancel: MyElevatedButton( title: 'No'.tr, onPressed: () { Get.back(); })); }, child: Container( decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 5, ), ], ), child: const Padding( padding: EdgeInsets.all(8.0), child: Icon( Icons.clear, size: 30, color: AppColor.redColor, ), ), ), ); }, ), ); } } class PricesWindow extends StatelessWidget { const PricesWindow({ super.key, }); @override Widget build(BuildContext context) { return GetBuilder(builder: (mapDriverController) { return mapDriverController.isPriceWindow ? Container( color: Colors.black.withOpacity(0.5), child: Center( child: Container( width: Get.width * 0.8, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'Total Price is '.tr, style: AppStyle.headTitle2, textAlign: TextAlign.center, ), const SizedBox(height: 10), Text( '${mapDriverController.totalPricePassenger} ${'\$'.tr}', style: AppStyle.headTitle2.copyWith( color: AppColor.primaryColor, fontSize: 36), ), const SizedBox( height: 20, ), MyElevatedButton( title: 'ok'.tr, onPressed: () => Get.to(() => RatePassenger(), arguments: { 'rideId': mapDriverController.rideId, 'passengerId': mapDriverController.passengerId, 'driverId': mapDriverController.driverId })) ], ), ), ), ) : const SizedBox(); }); } } ================================================== FILE PATH: ./lib/views/home/Captin/camer_widget.dart ================================================== import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/camer_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; class CameraWidgetCardId extends StatelessWidget { final CameraClassController cameraClassController = Get.put(CameraClassController()); CameraWidgetCardId({super.key}); @override Widget build(BuildContext context) { return MyScafolld( title: 'Scan Id'.tr, body: [ Column( children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: GetBuilder( builder: (cameraClassController) => cameraClassController.isCameraInitialized ? Stack( children: [ Container( decoration: AppStyle.boxDecoration, child: FittedBox( fit: BoxFit.fitWidth, child: SizedBox( width: Get.width * .9, height: Get.width * .9, // Set the desired aspect ratio here child: CameraPreview( cameraClassController.cameraController, ), ), ), ), Positioned( top: 72, child: Container( width: 230, height: 25, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.yellowColor, width: 2), ), ), ), Positioned( top: 60, right: 5, child: Container( width: 230, height: 25, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 156, right: 5, child: Container( width: 140, height: 20, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 175, right: 5, child: Container( width: 140, height: 15, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 191, right: 5, child: Container( width: 140, height: 15, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 207, right: 5, child: Container( width: 140, height: 15, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 225, right: 5, child: Container( width: 140, height: 15, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 115, left: 25, child: Container( width: 120, height: 110, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), ], ) : Container( decoration: AppStyle.boxDecoration, height: Get.width * 3 / 4, width: Get.width, child: Center( child: Text( 'Camera not initilaized yet'.tr, style: AppStyle.title, ), ), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Scan ID MklGoogle'.tr, onPressed: () {}), // cameraClassController.takePictureAndMLGoogleScan()), MyElevatedButton( title: 'Scan ID Tesseract'.tr, onPressed: () {}), ], ), MyElevatedButton( title: 'Scan ID Api'.tr, onPressed: () => cameraClassController.extractCardId()), GetBuilder( builder: (cameraClassController) => Expanded( child: Text(cameraClassController.scannedText.toString()))) ], ) ], isleading: true); } } class CameraWidgetPassPort extends StatelessWidget { final CameraClassController cameraClassController = Get.put(CameraClassController()); CameraWidgetPassPort({super.key}); @override Widget build(BuildContext context) { return MyScafolld( title: 'Scan Id'.tr, body: [ Column( children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: GetBuilder( builder: (cameraClassController) => cameraClassController.isCameraInitialized ? Stack( children: [ Container( decoration: AppStyle.boxDecoration, child: FittedBox( fit: BoxFit.fitWidth, child: SizedBox( width: Get.width * .9, height: Get.width * .9, // Set the desired aspect ratio here child: CameraPreview( cameraClassController.cameraController, ), ), ), ), Positioned( top: 35, left: 35, width: Get.width * .77, height: 17, //left":95.0,"top":134.0,"width":2909.0,"height":175.0 child: Container( // width: 230, // height: 25, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.yellowColor, width: 2), ), ), ), Positioned( top: 60, right: 25, width: 90, height: 25, child: Container( decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), Positioned( top: 110, right: 90, child: Container( width: 140, height: 20, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.blueColor, width: 2), ), ), ), ], ) : Container( decoration: AppStyle.boxDecoration, height: Get.width * 3 / 4, width: Get.width, child: Center( child: Text( 'Camera not initilaized yet', style: AppStyle.title, ), ), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Scan ID MklGoogle'.tr, onPressed: () => {}), // cameraClassController.takePictureAndMLGoogleScan()), MyElevatedButton( title: 'Scan ID Tesseract'.tr, onPressed: () {}), ], ), MyElevatedButton( title: 'Scan ID Api'.tr, onPressed: () => cameraClassController.extractCardId()), GetBuilder( builder: (cameraClassController) => Expanded( child: Text(cameraClassController.scannedText.toString()))) ], ) ], isleading: true); } } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/order_speed_request.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/firebase/firbase_messge.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/print.dart'; import 'package:sefer_driver/views/home/Captin/driver_map_page.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/links.dart'; import '../../../../constant/style.dart'; import '../../../../controller/firebase/notification_service.dart'; import '../../../../controller/functions/crud.dart'; import '../../../../controller/functions/launch.dart'; import '../../../../controller/home/captin/order_request_controller.dart'; import '../../../widgets/elevated_btn.dart'; import '../../../widgets/mydialoug.dart'; class OrderSpeedRequest extends StatelessWidget { OrderSpeedRequest({super.key}); final OrderRequestController orderRequestController = Get.put(OrderRequestController()); // دالة مساعدة لاستخراج البيانات بأمان (Null Safety) String _getData(int index, {String defaultValue = ''}) { if (orderRequestController.myList.length > index && orderRequestController.myList[index] != null) { return orderRequestController.myList[index].toString(); } return defaultValue; } @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) { // --- استخراج البيانات بشكل نظيف --- final String price = double.tryParse(_getData(2))?.toStringAsFixed(2) ?? 'N/A'; final bool isComfortTrip = _getData(31) == 'Comfort'; final String carType = _getData(31).tr; final String pickupName = _getData(12); final String pickupDetails = '(${_getData(11)})'; final String pickupFullAddress = _getData(29); final String dropoffName = _getData(5); final String dropoffDetails = '(${_getData(4)})'; final String dropoffFullAddress = _getData(30); final String passengerName = _getData(8); final String passengerRating = _getData(33); final bool isVisaPayment = _getData(13) == 'true'; final bool hasSteps = _getData(20) == 'haveSteps'; final String mapUrl = 'https://www.google.com/maps/dir/${_getData(0)}/${_getData(1)}/'; final String rideId = _getData(16); return Scaffold( appBar: AppBar( title: Text('Speed Order'.tr), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Get.back(), ), backgroundColor: AppColor.primaryColor, elevation: 2.0, ), backgroundColor: AppColor.secondaryColor ?? Colors.grey[100], body: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), child: Column( children: [ // 1. قسم الخريطة (ارتفاع ثابت) SizedBox( height: Get.height * 0.28, child: ClipRRect( borderRadius: BorderRadius.circular(15.0), child: GoogleMap( initialCameraPosition: CameraPosition( zoom: 12, target: Get.find().myLocation, ), cameraTargetBounds: CameraTargetBounds(controller.bounds), myLocationButtonEnabled: false, trafficEnabled: false, buildingsEnabled: false, mapToolbarEnabled: false, myLocationEnabled: true, markers: { Marker( markerId: MarkerId('MyLocation'.tr), position: LatLng(controller.latPassengerLocation, controller.lngPassengerLocation), icon: controller.startIcon), Marker( markerId: MarkerId('Destination'.tr), position: LatLng( controller.latPassengerDestination, controller.lngPassengerDestination), icon: controller.endIcon), }, polylines: { Polyline( zIndex: 1, consumeTapEvents: true, geodesic: true, endCap: Cap.buttCap, startCap: Cap.buttCap, visible: true, polylineId: const PolylineId('routeOrder'), points: controller.pointsDirection, color: AppColor.primaryColor, width: 3, ), }, ), ), ), const SizedBox(height: 8), // 2. بطاقة السعر _buildPriceCard(price, carType, isComfortTrip), const SizedBox(height: 8), // 3. التفاصيل القابلة للتمرير (تأخذ المساحة المتبقية) Expanded( child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildLocationCard( icon: Icons.arrow_circle_up, iconColor: AppColor.greenColor, title: pickupName, subtitle: pickupDetails, fullAddress: pickupFullAddress, ), const SizedBox(height: 8), _buildLocationCard( icon: Icons.arrow_circle_down, iconColor: AppColor.redColor, title: dropoffName, subtitle: dropoffDetails, fullAddress: dropoffFullAddress, ), const SizedBox(height: 8), _buildInfoCard(isVisaPayment, hasSteps, mapUrl), const SizedBox(height: 8), _buildPassengerCard(passengerName, passengerRating), ], ), ), ), // 4. الأزرار والمؤقت (مثبتة في الأسفل) Padding( padding: const EdgeInsets.only(top: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // زر القبول Expanded( child: MyElevatedButton( kolor: AppColor.greenColor, title: 'Accept Order'.tr, onPressed: () => _handleAcceptOrder(controller), ), ), const SizedBox(width: 10), // المؤقت GetBuilder( id: 'timerUpdate', builder: (timerCtrl) { final isNearEnd = timerCtrl.remainingTimeSpeed <= 5; return SizedBox( width: 60, height: 60, child: Stack( alignment: Alignment.center, children: [ CircularProgressIndicator( value: timerCtrl.progressSpeed, color: isNearEnd ? Colors.redAccent : AppColor.primaryColor, strokeWidth: 5, backgroundColor: Colors.grey.shade300, ), Text( '${timerCtrl.remainingTimeSpeed}', style: AppStyle.headTitle2.copyWith( color: isNearEnd ? Colors.redAccent : AppColor.writeColor ?? Colors.black, ), ), ], ), ); }, ), const SizedBox(width: 10), // زر الرفض Expanded( child: MyElevatedButton( title: 'Refuse Order'.tr, onPressed: () => _handleRefuseOrder(controller, rideId), kolor: AppColor.redColor, ), ), ], ), ), ], ), ), ), ); }, ); } // --- WIDGET BUILDERS (لبناء الواجهة بشكل نظيف) --- Widget _buildPriceCard(String price, String carType, bool isComfortTrip) { return Card( elevation: 3, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( price, style: AppStyle.headTitle.copyWith( color: AppColor.primaryColor, fontWeight: FontWeight.bold, fontSize: 28), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( carType, style: AppStyle.title.copyWith( color: AppColor.greenColor, fontWeight: FontWeight.bold), ), if (isComfortTrip) Row( children: [ const Icon(Icons.ac_unit, color: AppColor.blueColor, size: 18), const SizedBox(width: 4), Text('Air condition Trip'.tr, style: AppStyle.subtitle.copyWith(fontSize: 13)), ], ), ], ), ], ), ), ); } Widget _buildInfoCard(bool isVisaPayment, bool hasSteps, String mapUrl) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon( isVisaPayment ? Icons.credit_card : Icons.payments_outlined, color: isVisaPayment ? AppColor.deepPurpleAccent : AppColor.greenColor, size: 24, ), const SizedBox(width: 8), Text( isVisaPayment ? 'Visa'.tr : 'Cash'.tr, style: AppStyle.title.copyWith(fontWeight: FontWeight.w600), ), ], ), if (hasSteps) Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.format_list_numbered_rtl_outlined, color: AppColor.bronze, size: 24), const SizedBox(width: 4), Flexible( child: Text( 'Trip has Steps'.tr, style: AppStyle.title .copyWith(color: AppColor.bronze, fontSize: 13), overflow: TextOverflow.ellipsis, )), ], ), ), TextButton.icon( style: TextButton.styleFrom( padding: EdgeInsets.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, alignment: Alignment.centerRight, ), onPressed: () => showInBrowser(mapUrl), icon: const Icon(Icons.directions_outlined, color: AppColor.blueColor, size: 20), label: Text("Directions".tr, style: AppStyle.subtitle .copyWith(color: AppColor.blueColor, fontSize: 13)), ), ], ), ), ); } Widget _buildPassengerCard(String name, String rating) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), child: Row( children: [ const Icon(Icons.person_outline, color: AppColor.greyColor, size: 22), const SizedBox(width: 10), Expanded( child: Text( name, style: AppStyle.title, overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 10), const Icon(Icons.star_rounded, color: Colors.amber, size: 20), Text( rating, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold), ), ], ), ), ); } Widget _buildLocationCard( {required IconData icon, required Color iconColor, required String title, required String subtitle, required String fullAddress}) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), margin: const EdgeInsets.symmetric(vertical: 4), child: Padding( padding: const EdgeInsets.all(10.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, color: iconColor, size: 28), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "$title $subtitle".trim(), style: AppStyle.title.copyWith(fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (fullAddress.isNotEmpty) ...[ const SizedBox(height: 3), Text( fullAddress, style: AppStyle.subtitle .copyWith(fontSize: 13, color: AppColor.greyColor), maxLines: 2, overflow: TextOverflow.ellipsis, ), ] ], ), ), ], ), ), ); } // --- منطق التعامل مع الطلبات (Logic Handlers) --- Future _handleAcceptOrder(OrderRequestController controller) async { // 1. محاولة تحديث الحالة في السيرفر // 1. إظهار لودينج وإيقاف التفاعل Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); // هذا الرابط يجب أن يكون لملف PHP الآمن الذي يحتوي على rowCount var res = await CRUD().post(link: AppLink.updateStausFromSpeed, payload: { 'id': (controller.myList[16]), 'rideTimeStart': DateTime.now().toString(), 'status': 'Apply', 'driver_id': box.read(BoxName.driverID), }); Log.print('oreder response update: ${res}'); // 2. إغلاق اللودينج بمجرد وصول الرد Get.back(); // إغلاق اللودينج // 2. معالجة الفشل (Robust Error Handling) // نفحص إذا كانت النتيجة فشل سواء وصلت كنص أو كـ JSON bool isFailed = false; if (res == 'failure') isFailed = true; if (res is Map && res['status'] == 'failure') isFailed = true; if (isFailed) { MyDialog().getDialog( "This ride is already applied by another driver.".tr, '', () { Get.back(); // يغلق نافذة التنبيه (Dialog) Get.back(); // يغلق صفحة الطلب بالكامل (Screen) ويرجع للخريطة }); return; // توقف تام للكود هنا، لن يتم تنفيذ أي سطر بالأسفل } // 3. معالجة النجاح (Success Handling) // إيقاف المؤقت وتحديث الواجهة controller.endTimer(); controller.changeApplied(); // تحديث حالة السائق في التطبيق Get.put(HomeCaptainController()).changeRideId(); box.write(BoxName.statusDriverLocation, 'on'); // *هام*: تم حذف استدعاء الـ API الثاني المكرر هنا لأنه غير ضروري وقد يسبب مشاكل // تسجيل الطلب في سجل السائقين (Driver History) CRUD().postFromDialogue(link: AppLink.addDriverOrder, payload: { 'driver_id': (controller.myList[6].toString()), 'order_id': (controller.myList[16].toString()), 'status': 'Apply' }); // إرسال إشعار للراكب List bodyToPassenger = [ controller.myList[6].toString(), controller.myList[8].toString(), controller.myList[9].toString(), ]; NotificationService.sendNotification( target: controller.myList[9].toString(), title: "Accepted Ride".tr, body: 'your ride is Accepted'.tr, isTopic: false, tone: 'start', driverList: bodyToPassenger, category: 'Accepted Ride', ); // حفظ البيانات في الصندوق (Box) للانتقال للصفحة التالية box.write(BoxName.rideArguments, { 'passengerLocation': controller.myList[0].toString(), 'passengerDestination': controller.myList[1].toString(), 'Duration': controller.myList[4].toString(), 'totalCost': controller.myList[26].toString(), 'Distance': controller.myList[5].toString(), 'name': controller.myList[8].toString(), 'phone': controller.myList[10].toString(), 'email': controller.myList[28].toString(), 'WalletChecked': controller.myList[13].toString(), 'tokenPassenger': controller.myList[9].toString(), 'direction': 'https://www.google.com/maps/dir/${controller.myList[0]}/${controller.myList[1]}/', 'DurationToPassenger': controller.myList[15].toString(), 'rideId': (controller.myList[16].toString()), 'passengerId': (controller.myList[7].toString()), 'driverId': (controller.myList[18].toString()), 'durationOfRideValue': controller.myList[19].toString(), 'paymentAmount': controller.myList[2].toString(), 'paymentMethod': controller.myList[13].toString() == 'true' ? 'visa' : 'cash', 'isHaveSteps': controller.myList[20].toString(), 'step0': controller.myList[21].toString(), 'step1': controller.myList[22].toString(), 'step2': controller.myList[23].toString(), 'step3': controller.myList[24].toString(), 'step4': controller.myList[25].toString(), 'passengerWalletBurc': controller.myList[26].toString(), 'timeOfOrder': DateTime.now().toString(), 'totalPassenger': controller.myList[2].toString(), 'carType': controller.myList[31].toString(), 'kazan': controller.myList[32].toString(), 'startNameLocation': controller.myList[29].toString(), 'endNameLocation': controller.myList[30].toString(), }); // الانتقال لصفحة تتبع الراكب Get.back(); // يغلق صفحة الطلب الحالية Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Log.print( 'box.read(BoxName.rideArguments): ${box.read(BoxName.rideArguments)}'); } void _handleRefuseOrder(OrderRequestController controller, String rideId) { controller.endTimer(); // controller.refuseOrder(rideId); // تسجيل الرفض في الإشعارات المحلية للسائق controller.addRideToNotificationDriverString( rideId, _getData(29), _getData(30), '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}', '${DateTime.now().hour}:${DateTime.now().minute}', _getData(2), _getData(7), 'wait', _getData(31), _getData(33), _getData(2), _getData(5), _getData(4)); // الخروج من الصفحة بعد الرفض Get.back(); } } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/vip_order_page.dart ================================================== import 'dart:convert'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../../main.dart'; import '../../../../print.dart'; class VipOrderPage extends StatelessWidget { const VipOrderPage({super.key}); @override Widget build(BuildContext context) { Get.put(VipOrderController()); return MyScafolld( title: 'VIP Order'.tr, body: [ GetBuilder(builder: (vipOrderController) { if (vipOrderController.isLoading) { return const Center( child: CircularProgressIndicator(), ); } if (vipOrderController.tripData.isEmpty) { return Center( child: Text('No orders available'.tr), ); } final order = vipOrderController.tripData[0]; Log.print('order: ${order}'); return SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Passenger Section _buildSectionTitle('Passenger Information'.tr), _buildInfoCard( children: [ _buildDetailRow('Name'.tr, '${order['passengerName'] ?? 'Unknown'} ${order['passengerLastName'] ?? ''}'), _buildDetailRow( 'Phone'.tr, order['passengerPhone'] ?? 'Unknown'), _buildDetailRow( 'Gender'.tr, order['passengergender'] ?? 'Unknown'), _buildDetailRow('time Selected'.tr, order['timeSelected'] ?? 'Unknown'), _buildDetailRow( 'Ride Status'.tr, order['status'] ?? 'Unknown'), // _buildDetailRow('Ride Status'.tr, // vipOrderController.myList[4] ?? 'Unknown'), IconButton( onPressed: () { // print(vipOrderController.myList); }, icon: const Icon(Icons.add), ), ], ), const SizedBox(height: 24), // Action Buttons _buildActionButtons(context), ], ), ), ); }) ], isleading: true, ); } } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Text( title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ); } Widget _buildInfoCard({required List children}) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 5, offset: const Offset(0, 3), ), ], ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: children, ), ), ); } Widget _buildDetailRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 2, child: Text( label, style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), Expanded( flex: 3, child: Text( value, style: const TextStyle(color: Colors.black54), ), ), ], ), ); } Widget _buildActionButtons(BuildContext context) { return Row( children: [ Expanded( child: ElevatedButton( onPressed: () => _onReject(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.red, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( 'Reject'.tr, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(width: 16), Expanded( child: ElevatedButton( onPressed: () => _onApply(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.green, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( 'Apply'.tr, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ), ], ); } void _onReject(BuildContext context) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Ride Rejected'), backgroundColor: Colors.red, ), ); } void _onApply(BuildContext context) { // TODO: Implement application logic ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Ride Applied'), backgroundColor: Colors.green, ), ); } class VipOrderController extends GetxController { bool isLoading = false; List tripData = []; fetchOrder() async { isLoading = true; // Set loading state update(); // Notify listeners var res = await CRUD().get(link: AppLink.getMishwariDriver, payload: { 'driverId': box.read(BoxName.driverID).toString(), }); if (res != 'failure') { tripData = jsonDecode(res)['message']; } else { tripData = []; } isLoading = false; // Loading complete update(); // Notify listeners } @override void onInit() async { fetchOrder(); super.onInit(); } } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/order_request_page.dart ================================================== import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/home/Captin/driver_map_page.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/links.dart'; import '../../../../constant/style.dart'; import '../../../../controller/firebase/notification_service.dart'; import '../../../../controller/functions/crud.dart'; import '../../../../controller/home/captin/order_request_controller.dart'; import '../../../../print.dart'; import '../../../widgets/elevated_btn.dart'; class OrderRequestPage extends StatefulWidget { const OrderRequestPage({super.key}); @override State createState() => _OrderRequestPageState(); } class _OrderRequestPageState extends State { // 1. تعريف المتغير بكلمة late لتهيئة قيمته لاحقاً late OrderRequestController orderRequestController; @override void initState() { super.initState(); // 2. نقوم بحقن الكنترولر هنا داخل initState // هذا يضمن عدم حدوث كراش أثناء بناء الـ State orderRequestController = Get.put(OrderRequestController()); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Orders Page'.tr), centerTitle: true, ), body: GetBuilder( // بما أننا قمنا بحقنه في initState، سيتعرف عليه GetBuilder تلقائياً builder: (controller) { if (controller.myList == null) { return const Center(child: CircularProgressIndicator()); } return Column( children: [ SizedBox( height: Get.height * 0.3, child: GoogleMap( mapType: MapType.normal, initialCameraPosition: CameraPosition( target: LatLng(controller.latPassengerLocation, controller.lngPassengerLocation), zoom: 14.0, ), myLocationButtonEnabled: true, onMapCreated: controller.onMapCreated, myLocationEnabled: true, markers: { Marker( markerId: const MarkerId('startLocation'), position: LatLng(controller.latPassengerLocation, controller.lngPassengerLocation), icon: controller.startIcon, ), Marker( markerId: const MarkerId('destinationLocation'), position: LatLng(controller.latPassengerDestination, controller.lngPassengerDestination), icon: controller.endIcon, ), }, polylines: { Polyline( polylineId: const PolylineId('route'), color: AppColor.primaryColor, width: 5, points: controller.pointsDirection, ), }, ), ), Expanded( child: ListView( padding: const EdgeInsets.all(16), children: [ Card( elevation: 4, child: ListTile( leading: Icon( controller.myList[13].toString() == 'true' ? Icons.credit_card : Icons.money, color: controller.myList[13].toString() == 'true' ? AppColor.deepPurpleAccent : AppColor.greenColor, ), title: Text( 'Payment Method'.tr, style: Theme.of(context).textTheme.titleMedium, ), trailing: Text( controller.myList[13].toString() == 'true' ? 'Visa' : 'Cash', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 10), Card( elevation: 4, child: ListTile( leading: const Icon(Icons.account_circle, color: AppColor.secondaryColor), title: Text( controller.myList[8], style: Theme.of(context).textTheme.titleMedium, ), subtitle: Row( children: [ const Icon(Icons.star, size: 16, color: Colors.amber), Text( controller.myList[33].toString(), style: const TextStyle(color: Colors.amber), ), ], ), ), ), const SizedBox(height: 10), Card( elevation: 4, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.location_on, color: AppColor.greenColor), const SizedBox(width: 8), Expanded( // Keep Expanded here for layout child: Text( controller.myList[29], style: Theme.of(context).textTheme.titleSmall, maxLines: 2, // Allow up to 2 lines overflow: TextOverflow .ellipsis, // Handle overflow ), ), ], ), const Divider(), Row( children: [ const Icon(Icons.flag, color: AppColor.redColor), const SizedBox(width: 8), Expanded( // Keep Expanded here for layout child: Text( controller.myList[30], style: Theme.of(context).textTheme.titleSmall, maxLines: 2, // Allow up to 2 lines overflow: TextOverflow .ellipsis, // Handle overflow ), ), ], ), ], ), ), ), const SizedBox(height: 10), Card( elevation: 4, child: Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _InfoTile( icon: Icons.timer, label: '${((double.tryParse(controller.myList[11].toString()) ?? 0.0) / 60).toStringAsFixed(0)} ${'min'.tr}', ), _InfoTile( icon: Icons.directions_car, label: '${((double.tryParse(controller.myList[12].toString()) ?? 0.0) / 1000).toStringAsFixed(1)} ${'km'.tr}', ), _InfoTile( icon: Icons.money, label: '${controller.myList[2]}', ), ], ), ), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( kolor: AppColor.greenColor, title: 'Accept Order'.tr, onPressed: () async { var res = await CRUD().post( link: "${AppLink.ride}/rides/updateStausFromSpeed.php", payload: { 'id': (controller.myList[16]), 'rideTimeStart': DateTime.now().toString(), 'status': 'Apply', 'driver_id': box.read(BoxName.driverID), }); if (res == 'failure') { MyDialog().getDialog( "This ride is already applied by another driver." .tr, '', () { Get.back(); Get.back(); }); } else { Get.put(HomeCaptainController()).changeRideId(); box.write(BoxName.statusDriverLocation, 'on'); controller.endTimer(); controller.changeApplied(); CRUD().postFromDialogue( link: AppLink.addDriverOrder, payload: { 'driver_id': (controller.myList[6].toString()), 'order_id': (controller.myList[16].toString()), 'status': 'Apply' }); List bodyToPassenger = [ controller.myList[6].toString(), controller.myList[8].toString(), controller.myList[9].toString(), ]; NotificationService.sendNotification( target: controller.myList[9].toString(), title: "Accepted Ride".tr, body: 'your ride is Accepted'.tr, isTopic: false, // Important: this is a token tone: 'start', driverList: bodyToPassenger, category: 'Accepted Ride', ); Get.back(); if (Get.isRegistered()) { Get.find() .pauseHomeMapUpdates(); } // 2. إيقاف تايمر صفحة الطلب الحالية controller.endTimer(); box.write(BoxName.rideArguments, { 'passengerLocation': controller.myList[0].toString(), 'passengerDestination': controller.myList[1].toString(), 'Duration': controller.myList[4].toString(), 'totalCost': controller.myList[26].toString(), 'Distance': controller.myList[5].toString(), 'name': controller.myList[8].toString(), 'phone': controller.myList[10].toString(), 'email': controller.myList[28].toString(), 'WalletChecked': controller.myList[13].toString(), 'tokenPassenger': controller.myList[9].toString(), 'direction': 'https://www.google.com/maps/dir/${controller.myList[0]}/${controller.myList[1]}/', 'DurationToPassenger': controller.myList[15].toString(), 'rideId': (controller.myList[16].toString()), 'passengerId': (controller.myList[7].toString()), 'driverId': (controller.myList[18].toString()), 'durationOfRideValue': controller.myList[19].toString(), 'paymentAmount': controller.myList[2].toString(), 'paymentMethod': controller.myList[13].toString() == 'true' ? 'visa' : 'cash', 'isHaveSteps': controller.myList[20].toString(), 'step0': controller.myList[21].toString(), 'step1': controller.myList[22].toString(), 'step2': controller.myList[23].toString(), 'step3': controller.myList[24].toString(), 'step4': controller.myList[25].toString(), 'passengerWalletBurc': controller.myList[26].toString(), 'timeOfOrder': DateTime.now().toString(), 'totalPassenger': controller.myList[2].toString(), 'carType': controller.myList[31].toString(), 'kazan': controller.myList[32].toString(), 'startNameLocation': controller.myList[29].toString(), 'endNameLocation': controller.myList[30].toString(), }); Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Log.print( 'box.read(BoxName.rideArguments): ${box.read(BoxName.rideArguments)}'); } }, ), GetBuilder( builder: (timerController) { final isNearEnd = timerController.remainingTime <= 5; return Stack( alignment: Alignment.center, children: [ CircularProgressIndicator( value: timerController.progress, color: isNearEnd ? Colors.red : Colors.blue, ), Text( '${timerController.remainingTime}', style: AppStyle.number, ), ], ); }, ), MyElevatedButton( title: 'Refuse Order'.tr, onPressed: () async { controller.endTimer(); controller.addRideToNotificationDriverString( controller.myList[16].toString(), controller.myList[29].toString(), controller.myList[30].toString(), '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}', '${DateTime.now().hour}:${DateTime.now().minute}', controller.myList[2].toString(), controller.myList[7].toString(), 'wait', controller.myList[31].toString(), controller.myList[33].toString(), controller.myList[2].toString(), controller.myList[5].toString(), controller.myList[4].toString()); }, kolor: AppColor.redColor, ), ], ), ], ), ), ], ); }, ), ); } } class _InfoTile extends StatelessWidget { final IconData icon; final String label; const _InfoTile({required this.icon, required this.label}); @override Widget build(BuildContext context) { return Column( children: [ Icon(icon, color: AppColor.primaryColor), const SizedBox(height: 4), Text( label, style: Theme.of(context).textTheme.bodyMedium, ), ], ); } } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/order_over_lay.dart ================================================== import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:just_audio/just_audio.dart'; import 'package:sefer_driver/constant/api_key.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/links.dart'; import '../../../../controller/firebase/firbase_messge.dart'; import '../../../../controller/firebase/local_notification.dart'; import '../../../../controller/firebase/notification_service.dart'; import '../../../../controller/functions/crud.dart'; import '../../../../main.dart'; import '../../../../models/model/order_data.dart'; import '../../../../print.dart'; // === Enhanced Colors for Better Readability === class AppColors { static const primary = Color(0xFF1A252F); static const card = Color(0xFF2C3E50); static const white = Colors.white; static const gray = Color(0xFFBDC3C7); static const lightGray = Color(0xFFECF0F1); static const accent = Color(0xFF00BCD4); static const accept = Color(0xFF4CAF50); static const reject = Color(0xFFFF5722); static const highlight = Color(0xFFFFC107); static const priceHighlight = Color(0xFF00E676); static const urgentRed = Color(0xFFD32F2F); } class OrderOverlay extends StatefulWidget { const OrderOverlay({Key? key}) : super(key: key); @override State createState() => _OrderOverlayState(); } class _OrderOverlayState extends State with WidgetsBindingObserver { // === State Variables === OrderData? orderData; Timer? timer; int remainingSeconds = 10; final AudioPlayer audioPlayer = AudioPlayer(); bool buttonsEnabled = true; final String mapApiKey = AK.mapAPIKEY; final CRUD _crud = CRUD(); final NotificationController notificationController = Get.put(NotificationController()); // === Getters === bool get canShowMap { if (orderData == null || mapApiKey.isEmpty) return false; final start = orderData!.startCoordinates; final end = orderData!.endCoordinates; return start?['lat'] != null && start?['lng'] != null && end?['lat'] != null && end?['lng'] != null; } String get staticMapUrl { if (!canShowMap) return ""; final start = orderData!.startCoordinates!; final end = orderData!.endCoordinates!; final startMarker = Uri.encodeComponent("${start['lat']},${start['lng']}"); final endMarker = Uri.encodeComponent("${end['lat']},${end['lng']}"); return "https://maps.googleapis.com/maps/api/staticmap?" "size=600x150&maptype=roadmap" "&markers=color:green%7Clabel:S%7C$startMarker" "&markers=color:red%7Clabel:D%7C$endMarker" "&path=color:0x007bff%7Cweight:5%7C$startMarker%7C$endMarker" "&key=$mapApiKey"; } // === Lifecycle === @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); FlutterOverlayWindow.overlayListener.listen((event) { if (mounted) _processEventData(event); }); } @override void dispose() { timer?.cancel(); _stopAudio(); audioPlayer.dispose(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { _checkOverlayStatus(); } } List myList = []; // === Setup & Listeners === void _setupOverlayListener() { FlutterOverlayWindow.overlayListener.listen((event) { if (mounted) _processEventData(event); }); } void _processEventData(dynamic event) { _log("Received event: $event"); if (event is List) { try { myList = event; final newOrder = OrderData.fromList(event); _log("Parsed OrderData: ${newOrder.toMap()}"); setState(() { orderData = newOrder; }); _resetAndStartTimer(); } catch (e, s) { _log("Error parsing OrderData: $e\nStackTrace: $s"); } } else { _log("Unexpected data format: $event"); } } void _checkOverlayStatus() async { bool isActive = await FlutterOverlayWindow.isActive(); if (isActive && mounted && orderData != null) { if (remainingSeconds > 0 && (timer == null || !timer!.isActive)) { _resetAndStartTimer(); } } } // === Timer Management === void _resetAndStartTimer() { timer?.cancel(); audioPlayer.stop(); setState(() { buttonsEnabled = true; remainingSeconds = _calculateTimerDuration(); }); _playAudio(); _startTimer(); } int _calculateTimerDuration() { if (orderData?.durationToPassengerMinutes != null && orderData!.durationToPassengerMinutes > 0) { int duration = orderData!.durationToPassengerMinutes * 60; return duration > 10 ? 10 : duration; } return 10; } void _startTimer() { if (orderData == null) return; timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (!mounted) { timer.cancel(); _stopAudio(); return; } setState(() { if (remainingSeconds > 0) { remainingSeconds--; } else { timer.cancel(); _stopAudio(); if (buttonsEnabled) _handleOrderTimeout(); } }); }); } // === Audio Management === void _playAudio() async { try { await audioPlayer.setAsset('assets/order.mp3', preload: true); await audioPlayer.setLoopMode(LoopMode.one); await audioPlayer.play(); } catch (e) { _log('Error playing audio: $e'); } } void _stopAudio() { audioPlayer.stop(); } String _getData(int index, {String defaultValue = ''}) { if (myList.length > index && myList[index] != null) { return myList[index].toString(); } return defaultValue; } // === Order Actions === Future _acceptOrder() async { if (!buttonsEnabled || orderData == null) return; _disableButtonsAndProcess(); _log("Order ACCEPTED: ${orderData!.orderId}"); try { final driverId = box.read(BoxName.driverID)?.toString(); if (driverId == null) { _log("Error: Driver ID is null. Closing overlay."); await _closeOverlay(); return; } var res = await CRUD().post( link: "${AppLink.ride}/rides/updateStausFromSpeed.php", payload: { 'id': orderData!.orderId, 'rideTimeStart': DateTime.now().toString(), 'status': 'Apply', 'driver_id': box.read(BoxName.driverID), }); List bodyToPassenger = [ _getData(6).toString(), _getData(8).toString(), _getData(9).toString(), ]; NotificationService.sendNotification( target: _getData(9).toString(), title: "Accepted Ride".tr, body: 'your ride is Accepted'.tr, isTopic: false, // Important: this is a token tone: 'start', driverList: bodyToPassenger, category: 'Accepted Ride', ); final payload = { // بيانات أساسية 'driver_id': driverId, 'status': 'Apply', 'passengerLocation': _getData(0), 'passengerDestination': _getData(1), 'Duration': _getData(4), 'totalCost': _getData(26), 'Distance': _getData(5), 'name': _getData(8), 'phone': _getData(10), 'email': _getData(28), 'WalletChecked': _getData(13), 'tokenPassenger': _getData(9), 'direction': staticMapUrl.toString(), 'DurationToPassenger': _getData(15), 'rideId': orderData!.orderId, 'passengerId': _getData(7), 'durationOfRideValue': _getData(19), 'paymentAmount': _getData(2), 'paymentMethod': _getData(13) == 'true' ? 'visa' : 'cash', 'isHaveSteps': _getData(20), 'step0': myList[21].toString(), 'step1': myList[22].toString(), 'step2': myList[23].toString(), 'step3': myList[24].toString(), 'step4': myList[25].toString(), 'passengerWalletBurc': myList[26].toString(), 'carType': myList[31].toString(), 'kazan': myList[32].toString(), 'startNameLocation': myList[29].toString(), 'endNameLocation': myList[30].toString(), // الحقول الإضافية التي يجب تضمينها 'timeOfOrder': DateTime.now().toIso8601String(), 'totalPassenger': _getData(2), }; Log.print('myList: ${myList}'); Log.print('payload: ${payload}'); CRUD().post( link: AppLink.addOverLayStatus, payload: payload, ); if (res != "failure") { // Using rideId (_getData(16)) for order_id consistently CRUD().post(link: AppLink.addDriverOrder, payload: { 'driver_id': driverId, // Driver ID from the order data 'order_id': orderData!.orderId, 'status': 'Apply' }); _log("Server update successful. Writing to storage."); notificationController.showNotification( "Order Accepted".tr, "Open app and go to passenger".tr, 'ding', '', ); await _closeOverlay(); } else { _log("Failed to update order status on server: $res"); notificationController.showNotification( "Order Accepted by another driver".tr, "Open app and go to passenger".tr, 'ding', '', ); await _closeOverlay(); } } catch (e, s) { _log( "A critical error occurred during server update: $e\nStackTrace: $s"); if (mounted) setState(() => buttonsEnabled = true); return; } } // Your list parsing for 'customerToken' should be something like: // customerToken: list.length > a_certain_index ? list[a_certain_index].toString() : null, Future _rejectOrder() async { if (!buttonsEnabled || orderData == null) return; _disableButtonsAndProcess(); _log("Order REJECTED: ${orderData!.orderId}"); box.write(BoxName.rideStatus, 'reject'); Log.print('rideStatus from overlay 303 : ${box.read(BoxName.rideStatus)}'); await _apiRefuseOrder(orderData!.orderId); await _closeOverlay(); } void _handleOrderTimeout() { if (orderData == null) return; _log("Order TIMED OUT: ${orderData!.orderId}"); _rejectOrder(); } Future _apiRefuseOrder(String orderID) async { if (orderID == "N/A") { _log("Cannot refuse order with N/A ID"); return; } try { final driverId = box.read(BoxName.driverID)?.toString(); if (driverId == null) { _log("Driver ID is null, cannot refuse order"); return; } _crud.post(link: AppLink.addDriverOrder, payload: { 'driver_id': driverId, 'order_id': orderID, 'status': 'Refused' }); _log("Order $orderID refused successfully"); } catch (e) { _log("Error in _apiRefuseOrder for $orderID: $e"); } } // === Helper Methods === void _disableButtonsAndProcess() { setState(() => buttonsEnabled = false); timer?.cancel(); _stopAudio(); } Future _closeOverlay() async { _stopAudio(); timer?.cancel(); if (await FlutterOverlayWindow.isActive()) { await FlutterOverlayWindow.closeOverlay(); } } void _log(String message) { // A simple logger to distinguish overlay logs print("OVERLAY_LOG: $message"); } // === UI Build Methods === @override Widget build(BuildContext context) { // ... (Your entire UI build method remains unchanged) ... // The UI code is excellent and doesn't need modification. if (orderData == null) { return const Material( color: Colors.transparent, child: Center( child: CircularProgressIndicator(color: AppColors.accent))); } return Material( color: Colors.black.withOpacity(0.4), child: Center( child: Container( margin: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( color: AppColors.card, borderRadius: BorderRadius.circular(20.0), border: Border.all( color: AppColors.accent.withOpacity(0.3), width: 1.5), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.6), blurRadius: 15, spreadRadius: 2, ) ], ), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildQuickHeader(), const SizedBox(height: 12), _buildPrimaryInfo(), const SizedBox(height: 12), if (canShowMap) _buildCompactMap(), if (canShowMap) const SizedBox(height: 12), _buildSecondaryInfo(), const SizedBox(height: 16), _buildEnhancedActionButtons(), ], ), ), ), ), ); } // All your _build... widget methods (_buildQuickHeader, _buildPrimaryInfo, etc.) // are perfectly fine and do not need to be changed. // ... Paste all your existing _build... methods here ... Widget _buildQuickHeader() { return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( gradient: LinearGradient( colors: [ remainingSeconds <= 3 ? AppColors.urgentRed : remainingSeconds <= 5 ? AppColors.highlight : AppColors.accent, remainingSeconds <= 3 ? AppColors.urgentRed.withOpacity(0.7) : remainingSeconds <= 5 ? AppColors.highlight.withOpacity(0.7) : AppColors.accent.withOpacity(0.7), ], ), borderRadius: BorderRadius.circular(15), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon(Icons.drive_eta_rounded, color: AppColors.white, size: 24), const SizedBox(width: 8), Text( "طلب جديد".tr, style: const TextStyle( color: AppColors.white, fontSize: 18, fontWeight: FontWeight.w600), ), ], ), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), decoration: BoxDecoration( color: AppColors.white.withOpacity(0.9), borderRadius: BorderRadius.circular(20), ), child: Text( "$remainingSeconds ث", style: TextStyle( color: remainingSeconds <= 3 ? AppColors.urgentRed : remainingSeconds <= 5 ? AppColors.highlight : AppColors.accent, fontSize: 20, fontWeight: FontWeight.bold, ), ), ), ], ), ); } Widget _buildPrimaryInfo() { final order = orderData!; return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.6), borderRadius: BorderRadius.circular(12), border: Border.all( color: AppColors.priceHighlight.withOpacity(0.3), width: 1), ), child: Column( children: [ // Price and Distance - Most Important Info Row( children: [ Expanded( flex: 3, child: _buildHighlightInfo( // التعديل هنا 👇 "${NumberFormat('#,##0').format(order.price)} ل.س", // أو يمكنك استخدام "SYP" بدلاً من "ل.س" "السعر".tr, Icons.monetization_on_rounded, AppColors.priceHighlight, isLarge: true, ), ), const SizedBox(width: 12), Expanded( flex: 2, child: _buildHighlightInfo( "${order.tripDistanceKm.toStringAsFixed(1)} كم", "المسافة".tr, Icons.straighten_rounded, AppColors.accent, ), ), ], ), const SizedBox(height: 12), Divider(color: AppColors.gray.withOpacity(0.2), thickness: 1), const SizedBox(height: 12), // Passenger Info and ETA Row( children: [ Expanded( flex: 2, child: _buildPassengerQuickInfo(), ), const SizedBox(width: 12), Expanded( child: _buildHighlightInfo( "${order.durationToPassengerMinutes} د", "للوصول".tr, Icons.access_time_filled_rounded, order.durationToPassengerMinutes <= 3 ? AppColors.priceHighlight : AppColors.gray, ), ), ], ), ], ), ); } Widget _buildHighlightInfo( String value, String label, IconData icon, Color color, {bool isLarge = false}) { return Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(10), border: Border.all(color: color.withOpacity(0.3), width: 1), ), child: Column( children: [ Icon(icon, color: color, size: isLarge ? 24 : 20), const SizedBox(height: 4), Text( value, style: TextStyle( color: AppColors.white, fontSize: isLarge ? 20 : 16, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), Text( label, style: TextStyle( color: AppColors.lightGray.withOpacity(0.7), fontSize: 11, ), textAlign: TextAlign.center, ), ], ), ); } Widget _buildPassengerQuickInfo() { final order = orderData!; return Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), decoration: BoxDecoration( color: AppColors.highlight.withOpacity(0.1), borderRadius: BorderRadius.circular(10), border: Border.all(color: AppColors.highlight.withOpacity(0.3), width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.person_rounded, color: AppColors.highlight, size: 18), const SizedBox(width: 4), Expanded( child: Text( order.customerName, style: const TextStyle( color: AppColors.white, fontSize: 14, fontWeight: FontWeight.w600, ), overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 2), Text( order.rideType, style: TextStyle( color: AppColors.lightGray.withOpacity(0.7), fontSize: 11, ), ), ], ), ); } Widget _buildCompactMap() { return ClipRRect( borderRadius: BorderRadius.circular(12.0), child: Image.network( staticMapUrl, height: 100, // Reduced from 110 fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( height: 100, decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.3), borderRadius: BorderRadius.circular(12), ), child: const Center( child: Icon(Icons.map_outlined, color: AppColors.gray, size: 32)), ); }, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return SizedBox( height: 100, child: Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, color: AppColors.accent, strokeWidth: 2.0, ), ), ); }, ), ); } Widget _buildSecondaryInfo() { final order = orderData!; return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.4), borderRadius: BorderRadius.circular(10), ), child: Column( children: [ _buildLocationRow( Icons.trip_origin_rounded, "من".tr, order.startLocationAddress, Colors.green.shade300, ), const SizedBox(height: 8), _buildLocationRow( Icons.flag_rounded, "إلى".tr, order.endLocationAddress, Colors.red.shade300, ), if (order.tripDurationMinutes > 0) ...[ const SizedBox(height: 8), Divider(color: AppColors.gray.withOpacity(0.2), thickness: 0.5), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.timer_outlined, color: AppColors.accent, size: 16), const SizedBox(width: 4), Text( "مدة الرحلة: ${order.tripDurationMinutes} دقيقة".tr, style: const TextStyle( color: AppColors.lightGray, fontSize: 12, ), ), ], ), ] ], ), ); } Widget _buildLocationRow( IconData icon, String label, String address, Color iconColor) { return Row( children: [ Icon(icon, color: iconColor, size: 16), const SizedBox(width: 8), Text( "$label: ", style: TextStyle( color: AppColors.lightGray.withOpacity(0.8), fontSize: 12, fontWeight: FontWeight.w500, ), ), Expanded( child: Text( address, style: const TextStyle( color: AppColors.white, fontSize: 12, ), overflow: TextOverflow.ellipsis, maxLines: 1, ), ), ], ); } Widget _buildEnhancedActionButtons() { return Row( children: [ Expanded( child: ElevatedButton( onPressed: buttonsEnabled ? _rejectOrder : null, style: ElevatedButton.styleFrom( backgroundColor: AppColors.reject, foregroundColor: AppColors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), disabledBackgroundColor: AppColors.reject.withOpacity(0.3), elevation: 3, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.close_rounded, size: 20), const SizedBox(width: 6), Text( "رفض".tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600), ), ], ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: buttonsEnabled ? _acceptOrder : null, style: ElevatedButton.styleFrom( backgroundColor: AppColors.accept, foregroundColor: AppColors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), disabledBackgroundColor: AppColors.accept.withOpacity(0.3), elevation: 3, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.check_circle_rounded, size: 20), const SizedBox(width: 6), Text( "قبول".tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600), ), ], ), ), ), ], ); } } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/call.dart ================================================== // import 'package:flutter/material.dart'; // import 'package:ride/constant/api_key.dart'; // import 'package:ride/constant/box_name.dart'; // import 'package:ride/main.dart'; // import 'package:zego_uikit_prebuilt_call/zego_uikit_prebuilt_call.dart'; // class CallPage extends StatelessWidget { // const CallPage({Key? key, required this.callID}) : super(key: key); // final String callID; // @override // Widget build(BuildContext context) { // return ZegoUIKitPrebuiltCall( // appID: AK // .zegoCloudAppID, // Fill in the appID that you get from ZEGOCLOUD Admin Console. // appSign: AK // .zegoCloudAppSIGN, // Fill in the appSign that you get from ZEGOCLOUD Admin Console. // userID: box.read(BoxName.passengerID) ?? box.read(BoxName.driverID), // userName: box.read(BoxName.name) ?? box.read(BoxName.nameDriver), // callID: callID, // // You can also use groupVideo/groupVoice/oneOnOneVoice to make more types of calls. // config: ZegoUIKitPrebuiltCallConfig.oneOnOneVoiceCall(), // ); // } // } ================================================== FILE PATH: ./lib/views/home/Captin/orderCaptin/test_order_page.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'dart:math' as math; import '../../../../constant/colors.dart'; import '../../../../controller/home/captin/home_captain_controller.dart'; class OrderRequestPageTest extends StatefulWidget { const OrderRequestPageTest({super.key}); @override State createState() => _OrderRequestPageTestState(); } class _OrderRequestPageTestState extends State { late OrderRequestController _orderRequestController; @override void initState() { super.initState(); // Initialize the controller and process arguments _initializeController(); } void _initializeController() { // Get the controller or create a new one if not exists _orderRequestController = Get.put(OrderRequestController()); // Process arguments passed to the page final arguments = Get.arguments; final myListString = arguments['myListString']; var myList = arguments['DriverList'] == null || arguments['DriverList'].isEmpty ? jsonDecode(myListString) : arguments['DriverList']; // Parse coordinates and prepare map data _orderRequestController.parseCoordinates(myList); // Start timer and calculate fuel consumption _orderRequestController.startTimer( myList[6].toString(), myList[16].toString(), ); _orderRequestController.calculateConsumptionFuel(); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 6), child: Container( color: const Color.fromARGB(255, 241, 238, 238), child: ListView( children: [ SizedBox( height: Get.height * .33, child: Obx(() => GoogleMap( initialCameraPosition: CameraPosition( zoom: 12, target: Get.find().myLocation, ), cameraTargetBounds: CameraTargetBounds( _orderRequestController.mapBounds.value), myLocationButtonEnabled: true, trafficEnabled: false, buildingsEnabled: false, mapToolbarEnabled: true, myLocationEnabled: true, markers: _orderRequestController.markers.value, polylines: _orderRequestController.polylines.value, onMapCreated: (GoogleMapController controller) { _orderRequestController.mapController.value = controller; }, onCameraMove: (CameraPosition position) { _orderRequestController .updateCameraPosition(position); }, )), ), // Rest of your UI components ], ), ), ), ], ), ); } } class OrderRequestController extends GetxController { // Reactive variables for map-related data Rx mapBounds = Rx(LatLngBounds( southwest: const LatLng(0, 0), northeast: const LatLng(0, 0))); Rx> markers = Rx>({}); Rx> polylines = Rx>({}); Rx mapController = Rx(null); // Icons for start and end markers late BitmapDescriptor startIcon; late BitmapDescriptor endIcon; // Coordinates for passenger location and destination Rx passengerLocation = Rx(null); Rx passengerDestination = Rx(null); @override void onInit() { super.onInit(); // Initialize marker icons _initializeMarkerIcons(); } void _initializeMarkerIcons() async { // Load custom marker icons startIcon = await BitmapDescriptor.fromAssetImage( const ImageConfiguration(size: Size(48, 48)), 'assets/start_marker.png'); endIcon = await BitmapDescriptor.fromAssetImage( const ImageConfiguration(size: Size(48, 48)), 'assets/end_marker.png'); } void parseCoordinates(List myList) { // Parse coordinates from the input list var cords = myList[0].split(','); var cordDestination = myList[1].split(','); double latPassengerLocation = double.parse(cords[0]); double lngPassengerLocation = double.parse(cords[1]); double latPassengerDestination = double.parse(cordDestination[0]); double lngPassengerDestination = double.parse(cordDestination[1]); // Update passenger location and destination passengerLocation.value = LatLng(latPassengerLocation, lngPassengerLocation); passengerDestination.value = LatLng(latPassengerDestination, lngPassengerDestination); // Create markers _createMarkers(); // Create polyline _createPolyline(); // Calculate map bounds _calculateMapBounds(); } void _createMarkers() { if (passengerLocation.value == null || passengerDestination.value == null) return; markers.value = { Marker( markerId: MarkerId('MyLocation'.tr), position: passengerLocation.value!, draggable: true, icon: startIcon, ), Marker( markerId: MarkerId('Destination'.tr), position: passengerDestination.value!, draggable: true, icon: endIcon, ), }; } void _createPolyline() { if (passengerLocation.value == null || passengerDestination.value == null) return; polylines.value = { Polyline( zIndex: 1, consumeTapEvents: true, geodesic: true, endCap: Cap.buttCap, startCap: Cap.buttCap, visible: true, polylineId: const PolylineId('routeOrder'), points: [passengerLocation.value!, passengerDestination.value!], color: AppColor.primaryColor, width: 2, ), }; } void _calculateMapBounds() { if (passengerLocation.value == null || passengerDestination.value == null) return; double minLatitude = math.min(passengerLocation.value!.latitude, passengerDestination.value!.latitude); double maxLatitude = math.max(passengerLocation.value!.latitude, passengerDestination.value!.latitude); double minLongitude = math.min(passengerLocation.value!.longitude, passengerDestination.value!.longitude); double maxLongitude = math.max(passengerLocation.value!.longitude, passengerDestination.value!.longitude); mapBounds.value = LatLngBounds( southwest: LatLng(minLatitude, minLongitude), northeast: LatLng(maxLatitude, maxLongitude), ); } void updateCameraPosition(CameraPosition position) { // Implement any specific logic for camera position updates } void startTimer(String param1, String param2) { // Implement timer start logic } void calculateConsumptionFuel() { // Implement fuel consumption calculation } } ================================================== FILE PATH: ./lib/views/home/Captin/About Us/using_app_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; // 1. إنشاء Class لتمثيل بيانات كل سؤال وجواب class FaqItem { final String question; final Widget answer; // استخدام Widget يسمح بوضع نصوص أو صور final IconData icon; FaqItem({required this.question, required this.answer, required this.icon}); } class UsingAppPage extends StatelessWidget { const UsingAppPage({super.key}); @override Widget build(BuildContext context) { // 2. تجهيز قائمة البيانات بشكل منظم final List faqItems = [ FaqItem( question: "What are the order details we provide to you?".tr, icon: Icons.receipt_long_outlined, answer: Padding( padding: const EdgeInsets.all(8.0), child: Image.network( 'https://api.tripz-egypt.com/tripz/imageForUsingApp/order_page.jpg', fit: BoxFit.cover, // يمكنك إضافة مؤشر تحميل هنا loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const Center(child: CircularProgressIndicator()); }, errorBuilder: (context, error, stackTrace) { return const Center( child: Icon(Icons.error_outline, color: Colors.red, size: 40)); }, ), ), ), FaqItem( question: "What is the feature of our wallet?".tr, icon: Icons.account_balance_wallet_outlined, answer: Text( '''Intaleq Wallet Features: - Transfer money multiple times. - Transfer to anyone. - Make purchases. - Charge your account. - Charge a friend's Intaleq account. - Store your money with us and receive it in your bank as a monthly salary.''' .tr, style: TextStyle(fontSize: 15, height: 1.5, color: Colors.grey.shade700), ), ), FaqItem( question: "What is Types of Trips in Intaleq?".tr, icon: Icons.map_outlined, answer: Text( '''Types of Trips in Intaleq: - Comfort: For cars newer than 2017 with air conditioning. - Lady: For girl drivers. - Speed: For fixed salary and endpoints. - Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements. - Raih Gai: For same-day return trips longer than 50km.''' .tr, style: TextStyle(fontSize: 15, height: 1.5, color: Colors.grey.shade700), ), ), ]; // 3. بناء الواجهة الرسومية باستخدام البيانات return MyScafolld( title: "How to use App".tr, // تم تغيير العنوان ليكون أعم isleading: true, body: [ ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), itemCount: faqItems.length, separatorBuilder: (context, index) => const SizedBox(height: 12), itemBuilder: (context, index) { final item = faqItems[index]; return Card( elevation: 2, shadowColor: Colors.black.withOpacity(0.1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16)), clipBehavior: Clip.antiAlias, child: ExpansionTile( leading: Icon(item.icon, color: Theme.of(context).primaryColor), title: Text(item.question, style: const TextStyle(fontWeight: FontWeight.w600)), childrenPadding: const EdgeInsets.fromLTRB(16, 0, 16, 16), expandedCrossAxisAlignment: CrossAxisAlignment.start, children: [ const Divider(height: 1), const SizedBox(height: 12), item.answer, ], ), ); }, ), ], ); } } ================================================== FILE PATH: ./lib/views/home/Captin/About Us/frequantly_question.dart ================================================== import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../../constant/style.dart'; class FrequentlyQuestionsPage extends StatelessWidget { const FrequentlyQuestionsPage({super.key}); @override Widget build(BuildContext context) { String selectedPayment = 'cash'; // Replace with your initial selection bool canCancelRide = false; return MyScafolld( title: 'Frequently Questions'.tr, body: [ Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ // Question 1: How do I request a ride? ExpansionTile( title: Text( 'How do I request a ride?'.tr, style: AppStyle.title, ), children: [ Text( 'Step-by-step instructions on how to request a ride through the Intaleq app.' .tr, style: AppStyle.title, ), ], ), // Question 2: What types of vehicles are available? ExpansionTile( title: Text( 'What types of vehicles are available?'.tr, style: AppStyle.title, ), children: [ Text( 'Intaleq offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.' .tr, style: AppStyle.title, ), ], ), // Question 3: How can I pay for my ride? ExpansionTile( title: Text( 'How can I pay for my ride?'.tr, style: AppStyle.title, ), children: [ Text( 'Intaleq offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.' .tr, style: AppStyle.title, ), ], ), // Question 4: Can I cancel my ride? (if applicable) ExpansionTile( title: Text( 'Can I cancel my ride?'.tr, style: AppStyle.title, ), children: [ Text( 'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Intaleq cancellation policy for details.' .tr, style: AppStyle.title, ), ], ), // Question 5 & 6: Driver-specific questions ExpansionTile( title: Text( 'Driver Registration & Requirements'.tr, style: AppStyle.title, ), children: [ Text( '${'How can I register as a driver?'.tr}\n${'What are the requirements to become a driver?'.tr}', style: AppStyle.title, ), InkWell( onTap: () { MyDialog().getDialog('title', 'midTitle', () { ; //todo add in this dialog papers for driver }); }, child: Text( 'Visit our website or contact Intaleq support for information on driver registration and requirements.' .tr, style: AppStyle.title, ), ), ], ), // Question 7: How do I communicate with the other party? ExpansionTile( title: Text( 'How do I communicate with the other party (passenger/driver)?' .tr, style: AppStyle.title, ), children: [ Text( 'Intaleq provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.' .tr, style: AppStyle.title, ), ], ), // Question 8: What safety measures does Intaleq offer? ExpansionTile( title: Text( 'What safety measures does Intaleq offer?'.tr, style: AppStyle.title, ), children: [ Text( 'Intaleq prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.' .tr, style: AppStyle.title, ), ], ), ], ), ) ], isleading: true); } } ================================================== FILE PATH: ./lib/views/home/Captin/About Us/settings_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/profile/setting_controller.dart'; import 'package:sefer_driver/views/lang/languages.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; // تأكد من صحة مسارات الاستيراد هذه import '../../../../controller/functions/vibrate.dart'; // Controller with isVibrate import '../../../auth/country_widget.dart'; import 'about_us.dart'; import 'frequantly_question.dart'; import 'using_app_page.dart'; class SettingsCaptain extends StatelessWidget { const SettingsCaptain({super.key}); @override Widget build(BuildContext context) { // تحميل الـ Controllers المطلوبة final settingsController = Get.put(SettingController()); final homeController = Get.put(HomePageController()); return MyScafolld( title: 'Settings'.tr, isleading: true, body: [ ListView( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), children: [ // --- القسم الأول: عام --- _buildSectionHeader('General'.tr, context), _buildSettingsCard( children: [ _buildListTile( icon: Icons.language_outlined, title: 'Language'.tr, subtitle: 'Change the app language'.tr, onTap: () => Get.to(() => const Language()), ), // _buildListTile( // icon: Icons.flag_outlined, // title: 'Change Country'.tr, // subtitle: 'Get features for your country'.tr, // onTap: () => Get.to( // () => MyScafolld( // title: 'Change Country'.tr, // body: [CountryPickerFromSetting()], // isleading: true, // ), // ), // ), ], ), const SizedBox(height: 20), // --- القسم الثاني: تفضيلات التطبيق --- _buildSectionHeader('App Preferences'.tr, context), _buildSettingsCard( children: [ _buildSwitchTile( icon: Icons.map_outlined, color: AppColor.redColor, title: 'Google Map App'.tr, subtitle: 'Run Google Maps directly'.tr, controller: settingsController, valueGetter: (ctrl) => (ctrl).isGoogleMapsEnabled, onChanged: (ctrl) => (ctrl).onChangMapApp(), ), _buildSwitchTile( icon: Icons.vibration, title: 'Vibration'.tr, subtitle: 'Vibration feedback for buttons'.tr, controller: homeController, valueGetter: (ctrl) => (ctrl).isVibrate, onChanged: (ctrl) => (ctrl) .changeVibrateOption(true), // قد تحتاج لتعديل الدالة ), ], ), const SizedBox(height: 20), // --- القسم الثالث: المساعدة والدعم --- _buildSectionHeader('Help & Support'.tr, context), _buildSettingsCard( children: [ _buildListTile( icon: Icons.quiz_outlined, title: 'Frequently Questions'.tr, onTap: () => Get.to(() => const FrequentlyQuestionsPage()), ), _buildListTile( icon: Icons.support_agent, title: "How to use App".tr, onTap: () => Get.to(() => const UsingAppPage()), ), _buildListTile( icon: Icons.info_outline, title: 'About Us'.tr, onTap: () => Get.to(() => const AboutPage()), ), ], ), const SizedBox(height: 20), // --- القسم الرابع: تسجيل الخروج --- _buildSectionHeader('Account'.tr, context), _buildSettingsCard( children: [ ListTile( leading: const Icon(Icons.logout, color: Colors.red), title: Text( 'Logout'.tr, style: const TextStyle( color: Colors.red, fontWeight: FontWeight.w500), ), onTap: () { MyDialog().getDialog( 'Logout'.tr, 'Are you sure you want to logout?'.tr, () { // أضف دالة تسجيل الخروج هنا Get.back(); // لإغلاق مربع الحوار }, // isConfirmation: true, ); }, ) ], ) ], ), ], ); } // ويدجت لبناء عنوان كل قسم Widget _buildSectionHeader(String title, BuildContext context) { return Padding( padding: const EdgeInsets.only(left: 8.0, bottom: 12.0), child: Text( title, style: Theme.of(context).textTheme.titleSmall?.copyWith( color: Colors.grey.shade600, fontWeight: FontWeight.bold, ), ), ); } // ويدجت لبناء بطاقة الإعدادات Widget _buildSettingsCard({required List children}) { return Card( elevation: 2, shadowColor: Colors.black.withOpacity(0.1), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), clipBehavior: Clip.antiAlias, // مهم لجعل splash effect داخل حدود البطاقة child: Column(children: children), ); } // ويدجت لبناء عنصر قابل للضغط (مثل اللغة، عن التطبيق) Widget _buildListTile({ required IconData icon, required String title, String? subtitle, required VoidCallback onTap, }) { return ListTile( leading: Icon(icon, color: Colors.grey.shade700), title: Text(title, style: const TextStyle(fontWeight: FontWeight.w500)), subtitle: subtitle != null ? Text(subtitle) : null, trailing: const Icon(Icons.arrow_forward_ios, size: 16, color: Colors.grey), onTap: onTap, ); } // ويدجت لبناء عنصر يحتوي على مفتاح تفعيل/إلغاء (Switch) Widget _buildSwitchTile({ required IconData icon, Color? color, required String title, required String subtitle, required T controller, required bool Function(T) valueGetter, required Function(T) onChanged, }) { return GetBuilder( init: controller, builder: (ctrl) { return SwitchListTile( secondary: Icon(icon, color: color ?? Colors.grey.shade700), title: Text(title, style: const TextStyle(fontWeight: FontWeight.w500)), subtitle: Text(subtitle), value: valueGetter(ctrl), onChanged: (value) => onChanged(ctrl), activeColor: AppColor.primaryColor, ); }, ); } } ================================================== FILE PATH: ./lib/views/home/Captin/About Us/video_page.dart ================================================== import 'package:sefer_driver/constant/info.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:video_player/video_player.dart'; import 'package:youtube_player_flutter/youtube_player_flutter.dart'; import '../../../../controller/home/captin/help/video_controller.dart'; import 'package:flutter/cupertino.dart'; class VideoListPage extends StatelessWidget { final VideoController videoController = Get.put(VideoController()); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('Videos Tutorials'.tr), ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 10.0), // Outer padding around the list child: GetBuilder( builder: (videoController) { return ListView.builder( itemCount: videoController.videos.length, itemBuilder: (context, index) { final video = videoController.videos[index]; return Container( margin: const EdgeInsets.symmetric( vertical: 8.0), // Spacing between each card decoration: BoxDecoration( color: CupertinoColors.white, borderRadius: BorderRadius.circular(12.0), // Rounded corners boxShadow: [ BoxShadow( color: CupertinoColors.systemGrey.withOpacity(0.3), offset: const Offset( 0, 4), // Offset for shadow to appear below blurRadius: 10.0, // Blur for softer shadow effect ), ], border: Border.all( color: CupertinoColors.systemGrey4, width: 0.5, // Subtle border for a refined iOS-like look ), ), child: CupertinoListTile( title: Padding( padding: const EdgeInsets.only(bottom: 4.0), child: Text( video['title'], style: const TextStyle( color: CupertinoColors.black, fontWeight: FontWeight.bold, ), ), ), subtitle: Text( video['description'], style: const TextStyle( color: CupertinoColors.systemGrey, ), ), onTap: () { // Navigate to video player page (iOS-style) Get.to(() => VideoPlayerPage1(videoUrl: video['url'])); }, ), ); }, ); }, ), ), ), ); } } class VideoPlayerPage extends StatelessWidget { final String videoUrl; VideoPlayerPage({required this.videoUrl}); final VideoController videoController = Get.put(VideoController()); @override Widget build(BuildContext context) { // Initialize the video when the page is loaded videoController.initializeVideo(videoUrl); return CupertinoPageScaffold( navigationBar: const CupertinoNavigationBar( middle: Text(AppInformation.appName), ), child: SafeArea( child: Center( child: GetBuilder( builder: (controller) { if (!controller.videoPlayerController.value.isInitialized) { return const CircularProgressIndicator(); // Show loading indicator while initializing } return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Video player widget AspectRatio( aspectRatio: controller.videoPlayerController.value.aspectRatio, // child: VideoPlayer(controller.videoPlayerController), child: VideoPlayer(controller.videoPlayerController), ), const SizedBox(height: 20), // Play/pause button CupertinoButton( onPressed: () { if (controller.videoPlayerController.value.isPlaying) { controller.pause(); } else { controller.play(); } }, child: Icon( controller.videoPlayerController.value.isPlaying ? CupertinoIcons.pause : CupertinoIcons.play_arrow, color: CupertinoColors.activeBlue, size: 30, ), ), ], ); }, ), ), ), ); } } class VideoPlayerPage1 extends StatelessWidget { final String videoUrl; const VideoPlayerPage1({required this.videoUrl}); @override Widget build(BuildContext context) { // Extract the video ID from the URL String videoId = YoutubePlayer.convertUrlToId(videoUrl)!; // Create a YoutubePlayerController final YoutubePlayerController _controller = YoutubePlayerController( initialVideoId: videoId, flags: const YoutubePlayerFlags( autoPlay: true, loop: true, mute: false, captionLanguage: 'ar', ), ); return Scaffold( body: Stack( children: [ // Full-screen YouTube player Positioned.fill( child: YoutubePlayer( controller: _controller, showVideoProgressIndicator: true, ), ), // Overlay back button in the top left corner for exit Positioned( top: 40.0, left: 16.0, child: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () { Navigator.pop(context); }, ), ), ], ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/About Us/about_us.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class AboutPage extends StatelessWidget { const AboutPage({super.key}); @override Widget build(BuildContext context) { return MyScafolld( title: 'About Us'.tr, body: [ // Company Logo (consider adding an image asset) ListView( children: [ Center( child: Image.asset( 'assets/images/logo.png', // Replace with your logo image asset path height: 100.0, width: 100.0, ), ), // Company Name and Location Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Intaleq LLC\n${'Syria'.tr}', style: AppStyle.headTitle2, textAlign: TextAlign.center, ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'Intaleq is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:' .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), // Security Features List const SizedBox( height: 20, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( children: [ Row( children: [ const Icon(Icons.lock, color: Colors.blue), const SizedBox(width: 8.0), Text( 'Most Secure Methods'.tr, style: AppStyle.title, ), ], ), const SizedBox(height: 8.0), Row( children: [ const Icon(Icons.phone, color: Colors.blue), const SizedBox(width: 8.0), Text( 'In-App VOIP Calls'.tr, style: AppStyle.title, ), ], ), const SizedBox(height: 8.0), Row( children: [ const Icon(Icons.videocam, color: Colors.blue), const SizedBox(width: 8.0), Text( 'Recorded Trips for Safety'.tr, style: AppStyle.title, ), ], ), ], ), ), // Affordability Highlight Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( '\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.' .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), ], ), // About Us Text ], isleading: true); } } ================================================== FILE PATH: ./lib/views/home/Captin/history/history_details_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:sefer_driver/controller/auth/captin/history_captain.dart'; import 'package:sefer_driver/controller/functions/launch.dart'; class HistoryDetailsPage extends StatefulWidget { const HistoryDetailsPage({super.key}); @override State createState() => _HistoryDetailsPageState(); } class _HistoryDetailsPageState extends State { // Get the controller instance final HistoryCaptainController controller = Get.find(); // Helper method to safely parse LatLng from a string 'lat,lng' LatLng? _parseLatLng(String? latLngString) { if (latLngString == null) return null; final parts = latLngString.split(','); if (parts.length != 2) return null; final lat = double.tryParse(parts[0]); final lng = double.tryParse(parts[1]); if (lat == null || lng == null) return null; return LatLng(lat, lng); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( title: Text('Trip Details'.tr), backgroundColor: Colors.white, elevation: 1, ), body: GetBuilder( builder: (controller) { if (controller.isloading) { return const Center(child: CircularProgressIndicator()); } final res = controller.historyDetailsData['data']; if (res == null) { return Center(child: Text('Could not load trip details.'.tr)); } final startLocation = _parseLatLng(res['start_location']); final endLocation = _parseLatLng(res['end_location']); // Create markers for the map final Set markers = {}; if (startLocation != null) { markers.add(Marker( markerId: const MarkerId('start'), position: startLocation, infoWindow: InfoWindow(title: 'Start'.tr))); } if (endLocation != null) { markers.add(Marker( markerId: const MarkerId('end'), position: endLocation, infoWindow: InfoWindow(title: 'End'.tr))); } return AnimationLimiter( child: ListView( padding: const EdgeInsets.all(16.0), children: AnimationConfiguration.toStaggeredList( duration: const Duration(milliseconds: 375), childAnimationBuilder: (widget) => SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation(child: widget), ), children: [ // --- Map Card --- _buildMapCard(context, startLocation, endLocation, markers), const SizedBox(height: 16), // --- Trip Info Card --- _DetailCard( icon: Icons.receipt_long, title: 'Trip Info'.tr, child: Column( children: [ _InfoTile( label: 'Order ID'.tr, value: res['id']?.toString() ?? 'N/A'), _InfoTile( label: 'Date'.tr, value: res['date']?.toString() ?? 'N/A'), ], ), ), // --- Earnings Card --- _DetailCard( icon: Icons.account_balance_wallet, title: 'Earnings & Distance'.tr, child: Column( children: [ _InfoTile( label: 'Your Earnings'.tr, value: '${res['price_for_driver']}'), _InfoTile( label: 'Distance'.tr, value: '${res['distance']} KM'), ], ), ), // --- Timeline Card --- _DetailCard( icon: Icons.timeline, title: 'Trip Timeline'.tr, child: Column( children: [ _InfoTile( label: 'Time to Passenger'.tr, value: res['DriverIsGoingToPassenger'] ?? 'N/A'), _InfoTile( label: 'Trip Started'.tr, value: res['rideTimeStart'] ?? 'N/A'), _InfoTile( label: 'Trip Finished'.tr, value: res['rideTimeFinish'] ?? 'N/A'), ], ), ), // --- Passenger & Status Card --- _DetailCard( icon: Icons.person, title: 'Passenger & Status'.tr, child: Column( children: [ _InfoTile( label: 'Passenger Name'.tr, value: '${res['passengerName']} ${res['last_name']}'), _InfoTile( label: 'Status'.tr, value: res['status'] ?? 'N/A', isStatus: true), ], ), ), ], ), ), ); }, ), ); } Widget _buildMapCard(BuildContext context, LatLng? startLocation, LatLng? endLocation, Set markers) { // A fallback position if locations are not available final initialCameraPosition = (startLocation != null) ? CameraPosition(target: startLocation, zoom: 14) : const CameraPosition( target: LatLng(31.96, 35.92), zoom: 12); // Fallback to Amman return Card( elevation: 4, shadowColor: Colors.black.withOpacity(0.1), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), clipBehavior: Clip.antiAlias, // Ensures the map respects the border radius child: Stack( children: [ SizedBox( height: 250, child: GoogleMap( initialCameraPosition: initialCameraPosition, markers: markers, polylines: { if (startLocation != null && endLocation != null) Polyline( polylineId: const PolylineId('route'), points: [startLocation, endLocation], color: Colors.deepPurple, width: 5, ), }, onMapCreated: (GoogleMapController mapController) { // Animate camera to fit the route if (startLocation != null && endLocation != null) { LatLngBounds bounds = LatLngBounds( southwest: LatLng( startLocation.latitude < endLocation.latitude ? startLocation.latitude : endLocation.latitude, startLocation.longitude < endLocation.longitude ? startLocation.longitude : endLocation.longitude, ), northeast: LatLng( startLocation.latitude > endLocation.latitude ? startLocation.latitude : endLocation.latitude, startLocation.longitude > endLocation.longitude ? startLocation.longitude : endLocation.longitude, ), ); mapController.animateCamera( CameraUpdate.newLatLngBounds(bounds, 60.0)); } }, ), ), Positioned( top: 10, right: 10, child: FloatingActionButton.small( heroTag: 'open_maps', onPressed: () { if (startLocation != null && endLocation != null) { String mapUrl = 'https://www.google.com/maps/dir/${startLocation.latitude},${startLocation.longitude}/${endLocation.latitude},${endLocation.longitude}/'; showInBrowser(mapUrl); } }, child: const Icon(Icons.directions), ), ), ], ), ); } } // A reusable widget for the main detail cards class _DetailCard extends StatelessWidget { final IconData icon; final String title; final Widget child; const _DetailCard({ required this.icon, required this.title, required this.child, }); @override Widget build(BuildContext context) { return Card( elevation: 2, shadowColor: Colors.black.withOpacity(0.05), margin: const EdgeInsets.only(bottom: 16.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(icon, color: Theme.of(context).primaryColor), const SizedBox(width: 8), Text( title, style: Theme.of(context) .textTheme .titleLarge ?.copyWith(fontWeight: FontWeight.bold), ), ], ), const Divider(height: 24), child, ], ), ), ); } } // A reusable widget for a label-value pair inside a card class _InfoTile extends StatelessWidget { final String label; final String value; final bool isStatus; const _InfoTile({ required this.label, required this.value, this.isStatus = false, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: Theme.of(context) .textTheme .titleMedium ?.copyWith(color: Colors.grey[700])), if (isStatus) _buildStatusChip(value) else Flexible( child: Text( value, style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.bold), textAlign: TextAlign.end, ), ), ], ), ); } } // Reusing the status chip from the previous page for consistency Widget _buildStatusChip(String status) { Color chipColor; Color textColor; IconData iconData; switch (status.toLowerCase()) { case 'apply': case 'completed': // Assuming 'Apply' means completed chipColor = Colors.green.shade50; textColor = Colors.green.shade800; iconData = Icons.check_circle; status = 'Completed'; break; case 'refused': chipColor = Colors.red.shade50; textColor = Colors.red.shade800; iconData = Icons.cancel; break; case 'cancel': chipColor = Colors.orange.shade50; textColor = Colors.orange.shade800; iconData = Icons.info; status = 'Cancelled'; break; default: chipColor = Colors.grey.shade200; textColor = Colors.grey.shade800; iconData = Icons.hourglass_empty; } return Chip( avatar: Icon(iconData, color: textColor, size: 16), label: Text( status.tr, style: TextStyle(color: textColor, fontWeight: FontWeight.w600), ), backgroundColor: chipColor, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), side: BorderSide.none, ); } ================================================== FILE PATH: ./lib/views/home/Captin/history/history_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import '../../../../controller/auth/captin/history_captain.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; class HistoryCaptain extends StatelessWidget { const HistoryCaptain({super.key}); @override Widget build(BuildContext context) { Get.put(HistoryCaptainController()); return Scaffold( backgroundColor: Colors.grey[100], // A softer background color appBar: AppBar( title: Text('Ride History'.tr), backgroundColor: Colors.white, foregroundColor: Colors.black, elevation: 1, ), body: GetBuilder( builder: (controller) { if (controller.isloading) { return const Center(child: CircularProgressIndicator()); } if (controller.historyData['message'].isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.history_toggle_off, size: 80, color: Colors.grey[400]), const SizedBox(height: 16), Text( 'No Rides Yet'.tr, style: Theme.of(context) .textTheme .headlineSmall ?.copyWith(color: Colors.grey[600]), ), ], ), ); } // 动画: Wrap ListView with AnimationLimiter for staggered animations return AnimationLimiter( child: ListView.builder( padding: const EdgeInsets.all(16.0), itemCount: controller.historyData['message'].length, itemBuilder: (BuildContext context, int index) { var trip = controller.historyData['message'][index]; // 动画: Apply animation to each list item return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: _AnimatedHistoryCard( trip: trip, onTap: () { // Your original logic is preserved here if (trip['status'] != 'Cancel') { controller.getHistoryDetails(trip['order_id']); } else { MyDialog().getDialog( 'This Trip Was Cancelled'.tr, 'This Trip Was Cancelled'.tr, () => Get.back(), ); } }, ), ), ), ); }, ), ); }, ), ); } } // 动画: A new stateful widget to handle the tap animation class _AnimatedHistoryCard extends StatefulWidget { final Map trip; final VoidCallback onTap; const _AnimatedHistoryCard({required this.trip, required this.onTap}); @override __AnimatedHistoryCardState createState() => __AnimatedHistoryCardState(); } class __AnimatedHistoryCardState extends State<_AnimatedHistoryCard> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 150), ); _scaleAnimation = Tween(begin: 1.0, end: 0.95).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { _controller.forward(); } void _onTapUp(TapUpDetails details) { _controller.reverse(); widget.onTap(); } void _onTapCancel() { _controller.reverse(); } @override Widget build(BuildContext context) { return GestureDetector( onTapDown: _onTapDown, onTapUp: _onTapUp, onTapCancel: _onTapCancel, child: ScaleTransition( scale: _scaleAnimation, child: Card( elevation: 4, shadowColor: Colors.black.withOpacity(0.1), margin: const EdgeInsets.only(bottom: 16.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16.0), child: Row( children: [ Icon(Icons.receipt_long, color: Theme.of(context).primaryColor, size: 40), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${'OrderId'.tr}: ${widget.trip['order_id']}', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( widget.trip['created_at'], style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Colors.grey[600], ), ), ], ), ), const SizedBox(width: 16), _buildStatusChip(widget.trip['status']), ], ), ), ), ), ); } } // 🎨 A separate function for the status chip, slightly restyled for Material Widget _buildStatusChip(String status) { Color chipColor; Color textColor; String statusText = status; IconData iconData; switch (status) { case 'Apply': chipColor = Colors.green.shade50; textColor = Colors.green.shade800; iconData = Icons.check_circle; break; case 'Refused': chipColor = Colors.red.shade50; textColor = Colors.red.shade800; iconData = Icons.cancel; break; case 'Cancel': chipColor = Colors.orange.shade50; textColor = Colors.orange.shade800; iconData = Icons.info; statusText = 'Cancelled'; break; default: chipColor = Colors.grey.shade200; textColor = Colors.grey.shade800; iconData = Icons.hourglass_empty; } return Chip( avatar: Icon(iconData, color: textColor, size: 16), label: Text( statusText.tr, style: TextStyle(color: textColor, fontWeight: FontWeight.w600), ), backgroundColor: chipColor, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), side: BorderSide.none, ); } ================================================== FILE PATH: ./lib/views/home/Captin/mapDriverWidgets/google_driver_map_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../../../../controller/functions/location_controller.dart'; import '../../../../controller/home/captin/map_driver_controller.dart'; class GoogleDriverMap extends StatelessWidget { const GoogleDriverMap({ super.key, required this.locationController, }); final LocationController locationController; @override Widget build(BuildContext context) { final MapDriverController controller = Get.put(MapDriverController()); // New: تحديد قيمة الـ padding لتحريك مركز الخريطة للأعلى final double mapPaddingBottom = MediaQuery.of(context).size.height * 0.3; return GetBuilder( builder: (controller) => GoogleMap( onMapCreated: (mapController) { controller.onMapCreated(mapController); // New: تطبيق الـ padding بعد إنشاء الخريطة مباشرة mapController.setMapStyle('[]'); // يمكنك إضافة تصميم مخصص للخريطة هنا // يمكنك استخدام CameraUpdate.scrollBy لتحريك الكاميرا إذا رغبت بذلك: // controller.mapController!.animateCamera(CameraUpdate.scrollBy(0, mapPaddingBottom)); }, // New: إضافة padding لتحريك مركز الخريطة للأعلى، مما يجعل أيقونة السائق تظهر في الأسفل zoomControlsEnabled: false, // Changed: تم إخفاء أزرار الزوم الافتراضية initialCameraPosition: CameraPosition( target: locationController.myLocation, zoom: 17, bearing: locationController.heading, // استخدام اتجاه السائق tilt: 60, // زاوية ميل ), onCameraMove: (position) { CameraPosition( target: locationController.myLocation, zoom: 17.5, tilt: 50.0, bearing: locationController.heading, ); }, padding: EdgeInsets.only(bottom: 50, top: Get.height * 0.7), minMaxZoomPreference: const MinMaxZoomPreference(8, 18), myLocationEnabled: false, // Changed: تم الاعتماد على ماركر مخصص myLocationButtonEnabled: true, compassEnabled: true, mapType: MapType.terrain, trafficEnabled: true, // Changed: تفعيل عرض حركة المرور buildingsEnabled: true, polylines: { Polyline( zIndex: 2, polylineId: const PolylineId('route1'), points: controller.polylineCoordinates, color: const Color.fromARGB(255, 163, 81, 246), width: 6, // Changed: زيادة عرض الخط startCap: Cap.roundCap, endCap: Cap.roundCap, ), // Polyline( // zIndex: 2, // polylineId: const PolylineId('route'), // points: controller.polylineCoordinatesDestination, // color: const Color.fromARGB(255, 10, 29, 126), // width: 6, // Changed: زيادة عرض الخط // startCap: Cap.roundCap, // endCap: Cap.roundCap, // ), Polyline( polylineId: const PolylineId('upcoming_route'), points: controller.upcomingPathPoints, color: Colors.blue, // أو أي لون آخر تختاره للمسار width: 8, zIndex: 2, ), // 2. الخط المقطوع (تحت) Polyline( polylineId: const PolylineId('traveled_route'), points: controller.traveledPathPoints, color: Colors.grey.withOpacity(0.8), width: 7, zIndex: 1, ), }, markers: { Marker( markerId: MarkerId('MyLocation'.tr), position: locationController.myLocation, rotation: locationController.heading, flat: true, anchor: const Offset(0.5, 0.5), icon: controller.carIcon, ), Marker( markerId: MarkerId('start'.tr), position: controller.latLngPassengerLocation, icon: controller.startIcon, ), Marker( markerId: MarkerId('end'.tr), position: controller.latLngPassengerDestination, icon: controller.endIcon, ), }, ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/mapDriverWidgets/driver_end_ride_bar.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:slide_to_act/slide_to_act.dart'; import 'package:vibration/vibration.dart'; import 'dart:io'; import '../../../../constant/colors.dart'; import '../../../../constant/style.dart'; import '../../../../controller/home/captin/map_driver_controller.dart'; import '../../../widgets/elevated_btn.dart'; // Changed: إعادة تصميم كاملة للشريط ليصبح شريطًا علويًا عند بدء الرحلة // ملف: driver_end_ride_bar.dart Widget driverEndRideBar() { // 1. Positioned هي الوالد المباشر (لأنها داخل Stack في الصفحة الرئيسية) return Positioned( top: 0, left: 0, right: 0, // 2. GetBuilder يكون في الداخل child: GetBuilder( builder: (controller) => AnimatedContainer( duration: const Duration(milliseconds: 300), // 3. نستخدم التحريك (Translation) لإخفاء الشريط وإظهاره بدلاً من تغيير الـ top transform: Matrix4.translationValues( 0, controller.isRideStarted ? 0 : -250, 0), child: Card( margin: EdgeInsets.zero, elevation: 10, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(bottom: Radius.circular(24)), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), child: Column( children: [ if (controller.carType != 'Mishwar Vip') Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildInfoColumn( icon: Icons.social_distance, text: '${controller.distance} ${'KM'.tr}', label: 'Distance'.tr, ), _buildInfoColumn( icon: Icons.timelapse, text: controller.hours > 1 ? '${controller.hours}h ${controller.minutes}m' : '${controller.minutes}m', label: 'Time'.tr, ), _buildInfoColumn( icon: Icons.money_sharp, text: '${NumberFormat('#,##0').format(double.tryParse(controller.paymentAmount.toString()) ?? 0)} ${'SYP'.tr}', label: 'Price'.tr, ), ], ), // ... بقية الكود كما هو (الأزرار والمؤقت) if (controller.carType != 'Mishwar Vip') const Divider(height: 20), const _builtTimerAndCarType(), const SizedBox(height: 12), SlideAction( height: 55, borderRadius: 15, elevation: 4, text: 'Slide to End Trip'.tr, textStyle: AppStyle.title.copyWith( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), outerColor: AppColor.redColor, innerColor: Colors.white, sliderButtonIcon: const Icon( Icons.arrow_forward_ios, color: AppColor.redColor, size: 24, ), sliderRotate: false, onSubmit: () { HapticFeedback.mediumImpact(); controller.finishRideFromDriver(); return null; }, ), ], ), ), ), ), ), ); } // New: ودجت لعرض معلومات الرحلة في الشريط العلوي Widget _buildInfoColumn( {required IconData icon, required String text, required String label}) { return Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: AppColor.primaryColor), const SizedBox(height: 4), Text(text, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)), Text(label, style: AppStyle.title.copyWith(color: Colors.grey[600], fontSize: 12)), ], ); } // Changed: تم تعديل تصميم ودجت عرض المؤقت ونوع السيارة class _builtTimerAndCarType extends StatelessWidget { const _builtTimerAndCarType(); @override Widget build(BuildContext context) { // نستخدم GetBuilder هنا لضمان تحديث العداد في كل ثانية return GetBuilder(builder: (controller) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // -- نوع السيارة -- Container( decoration: AppStyle.boxDecoration1.copyWith(color: Colors.grey[200]), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Text( controller.carType.tr, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold), ), ), // -- مؤقت الرحلة -- if (controller.carType != 'Comfort' && controller.carType != 'Mishwar Vip' && controller.carType != 'Lady') ...[ const SizedBox(width: 10), Expanded( child: Container( height: 40, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), gradient: LinearGradient( colors: [ controller.remainingTimeTimerRideBegin < 60 ? AppColor.redColor.withOpacity(0.8) : AppColor.greenColor.withOpacity(0.8), controller.remainingTimeTimerRideBegin < 60 ? AppColor.redColor : AppColor.greenColor, ], ), ), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Stack( alignment: Alignment.center, children: [ LinearProgressIndicator( backgroundColor: Colors.transparent, valueColor: AlwaysStoppedAnimation( Colors.white.withOpacity(0.2)), minHeight: 40, // تأكد من أن هذه القيمة بين 0.0 و 1.0 في الكونترولر value: controller.progressTimerRideBegin.toDouble(), ), Text( controller.stringRemainingTimeRideBegin, style: AppStyle.title.copyWith( color: Colors.white, fontWeight: FontWeight.bold), ), ], ), ), ), ) ], ], ); }); } } // Changed: تم تعديل مكان ومظهر دائرة السرعة // غيرنا نوع الإرجاع إلى Widget بدلاً من GetBuilder Widget speedCircle() { // التحقق من السرعة يمكن أن يبقى هنا أو داخل الـ builder // لكن التنبيهات (Vibration/Dialog) يفضل أن تكون داخل الـ builder لتجنب تكرارها أثناء إعادة البناء الخارجية return Positioned( // New: Positioned الآن هي الوالد المباشر (يجب وضع هذه الدالة داخل Stack في الصفحة الرئيسية) bottom: 25, left: 3, child: GetBuilder( builder: (controller) { // التحقق من التنبيهات هنا if (controller.speed > 100) { // نستخدم addPostFrameCallback لضمان عدم استدعاء الـ Dialog أثناء عملية البناء WidgetsBinding.instance.addPostFrameCallback((_) { if (!Get.isDialogOpen!) { // تجنب فتح أكثر من نافذة if (Platform.isIOS) { HapticFeedback.selectionClick(); } else { Vibration.vibrate(duration: 1000); } Get.defaultDialog( barrierDismissible: false, titleStyle: AppStyle.title, title: 'Speed Over'.tr, middleText: 'Please slow down'.tr, middleTextStyle: AppStyle.title, confirm: MyElevatedButton( title: 'I will slow down'.tr, onPressed: () => Get.back(), ), ); } }); } return controller.isRideStarted ? Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white, boxShadow: const [ BoxShadow(blurRadius: 5, color: Colors.black26) ], border: Border.all( width: 4, color: controller.speed > 100 ? Colors.red : AppColor.greenColor, ), ), height: 70, width: 70, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( controller.speed.toStringAsFixed(0), style: AppStyle.number.copyWith(fontSize: 24), ), const Text("km/h", style: TextStyle(fontSize: 10)), ], ), ), ) : const SizedBox(); // إذا لم تبدأ الرحلة نخفي العنصر وهو داخل الـ Positioned }, ), ); } ================================================== FILE PATH: ./lib/views/home/Captin/mapDriverWidgets/sos_connect.dart ================================================== // import 'dart:io'; // import 'package:bubble_head/bubble.dart'; // import 'package:flutter/material.dart'; // import 'package:flutter_font_icons/flutter_font_icons.dart'; // import 'package:get/get.dart'; // import 'package:sefer_driver/constant/info.dart'; // import 'package:sefer_driver/controller/functions/location_controller.dart'; // import 'package:sefer_driver/views/widgets/elevated_btn.dart'; // import 'package:sefer_driver/views/widgets/my_textField.dart'; // import 'package:url_launcher/url_launcher.dart'; // import '../../../../constant/box_name.dart'; // import '../../../../constant/colors.dart'; // import '../../../../constant/style.dart'; // import '../../../../controller/functions/launch.dart'; // import '../../../../controller/home/captin/map_driver_controller.dart'; // import '../../../../main.dart'; // class SosConnect extends StatelessWidget { // const SosConnect({super.key}); // @override // Widget build(BuildContext context) { // return GetBuilder( // builder: (mapDriverController) => mapDriverController.isRideStarted // ? Positioned( // left: 16, // bottom: 16, // child: Card( // elevation: 4, // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(12), // ), // child: SizedBox( // height: 60, // width: 180, // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceAround, // children: [ // IconButton( // onPressed: () { // _handleSosCall(mapDriverController); // }, // icon: const Icon( // Icons.sos_sharp, // size: 32, // color: AppColor.redColor, // ), // tooltip: 'SOS - Call Emergency', // ), // VerticalDivider( // color: Colors.grey[300], // thickness: 1, // ), // IconButton( // onPressed: () { // _handleWhatsApp(mapDriverController); // }, // icon: const Icon( // FontAwesome.whatsapp, // color: AppColor.greenColor, // size: 32, // ), // tooltip: 'SOS - Send WhatsApp Message', // ), // VerticalDivider( // color: Colors.grey[300], // thickness: 1, // ), // IconButton( // onPressed: () { // _handleGoogleMap(mapDriverController); // }, // icon: const Icon( // MaterialCommunityIcons.map_marker_radius, // color: AppColor.primaryColor, // size: 32, // ), // tooltip: 'Google Maps - Navigate', // ), // ], // ), // ), // ), // ) // : const SizedBox(), // ); // } // void _handleSosCall(MapDriverController mapDriverController) { // if (box.read(BoxName.sosPhoneDriver) == null) { // Get.defaultDialog( // title: 'Insert Emergency Number'.tr, // content: Form( // key: mapDriverController.formKey1, // child: MyTextForm( // controller: mapDriverController.sosEmergincyNumberCotroller, // label: 'Emergency Number'.tr, // hint: 'Enter phone number'.tr, // type: TextInputType.phone, // ), // ), // confirm: MyElevatedButton( // title: 'Save'.tr, // onPressed: () { // if (mapDriverController.formKey1.currentState!.validate()) { // box.write(BoxName.sosPhoneDriver, // mapDriverController.sosEmergincyNumberCotroller.text); // Get.back(); // Close the dialog // launchCommunication( // 'phone', box.read(BoxName.sosPhoneDriver), ''); // } // }, // ), // ); // } else { // launchCommunication('phone', box.read(BoxName.sosPhoneDriver), ''); // } // } // void _handleWhatsApp(MapDriverController mapDriverController) { // if (box.read(BoxName.sosPhoneDriver) == null) { // Get.defaultDialog( // title: 'Insert Emergency Number'.tr, // content: Form( // key: mapDriverController.formKey1, // child: MyTextForm( // controller: mapDriverController.sosEmergincyNumberCotroller, // label: 'Emergency Number'.tr, // hint: 'Enter phone number'.tr, // type: TextInputType.phone, // ), // ), // confirm: MyElevatedButton( // title: 'Save'.tr, // onPressed: () { // if (mapDriverController.formKey1.currentState!.validate()) { // box.write(BoxName.sosPhoneDriver, // mapDriverController.sosEmergincyNumberCotroller.text); // Get.back(); // Close the dialog // _sendWhatsAppMessage(mapDriverController); // } // }, // ), // ); // } else { // _sendWhatsAppMessage(mapDriverController); // } // } // void _handleGoogleMap(MapDriverController mapDriverController) { // () async { // if (Platform.isAndroid) { // Bubble().startBubbleHead(sendAppToBackground: true); // } // var startLat = // Get.find().latLngPassengerLocation.latitude; // var startLng = // Get.find().latLngPassengerLocation.longitude; // var endLat = // Get.find().latLngPassengerDestination.latitude; // var endLng = // Get.find().latLngPassengerDestination.longitude; // String url = // 'https://www.google.com/maps/dir/$startLat,$startLng/$endLat,$endLng/&directionsmode=driving'; // if (await canLaunchUrl(Uri.parse(url))) { // await launchUrl(Uri.parse(url)); // } else { // throw 'Could not launch google maps'; // } // }(); // } // void _sendWhatsAppMessage(MapDriverController mapDriverController) { // final sosNumber = box.read(BoxName.sosPhoneDriver); // if (sosNumber != null) { // launchCommunication( // 'whatsapp', // '+2$sosNumber', // Consider international format // "${"Hello, this is Driver".tr} ${box.read(BoxName.nameDriver)}. " // "${"My current location is:".tr} " // "https://www.google.com/maps/place/" // "${Get.find().myLocation.latitude}," // "${Get.find().myLocation.longitude} " // "${"\nI have a trip on".tr} ${AppInformation.appName} " // "${"app with passenger".tr} ${mapDriverController.passengerName}.", // ); // } // } // } import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/style.dart'; import '../../../../controller/firebase/firbase_messge.dart'; import '../../../../controller/firebase/notification_service.dart'; import '../../../../controller/functions/launch.dart'; import '../../../../controller/home/captin/map_driver_controller.dart'; import '../../../../main.dart'; // Changed: إعادة تصميم وتغيير موضع أزرار التواصل والطوارئ class SosConnect extends StatelessWidget { SosConnect({super.key}); final fcm = Get.isRegistered() ? Get.find() : Get.put(FirebaseMessagesController()); @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) { // New: تجميع الأزرار في عمود واحد على الجانب الأيمن return Positioned( bottom: 110, // New: فوق عداد السرعة right: 16, child: Column( children: [ // زر الاتصال بالراكب (يظهر قبل بدء الرحلة) if (!controller.isRideBegin && controller.isPassengerInfoWindow) _buildSocialButton( icon: Icons.phone, color: AppColor.blueColor, tooltip: 'Call Passenger', onPressed: () async { controller.isSocialPressed = true; // await controller.driverCallPassenger(); makePhoneCall(controller.passengerPhone.toString()); }, ), // زر الرسائل للراكب (يظهر قبل بدء الرحلة) if (!controller.isRideBegin && controller.isPassengerInfoWindow) const SizedBox(height: 12), if (!controller.isRideBegin && controller.isPassengerInfoWindow) _buildSocialButton( icon: Icons.message, color: AppColor.greenColor, tooltip: 'Send Message', onPressed: () { // الكود الخاص بنافذة الرسائل السريعة _showMessageOptions(context, controller); }, ), // زر الطوارئ (SOS) (يظهر بعد بدء الرحلة) if (controller.isRideStarted) _buildSocialButton( icon: Icons.sos_sharp, color: AppColor.redColor, tooltip: 'SOS - Call Emergency', onPressed: () => _handleSosCall(controller), ), ], ), ); }, ); } // New: ودجت منفصل لبناء أزرار التواصل Widget _buildSocialButton( {required IconData icon, required Color color, required String tooltip, required VoidCallback onPressed}) { return Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white, boxShadow: [BoxShadow(blurRadius: 5, color: Colors.black26)], ), child: IconButton( icon: Icon(icon, color: color, size: 28), tooltip: tooltip, onPressed: onPressed, ), ); } // الكود الخاص بنافذة إدخال رقم الطوارئ void _handleSosCall(MapDriverController mapDriverController) { if (box.read(BoxName.sosPhoneDriver) == null) { Get.defaultDialog( title: 'Insert Emergency Number'.tr, content: Form( key: mapDriverController.formKey1, child: MyTextForm( controller: mapDriverController.sosEmergincyNumberCotroller, label: 'Emergency Number'.tr, hint: 'Enter phone number'.tr, type: TextInputType.phone, ), ), confirm: MyElevatedButton( title: 'Save'.tr, onPressed: () { if (mapDriverController.formKey1.currentState!.validate()) { box.write(BoxName.sosPhoneDriver, mapDriverController.sosEmergincyNumberCotroller.text); Get.back(); launchCommunication( 'phone', box.read(BoxName.sosPhoneDriver), ''); } }, ), ); } else { launchCommunication('phone', box.read(BoxName.sosPhoneDriver), ''); } } // New: الكود الخاص بنافذة الرسائل السريعة (مستخرج من passenger_info_window.dart) void _showMessageOptions( BuildContext context, MapDriverController controller) { Get.bottomSheet( backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), Padding( padding: const EdgeInsets.all(16.0), child: _buildMessageOptions(controller), ), ); } Widget _buildMessageOptions(MapDriverController controller) { return Column( mainAxisSize: MainAxisSize.min, children: [ Text('Select a quick message'.tr, style: AppStyle.title), const SizedBox(height: 16), _buildMessageTile( text: "Where are you, sir?".tr, onTap: () { // fcm.sendNotificationToDriverMAP( // 'message From Driver', // "Where are you, sir?".tr, // controller.tokenPassenger, // [], // 'ding'); NotificationService.sendNotification( target: controller.tokenPassenger.toString(), title: 'message From Driver'.tr, body: "Where are you, sir?".tr, isTopic: false, // Important: this is a token tone: 'ding', driverList: [], category: 'message From Driver', ); Get.back(); }), _buildMessageTile( text: "I've been trying to reach you but your phone is off.".tr, onTap: () { // fcm.sendNotificationToDriverMAP( // 'message From Driver', // "I've been trying to reach you but your phone is off.".tr, // controller.tokenPassenger, // [], // 'ding'); NotificationService.sendNotification( target: controller.tokenPassenger.toString(), title: 'message From Driver'.tr, body: "I've been trying to reach you but your phone is off.".tr, isTopic: false, // Important: this is a token tone: 'ding', driverList: [], category: 'message From Driver', ); Get.back(); }), const SizedBox(height: 16), Row( children: [ Expanded( child: Form( key: controller.formKey2, child: MyTextForm( controller: controller.messageToPassenger, label: 'Type something'.tr, hint: 'Type something'.tr, type: TextInputType.text, ), ), ), IconButton( onPressed: () { // fcm.sendNotificationToDriverMAP( // 'message From Driver', // controller.messageToPassenger.text, // controller.tokenPassenger, // [], // 'ding'); NotificationService.sendNotification( target: controller.tokenPassenger.toString(), title: 'message From Driver'.tr, body: 'change device'.tr, isTopic: false, // Important: this is a token tone: 'cancel', driverList: [], category: 'message From Driver', ); controller.messageToPassenger.clear(); Get.back(); }, icon: const Icon(Icons.send), ), ], ), ], ); } Widget _buildMessageTile( {required String text, required VoidCallback onTap}) { return InkWell( onTap: onTap, child: Container( width: double.infinity, padding: const EdgeInsets.all(12), margin: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.grey[100], ), child: Text(text, style: AppStyle.title), ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/style.dart'; import '../../../../controller/firebase/notification_service.dart'; import '../../../../main.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; class PassengerInfoWindow extends StatelessWidget { PassengerInfoWindow({super.key}); // Optimization: defining static styles here avoids rebuilding them every frame final TextStyle _labelStyle = AppStyle.title.copyWith(color: Colors.grey[600], fontSize: 13); final TextStyle _valueStyle = AppStyle.title.copyWith(fontWeight: FontWeight.bold, fontSize: 18); @override Widget build(BuildContext context) { // Get safe area top padding (for Notches/Status bars) final double topPadding = MediaQuery.of(context).padding.top; final double topMargin = topPadding + 10; // Safe area + 10px spacing return GetBuilder( builder: (controller) => AnimatedPositioned( duration: const Duration(milliseconds: 400), curve: Curves.easeInOut, // FIX: Use calculated top margin to avoid hiding behind status bar top: controller.isPassengerInfoWindow ? topMargin : -250.0, left: 15.0, right: 15.0, child: Card( // Optimization: Lower elevation slightly for smoother animation on cheap phones elevation: 4, shadowColor: Colors.black.withOpacity(0.2), color: Colors.white, surfaceTintColor: Colors.white, // Fix for Material 3 tinting shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTopInfoRow(controller), const Divider(height: 16), if (!controller.isRideBegin) _buildActionButtons(controller), // Optimization: Only render linear indicator if needed if (controller.remainingTimeInPassengerLocatioWait < 300 && controller.remainingTimeInPassengerLocatioWait != 0 && !controller.isRideBegin) ...[ const SizedBox(height: 10), _buildWaitingIndicator(controller), ], if (controller.isdriverWaitTimeEnd && !controller.isRideBegin) ...[ const SizedBox(height: 10), _buildCancelAfterWaitButton(controller), ] ], ), ), ), ), ); } Widget _buildTopInfoRow(MapDriverController controller) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, // Align top children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Go to passenger:'.tr, style: _labelStyle), const SizedBox(height: 2), Text( controller.passengerName ?? 'loading...', style: _valueStyle, maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), const SizedBox(width: 10), // Spacing between name and chips Column( // Changed to Column for better layout on small screens crossAxisAlignment: CrossAxisAlignment.end, children: [ _buildInfoChip(Icons.map_outlined, '${controller.distance} km'), const SizedBox(height: 6), // Vertical spacing _buildInfoChip( Icons.timer_outlined, controller.hours > 1 ? '${controller.hours}h ${controller.minutes}m' : '${controller.minutes}m', ), ], ), ], ); } Widget _buildInfoChip(IconData icon, String text) { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: AppColor.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: AppColor.primaryColor, size: 14), // Smaller icon const SizedBox(width: 6), Text( text, style: TextStyle( color: AppColor.primaryColor, fontWeight: FontWeight.bold, fontSize: 12 // Slightly smaller font for chips ), ), ], ), ); } Widget _buildActionButtons(MapDriverController controller) { return Row( children: [ if (controller.isArrivedSend) Expanded( flex: 1, child: SizedBox( height: 45, // Fixed height for consistency child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColor.yellowColor, foregroundColor: Colors.black, padding: EdgeInsets.zero, // Reduce padding to fit text shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), onPressed: () async { // LOGIC FIX: Check distance FIRST double distance = await controller .calculateDistanceBetweenDriverAndPassengerLocation(); if (distance < 140) { // Only draw route and send notif if close enough controller.getRoute( origin: controller.latLngPassengerLocation, destination: controller.latLngPassengerDestination, routeColor: Colors.blue); NotificationService.sendNotification( target: controller.tokenPassenger.toString(), title: 'Hi ,I Arrive your site'.tr, body: 'I Arrive at your site'.tr, isTopic: false, tone: 'ding', driverList: [], category: 'Hi ,I Arrive your site', ); controller.startTimerToShowDriverWaitPassengerDuration(); controller.isArrivedSend = false; } else { MyDialog().getDialog( 'You are not near'.tr, // Shortened title 'Please go to the pickup location exactly'.tr, () => Get.back()); } }, // Using Row instead of .icon constructor for better control child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.location_on, size: 16), const SizedBox(width: 4), Flexible( child: Text('I Arrive'.tr, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12))), ], ), ), ), ), if (controller.isArrivedSend) const SizedBox(width: 8), Expanded( flex: 2, // Give "Start" button more space child: SizedBox( height: 45, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), onPressed: () { MyDialog().getDialog( "Is the Passenger in your Car?".tr, "Don't start trip if passenger not in your car".tr, () async { await controller.startRideFromDriver(); Get.back(); }, ); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.play_arrow_rounded, size: 22), const SizedBox(width: 6), Flexible( child: Text('Start the Ride'.tr, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold))), ], ), ), ), ), ], ); } Widget _buildWaitingIndicator(MapDriverController controller) { return Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(10), child: LinearProgressIndicator( backgroundColor: AppColor.greyColor.withOpacity(0.2), // Ternary for color is fine color: controller.remainingTimeInPassengerLocatioWait < 60 ? AppColor.redColor : AppColor.greenColor, minHeight: 8, // Thinner looks more modern value: controller.progressInPassengerLocationFromDriver.toDouble(), ), ), const SizedBox(height: 4), Text( "${'Waiting'.tr}: ${controller.stringRemainingTimeWaitingPassenger}", style: AppStyle.title.copyWith( color: Colors.grey[700], fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ); } Widget _buildCancelAfterWaitButton(MapDriverController controller) { return MyElevatedButton( title: 'Cancel Trip & Get Cost'.tr, // Shortened text kolor: AppColor.gold, onPressed: () { MyDialog().getDialog('Are you sure to cancel?'.tr, '', () async { NotificationService.sendNotification( target: controller.tokenPassenger.toString(), title: 'Driver Cancelled Your Trip'.tr, body: 'You will need to pay the cost...', isTopic: false, tone: 'cancel', driverList: [], category: 'Driver Cancelled Your Trip', ); box.write(BoxName.rideStatus, 'Cancel'); await controller.addWaitingTimeCostFromPassengerToDriverWallet(); controller.isdriverWaitTimeEnd = false; Get.back(); }); }, ); } } ================================================== FILE PATH: ./lib/views/home/Captin/mapDriverWidgets/google_map_app.dart ================================================== import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; class GoogleMapApp extends StatelessWidget { const GoogleMapApp({super.key}); @override Widget build(BuildContext context) { return GetBuilder( builder: (mapDriverController) => mapDriverController.isRideStarted ? Positioned( right: 3, bottom: 20, child: Container( decoration: AppStyle.boxDecoration, child: IconButton( onPressed: () async { var startLat = Get.find() .latLngPassengerLocation .latitude; var startLng = Get.find() .latLngPassengerLocation .longitude; var endLat = Get.find() .latLngPassengerDestination .latitude; var endLng = Get.find() .latLngPassengerDestination .longitude; String url = 'https://www.google.com/maps/dir/$startLat,$startLng/$endLat,$endLng/&directionsmode=driving'; if (await canLaunchUrl(Uri.parse(url))) { await launchUrl(Uri.parse(url)); } else { throw 'Could not launch google maps'; } }, icon: const Icon( MaterialCommunityIcons.map_marker_radius, size: 45, color: AppColor.blueColor, ), )), ) : const SizedBox()); } } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/drawer_captain.dart ================================================== import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/upload_image.dart'; import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/device_compatibility_page.dart'; import 'package:sefer_driver/main.dart'; // استيراد الصفحات الأخرى... تأكد من صحة المسارات import 'package:sefer_driver/views/Rate/rate_app_page.dart'; import 'package:sefer_driver/views/auth/captin/contact_us_page.dart'; import 'package:sefer_driver/views/auth/captin/invite_driver_screen.dart'; import 'package:sefer_driver/views/notification/available_rides_page.dart'; import 'package:sefer_driver/views/auth/captin/logout_captain.dart'; import 'package:sefer_driver/views/home/Captin/history/history_captain.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/help_captain.dart'; import 'package:sefer_driver/views/home/Captin/About Us/settings_captain.dart'; import 'package:sefer_driver/views/home/my_wallet/walet_captain.dart'; import 'package:sefer_driver/views/home/profile/profile_captain.dart'; import 'package:sefer_driver/views/notification/notification_captain.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../../constant/colors.dart'; import '../About Us/video_page.dart'; import '../assurance_health_page.dart'; import '../maintain_center_page.dart'; // 1. إنشاء Class لتعريف بيانات كل عنصر في القائمة class DrawerItem { final String title; final IconData icon; final Color color; final VoidCallback onTap; DrawerItem( {required this.title, required this.icon, required this.color, required this.onTap}); } // --- الويدجت الرئيسية للقائمة الجانبية --- class AppDrawer extends StatelessWidget { AppDrawer({super.key}); final ImageController imageController = Get.put(ImageController()); // 2. تعريف بيانات القائمة بشكل مركزي ومنظم final List drawerItems = [ DrawerItem( title: 'Balance'.tr, icon: Icons.account_balance_wallet, color: Colors.green, onTap: () => Get.to(() => WalletCaptainRefactored())), DrawerItem( title: 'Profile'.tr, icon: Icons.person, color: Colors.blue, onTap: () => Get.to(() => ProfileCaptain())), DrawerItem( title: 'History of Trip'.tr, icon: Icons.history, color: Colors.orange, onTap: () => Get.to(() => const HistoryCaptain())), DrawerItem( title: 'Available for rides'.tr, icon: Icons.drive_eta, color: Colors.teal, onTap: () => Get.to(() => const AvailableRidesPage())), DrawerItem( title: 'Notifications'.tr, icon: Icons.notifications, color: Colors.purple, onTap: () => Get.to(() => const NotificationCaptain())), DrawerItem( title: 'Helping Center'.tr, icon: Icons.help_center, color: Colors.cyan, onTap: () => Get.to(() => HelpCaptain())), DrawerItem( title: 'Share App'.tr, icon: Icons.share, color: Colors.indigo, onTap: () => Get.to(() => InviteScreen())), // DrawerItem( // title: 'Maintenance Center'.tr, // icon: Icons.build, // color: Colors.brown, // onTap: () => Get.to(() => MaintainCenterPage())), // DrawerItem( // title: 'Health Insurance'.tr, // icon: Icons.favorite, // color: Colors.pink, // onTap: () => Get.to(() => AssuranceHealthPage())), DrawerItem( title: 'Contact Us'.tr, icon: Icons.email, color: Colors.blueGrey, onTap: () => Get.to(() => ContactUsPage())), DrawerItem( title: 'Videos Tutorials'.tr, icon: Icons.video_library, color: Colors.redAccent, onTap: () => Get.to(() => VideoListPage())), DrawerItem( title: 'Rate Our App'.tr, icon: Icons.star, color: Colors.amber, onTap: () => Get.to(() => RatingScreen())), DrawerItem( title: 'Is device compatible'.tr, icon: Icons.memory, color: Colors.greenAccent, onTap: () => Get.to(() => DeviceCompatibilityPage())), DrawerItem( title: 'Privacy Policy'.tr, icon: Icons.memory, color: Colors.greenAccent, onTap: () => launchUrl(Uri.parse('${AppLink.server}/privacy_policy.php'))), DrawerItem( title: 'Settings'.tr, icon: Icons.settings, color: Colors.grey.shade600, onTap: () => Get.to(() => const SettingsCaptain())), ]; @override Widget build(BuildContext context) { return Drawer( child: Container( color: Theme.of(context).scaffoldBackgroundColor, child: Column( children: [ // --- الجزء العلوي من القائمة (بيانات المستخدم) --- UserHeader(), // استخدمنا الويدجت المحسنة بالأسفل // --- قائمة العناصر المتحركة --- Expanded( child: AnimationLimiter( child: ListView.builder( padding: const EdgeInsets.all(8.0), itemCount: drawerItems.length + 1, // +1 لزر تسجيل الخروج itemBuilder: (BuildContext context, int index) { // --- زر تسجيل الخروج في النهاية --- if (index == drawerItems.length) { return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: _DrawerItemTile( item: DrawerItem( title: 'Sign Out'.tr, icon: Icons.logout, color: Colors.red, onTap: () => Get.to(() => const LogoutCaptain())), ), ), ), ); } // --- بقية العناصر --- final item = drawerItems[index]; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: _DrawerItemTile(item: item), ), ), ); }, ), ), ), ], ), ), ); } } // --- ويدجت خاصة بكل عنصر في القائمة --- class _DrawerItemTile extends StatelessWidget { final DrawerItem item; const _DrawerItemTile({required this.item}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: item.color.withOpacity(0.1), shape: BoxShape.circle, ), child: Icon(item.icon, color: item.color, size: 24), ), title: Text( item.title, style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.w500), ), onTap: () { Get.back(); // لإغلاق القائمة عند الضغط Future.delayed(const Duration(milliseconds: 250), () { item.onTap(); // الانتقال للصفحة بعد تأخير بسيط لإظهار الأنيميشن }); }, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), splashColor: item.color.withOpacity(0.2), ), ); } } // --- ويدجت محسنة للجزء العلوي من القائمة --- // ... (الاستيرادات السابقة تبقى كما هي) // --- تم تعديل UserHeader لإضافة التحقق من الصورة --- class UserHeader extends StatelessWidget { UserHeader({super.key}); final ImageController imageController = Get.find(); final HomeCaptainController homeCaptainController = Get.find(); // دالة لإظهار التنبيه void _showUploadPhotoDialog( BuildContext context, ImageController controller) { // نستخدم addPostFrameCallback لضمان عدم ظهور الخطأ أثناء بناء الواجهة WidgetsBinding.instance.addPostFrameCallback((_) { // نتأكد ألا يكون هناك dialog مفتوح بالفعل لتجنب التكرار if (Get.isDialogOpen == true) return; Get.defaultDialog( title: "Profile Photo Required".tr, titleStyle: const TextStyle(color: Colors.red, fontWeight: FontWeight.bold), middleText: "Please upload a clear photo of your face to be identified by passengers." .tr, barrierDismissible: false, // منع الإغلاق بالضغط خارج النافذة radius: 15, contentPadding: const EdgeInsets.all(20), confirm: ElevatedButton.icon( onPressed: () { Get.back(); // إغلاق النافذة الحالية // فتح الكاميرا فوراً controller.choosImagePicture( AppLink.uploadImagePortrate, 'portrait'); }, icon: const Icon(Icons.camera_alt, color: Colors.white), label: Text("Take Photo Now".tr, style: const TextStyle(color: Colors.white)), style: ElevatedButton.styleFrom( backgroundColor: AppColor .primaryColor, // تأكد من وجود هذا اللون أو استبدله بـ Colors.blue padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), ), ), cancel: TextButton( onPressed: () => Get.back(), child: Text("Later".tr, style: const TextStyle(color: Colors.grey)), ), ); }); } @override Widget build(BuildContext context) { return UserAccountsDrawerHeader( accountName: Text( box.read(BoxName.nameDriver).toString(), style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 18, shadows: [Shadow(blurRadius: 2, color: Colors.black26)]), ), accountEmail: box.read(BoxName.emailDriver).toString().contains('intaleqapp') ? Text('Your email not updated yet'.tr) : Text(box.read(BoxName.emailDriver)), currentAccountPicture: GetBuilder( builder: (controller) => Stack( clipBehavior: Clip.none, children: [ Container( decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), boxShadow: [ BoxShadow(color: Colors.black.withOpacity(0.3), blurRadius: 5) ], ), child: controller.isloading ? const CircularProgressIndicator(color: Colors.white) : CircleAvatar( // محاولة تحميل الصورة backgroundImage: NetworkImage( '${AppLink.server}/portrate_captain_image/${box.read(BoxName.driverID)}.jpg'), // [تعديل هام]: في حال فشل تحميل الصورة (غير موجودة) onBackgroundImageError: (exception, stackTrace) { // طباعة الخطأ في الكونسول للتوضيح debugPrint( "Profile image not found or error loading: $exception"); // استدعاء نافذة التنبيه _showUploadPhotoDialog(context, controller); }, // أيقونة بديلة تظهر في الخلفية إذا لم تكن الصورة موجودة backgroundColor: Colors.grey.shade300, child: const Icon(Icons.person, size: 40, color: Colors.white), ), ), Positioned( bottom: -5, right: -5, child: InkWell( onTap: () => controller.choosImagePicture( AppLink.uploadImagePortrate, 'portrait'), child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: Icon(Icons.camera_alt, color: Theme.of(context).primaryColor, size: 18), ), ), ), ], ), ), otherAccountsPictures: [ Row( mainAxisSize: MainAxisSize.min, children: [ Text( homeCaptainController.rating.toString(), style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), const SizedBox(width: 4), const Icon(Icons.star, color: Colors.amber, size: 20), ], ), ], decoration: BoxDecoration( gradient: LinearGradient( colors: [Theme.of(context).primaryColor, Colors.blue.shade700], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/help_details_replay_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../../controller/functions/encrypt_decrypt.dart'; import '../../../../controller/home/captin/help/help_controller.dart'; import '../../../widgets/my_scafold.dart'; class HelpDetailsReplayPage extends StatelessWidget { const HelpDetailsReplayPage({super.key}); @override Widget build(BuildContext context) { Get.find(); return GetBuilder( builder: (helpController) => MyScafolld( title: 'Help Details'.tr, body: [ helpController.isLoading ? const MyCircularProgressIndicator() : Column( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Card( elevation: 3, child: Container( width: Get.width * .66, color: Colors.transparent, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( helpController.qustion, style: AppStyle.title, ), ), ), ), ]), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Card( elevation: 3, child: Container( color: Colors.transparent, width: Get.width * .66, child: Padding( padding: const EdgeInsets.all(8.0), child: helpController.status == 'not yet' || EncryptionHelper.instance .decryptData(helpController .helpQuestionRepleyDate[ 'message']['replay']) .toString() == 'not yet' ? Text( 'No Response yet.'.tr, style: AppStyle.title, ) : Text( EncryptionHelper.instance .decryptData(helpController .helpQuestionRepleyDate[ 'message']['replay']) .toString(), style: AppStyle.title, ), ), ), ), ]), ], ) ], isleading: true, )); } } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/driver_call_page.dart ================================================== // import 'dart:async'; // import 'package:SEFER/constant/box_name.dart'; // import 'package:SEFER/main.dart'; // import 'package:SEFER/views/widgets/my_scafold.dart'; // import 'package:flutter/material.dart'; // import 'package:get/get.dart'; // import 'package:permission_handler/permission_handler.dart'; // import 'package:agora_rtc_engine/agora_rtc_engine.dart'; // import '../../../../constant/api_key.dart'; // import '../../../../controller/functions/crud.dart'; // String appId = AK.agoraAppId; // class DriverCallPage extends StatefulWidget { // const DriverCallPage({super.key}); // @override // State createState() => _DriverCallPageState(); // } // class _DriverCallPageState extends State { // String channelName = ''; // String token = ''; // // "00612994c6e707543e68d5638894d04f989IAAlydoFEC3ZeZkeUwl0dSswZTX8n+xyZR8PBWdwXFV6t6MLiA8AAAAAEACCHD/gn3TUZQEAAQAAAAAA"; // // int uid = int.parse(box.read(BoxName.phoneDriver)); // uid of the local user // int uid = 0; // int? _remoteUid; // uid of the remote user // bool _isJoined = false; // Indicates if the local user has joined the channel // late RtcEngine agoraEngine; // Agora engine instance // final GlobalKey scaffoldMessengerKey = // GlobalKey(); // Global key to access the scaffold // showMessage(String message) { // scaffoldMessengerKey.currentState?.showSnackBar(SnackBar( // content: Text(message), // )); // } // initAgora() async { // await fetchToken(); // await setupVoiceSDKEngine(); // } // fetchToken() async { // var res = await CRUD() // .getAgoraToken(channelName: channelName, uid: uid.toString()); // setState(() { // token = res; // }); // } // @override // void initState() { // super.initState(); // _remoteUid = box.read(BoxName.phone) != null // ? int.parse(box.read(BoxName.phone)) // : int.parse(box.read(BoxName.phoneDriver)); // uid = box.read(BoxName.phoneDriver) != null // ? int.parse(box.read(BoxName.phoneDriver)) // : int.parse(box.read(BoxName.phone)); // // Set up an instance of Agora engine // initAgora(); // } // Future setupVoiceSDKEngine() async { // // retrieve or request microphone permission // await [Permission.microphone].request(); // //create an instance of the Agora engine // agoraEngine = createAgoraRtcEngine(); // await agoraEngine.initialize(RtcEngineContext(appId: AK.agoraAppId)); // // Register the event handler // agoraEngine.registerEventHandler( // RtcEngineEventHandler( // onJoinChannelSuccess: (RtcConnection connection, int elapsed) { // showMessage( // "Local user uid:${connection.localUid} joined the channel"); // setState(() { // _isJoined = true; // }); // }, // onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) { // showMessage("Remote user uid:$remoteUid joined the channel"); // setState(() { // _remoteUid = remoteUid; // }); // }, // onUserOffline: (RtcConnection connection, int remoteUid, // UserOfflineReasonType reason) { // showMessage("Remote user uid:$remoteUid left the channel"); // setState(() { // _remoteUid = null; // }); // }, // ), // ); // } // void join() async { // // Set channel options including the client role and channel profile // ChannelMediaOptions options = const ChannelMediaOptions( // clientRoleType: ClientRoleType.clientRoleBroadcaster, // channelProfile: ChannelProfileType.channelProfileCommunication, // ); // await agoraEngine.joinChannel( // token: token, // channelId: channelName, // options: options, // uid: uid, // ); // } // //https://console.agora.io/invite?sign=5e9e22d06f22caeeada9954c9e908572%253A5ba8aed978a35eab5a5113742502ded2a41478b2a81cb19c71a30776e125b58a // void leave() { // setState(() { // _isJoined = false; // _remoteUid = null; // }); // agoraEngine.leaveChannel(); // } // // Clean up the resources when you leave // @override // void dispose() async { // await agoraEngine.leaveChannel(); // super.dispose(); // } // // Build UI // @override // Widget build(BuildContext context) { // return MaterialApp( // scaffoldMessengerKey: scaffoldMessengerKey, // home: MyScafolld( // // appBar: AppBar( // // title: const Text('Get started with Voice Calling'), // // ), // title: 'Voice Calling'.tr, // isleading: true, // body: [ // ListView( // padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), // children: [ // // Status text // Container(height: 40, child: Center(child: _status())), // // Button Row // Row( // children: [ // Expanded( // child: ElevatedButton( // child: const Text("Join"), // onPressed: () => {join()}, // ), // ), // const SizedBox(width: 10), // Expanded( // child: ElevatedButton( // child: const Text("Leave"), // onPressed: () => {leave()}, // ), // ), // ], // ), // ], // ), // ]), // ); // } // Widget _status() { // String statusText; // if (!_isJoined) // statusText = 'Join a channel'; // else if (_remoteUid == null) // statusText = 'Waiting for a remote user to join...'; // else // statusText = 'Connected to remote user, uid:$_remoteUid'; // return Text( // statusText, // ); // } // } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/help_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/captin/help/help_controller.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/help_details_replay_page.dart'; import 'package:flutter/cupertino.dart'; import '../../../../controller/functions/encrypt_decrypt.dart'; class HelpCaptain extends StatelessWidget { HelpCaptain({super.key}); @override Widget build(BuildContext context) { Get.put(HelpController()); return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text( 'Helping Page'.tr, style: const TextStyle(fontWeight: FontWeight.bold), ), leading: CupertinoButton( padding: EdgeInsets.zero, onPressed: () => Navigator.pop(context), child: const Icon(CupertinoIcons.back), ), ), child: SafeArea( child: Padding( padding: const EdgeInsets.all( 20.0), // Increased padding around the content child: ListView( // crossAxisAlignment: // CrossAxisAlignment.stretch, // Stretch children to full width children: [ Container( padding: const EdgeInsets.all(18.0), // Slightly increased padding decoration: BoxDecoration( color: CupertinoTheme.of(context).brightness == Brightness.light ? CupertinoColors.systemGrey6 : CupertinoColors.darkBackgroundGray, borderRadius: BorderRadius.circular(15.0), // More rounded corners ), child: Text( 'If you need any help or have questions, this is the right place to do that. You are welcome!' .tr, style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( fontSize: 16, // Slightly larger font size color: CupertinoColors.label.resolveFrom( context), // Ensure text color adapts to theme ), textAlign: TextAlign.center, ), ), const SizedBox(height: 20), CupertinoFormSection.insetGrouped( // Using CupertinoFormSection for better styling header: Text('Submit Your Question'.tr), margin: EdgeInsets.zero, children: [ GetBuilder( builder: (helpController) => Form( key: helpController.formKey, child: CupertinoTextFormFieldRow( controller: helpController.helpQuestionController, placeholder: 'Enter your Question here'.tr, autovalidateMode: AutovalidateMode.onUserInteraction, validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your question'.tr; } return null; }, prefix: const Icon(CupertinoIcons .question_circle), // Added a prefix icon ), ), ), Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 10.0), child: GetBuilder( builder: (helpController) => helpController.isLoading ? const CupertinoActivityIndicator() : CupertinoButton.filled( onPressed: () { if (helpController.formKey.currentState! .validate()) { helpController.addHelpQuestion(); helpController.helpQuestionController .clear(); // Clear the text field } }, child: Text('Submit Question'.tr), ), ), ), ], ), const SizedBox(height: 20), Text( 'Your Questions'.tr, style: CupertinoTheme.of(context) .textTheme .navTitleTextStyle .copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 10), Expanded( child: GetBuilder( builder: (helpController) => CupertinoListSection.insetGrouped( margin: EdgeInsets.zero, children: helpController.helpQuestionDate['message'] != null ? List.generate( helpController.helpQuestionDate['message'].length, (index) { var list = helpController .helpQuestionDate['message'][index]; return CupertinoListTile( title: Text( EncryptionHelper.instance .decryptData(list['helpQuestion']), overflow: TextOverflow.ellipsis, ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Text( list['datecreated'], style: CupertinoTheme.of(context) .textTheme .tabLabelTextStyle, ), const Icon(CupertinoIcons.chevron_forward), ], ), onTap: () { helpController.getIndex( int.parse(EncryptionHelper.instance .decryptData(list['id'])), EncryptionHelper.instance .decryptData(list['helpQuestion'])); helpController .getHelpRepley(list['id'].toString()); Get.to(() => const HelpDetailsReplayPage()); }, ); }, ) : [ Center( child: Text('No questions asked yet.'.tr), ), ], ), ), ), ], ), ), ), ); } } // class HelpCaptain extends StatelessWidget { // HelpCaptain({super.key}); // @override // Widget build(BuildContext context) { // Get.put(HelpController()); // return CupertinoPageScaffold( // navigationBar: CupertinoNavigationBar( // middle: Text('Helping Page'.tr), // leading: CupertinoButton( // padding: EdgeInsets.zero, // child: Icon(CupertinoIcons.back), // onPressed: () => Navigator.pop(context), // ), // ), // child: SafeArea( // child: Padding( // padding: const EdgeInsets.all(16.0), // child: Column( // children: [ // Padding( // padding: const EdgeInsets.symmetric(vertical: 12.0), // child: Container( // padding: const EdgeInsets.all(16.0), // decoration: BoxDecoration( // borderRadius: BorderRadius.circular(12.0), // border: Border.all( // color: CupertinoColors.systemGrey2, // ), // ), // child: Text( // 'If you need any help or have questions, this is the right place to do that. You are welcome!' // .tr, // style: CupertinoTheme.of(context).textTheme.textStyle, // textAlign: TextAlign.center, // ), // ), // ), // Card( // elevation: 3, // color: CupertinoColors.systemGrey6, // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(12.0), // ), // child: Padding( // padding: const EdgeInsets.all(16.0), // child: GetBuilder( // builder: (helpController) => Form( // key: helpController.formKey, // child: Column( // children: [ // CupertinoTextField( // controller: helpController.helpQuestionController, // placeholder: 'Enter your Question here'.tr, // decoration: BoxDecoration( // borderRadius: BorderRadius.circular(12), // border: Border.all( // color: CupertinoColors.systemGrey, // ), // ), // padding: const EdgeInsets.all(16), // clearButtonMode: OverlayVisibilityMode.editing, // ), // const SizedBox(height: 20), // helpController.isLoading // ? const CupertinoActivityIndicator() // : CupertinoButton.filled( // onPressed: () { // if (helpController.formKey.currentState! // .validate()) { // helpController.addHelpQuestion(); // // Clear the feedback form // helpController.formKey.currentState! // .reset(); // } // }, // child: Text('Submit Question'.tr), // ), // ], // ), // ), // ), // ), // ), // const SizedBox(height: 20), // Expanded( // child: GetBuilder( // builder: (helpController) => Padding( // padding: const EdgeInsets.all(10), // child: Container( // decoration: BoxDecoration( // border: Border.all( // color: CupertinoColors.systemGrey2, // ), // borderRadius: BorderRadius.circular(12.0), // ), // child: ListView.builder( // itemCount: helpController.helpQuestionDate['message'] != // null // ? helpController.helpQuestionDate['message'].length // : 0, // itemBuilder: (BuildContext context, int index) { // var list = // helpController.helpQuestionDate['message'][index]; // return Padding( // padding: const EdgeInsets.all(3), // child: Container( // padding: const EdgeInsets.symmetric( // vertical: 12, horizontal: 16), // decoration: BoxDecoration( // border: Border.all( // color: CupertinoColors.activeGreen, // width: 2, // ), // borderRadius: BorderRadius.circular(12), // ), // child: GestureDetector( // onTap: () { // helpController.getIndex( // list['id'], list['helpQuestion']); // helpController // .getHelpRepley(list['id'].toString()); // Get.to(() => const HelpDetailsReplayPage()); // }, // child: Row( // mainAxisAlignment: // MainAxisAlignment.spaceBetween, // children: [ // Expanded( // child: Text( // list['helpQuestion'], // style: CupertinoTheme.of(context) // .textTheme // .textStyle, // overflow: TextOverflow.ellipsis, // ), // ), // Text( // list['datecreated'], // style: CupertinoTheme.of(context) // .textTheme // .tabLabelTextStyle, // ), // ], // ), // ), // ), // ); // }, // ), // ), // ), // ), // ), // ], // ), // ), // ), // ); // } // } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/home_captin.dart ================================================== import 'dart:io'; import 'dart:ui'; import 'package:bubble_head/bubble.dart'; // import 'package:google_maps_flutter/google_maps_flutter.dart'; // import 'package:flutter_map/flutter_map.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; // import 'package:latlong2/latlong.dart' as latlng; // لإحداثيات العرض import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/drawer_captain.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/info.dart'; import '../../../../constant/style.dart'; import '../../../../controller/functions/location_controller.dart'; import '../../../../controller/functions/overlay_permisssion.dart'; import '../../../../controller/functions/package_info.dart'; import '../../../../controller/home/captin/home_captain_controller.dart'; import '../../../../controller/home/captin/map_driver_controller.dart'; import '../../../../main.dart'; import '../../../notification/available_rides_page.dart'; import '../../../widgets/circle_container.dart'; import '../driver_map_page.dart'; import 'widget/connect.dart'; import 'widget/left_menu_map_captain.dart'; // ================================================================== // Redesigned Main Widget (V3) // ================================================================== class HomeCaptain extends StatelessWidget { HomeCaptain({super.key}); final LocationController locationController = Get.put(LocationController(), permanent: true); final HomeCaptainController homeCaptainController = Get.put(HomeCaptainController()); @override Widget build(BuildContext context) { // Initial calls remain the same. // Get.put(HomeCaptainController()); WidgetsBinding.instance.addPostFrameCallback((_) async { closeOverlayIfFound(); checkForUpdate(context); getPermissionOverlay(); showDriverGiftClaim(context); checkForAppliedRide(context); }); // The stack is now even simpler. return Scaffold( appBar: const _HomeAppBar(), drawer: AppDrawer(), body: SafeArea( child: Stack( children: [ // 1. The Map View is the base layer. const _MapView(), // 2. The new floating "Status Pod" at the bottom. const _StatusPodOverlay(), FloatingActionButtons(), // This widget from the original code remains. leftMainMenuCaptainIcons(), ], ), ), ); } } // ================================================================== // Redesigned Helper Widgets (V3) // ================================================================== /// 1. The AppBar now contains the map actions in a PopupMenuButton. class _HomeAppBar extends StatelessWidget implements PreferredSizeWidget { const _HomeAppBar(); @override Widget build(BuildContext context) { final homeCaptainController = Get.find(); return AppBar( backgroundColor: Colors.white, elevation: 1, shadowColor: Colors.black.withOpacity(0.1), title: Row( children: [ Image.asset( 'assets/images/logo.gif', height: 35, ), const SizedBox(width: 10), Text( AppInformation.appName.split(' ')[0].toString().tr, style: AppStyle.title.copyWith( fontSize: 24, fontWeight: FontWeight.bold, color: AppColor.blueColor, ), ), ], ), actions: [ // Refuse count indicator Padding( padding: const EdgeInsets.only(right: 8.0), child: Center( child: MyCircleContainer( child: Text( homeCaptainController.countRefuse.toString(), style: AppStyle.title.copyWith(fontWeight: FontWeight.bold), ), ), ), ), // The new PopupMenuButton for all map and ride actions. Container( margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), spreadRadius: 1, blurRadius: 4, ), ], ), child: Row( children: [ _MapControlButton( iconColor: Colors.blue, icon: Icons.satellite_alt, tooltip: 'Change Map Type'.tr, onPressed: homeCaptainController.changeMapType, ), // _MapControlButton( // iconColor: Colors.blue, // icon: Icons.streetview_sharp, // tooltip: 'Toggle Traffic'.tr, // onPressed: homeCaptainController.changeMapTraffic, // ), GetBuilder( builder: (controller) { return _MapControlButton( // تغيير الأيقونة واللون بناءً على الحالة icon: Icons.local_fire_department, iconColor: controller.isHeatmapVisible ? Colors.orange : Colors.grey, tooltip: 'Show Heatmap'.tr, onPressed: controller.toggleHeatmap, ); }, ), _MapControlButton( iconColor: Colors.blue, icon: Icons.my_location, // Changed for clarity tooltip: 'Center on Me'.tr, onPressed: () { if (homeCaptainController.mapHomeCaptainController != null) { homeCaptainController.mapHomeCaptainController! .animateCamera(CameraUpdate.newLatLngZoom( Get.find().myLocation, 17.5, )); } }, ), ], ), ), ], ); } PopupMenuItem _buildPopupMenuItem({ required String value, IconData? icon, Widget? iconWidget, required String text, Color? iconColor, }) { return PopupMenuItem( value: value, child: Row( children: [ iconWidget ?? Icon(icon, color: iconColor ?? Colors.grey.shade600), const SizedBox(width: 16), Text(text), ], ), ); } @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); } /// 2. The Map View is unchanged functionally. class _MapView extends StatelessWidget { const _MapView(); @override Widget build(BuildContext context) { // جلب الكونترولر الرئيسي final homeController = Get.find(); return GetBuilder( builder: (controller) { if (controller.isLoading) { return const MyCircularProgressIndicator(); } // --- هذا هو التعديل --- // هذا الـ Builder يستمع إلى تحديثات الموقع return GetBuilder( builder: (locationController) { // if (homeController.mapHomeCaptainController != null && // homeController.isActive) { // homeController.mapHomeCaptainController!.animateCamera( // CameraUpdate.newCameraPosition( // CameraPosition( // target: locationController.myLocation, // الموقع الجديد // zoom: 17.5, // تقريب لمتابعة السائق // tilt: 50.0, // زاوية رؤية 3D // bearing: locationController.heading, // اتجاه السيارة // ), // ), // ); // } // --- نهاية الكود الجديد --- // إرجاع الخريطة return GoogleMap( padding: const EdgeInsets.only(bottom: 110, top: 300), fortyFiveDegreeImageryEnabled: true, onMapCreated: controller.onMapCreated, // onCameraMove: controller.onCameraMove, minMaxZoomPreference: const MinMaxZoomPreference(6, 18), initialCameraPosition: CameraPosition( target: locationController.myLocation, zoom: 15, ), // --- تم حذف onCameraMove الخاطئ --- // === إضافة الطبقة الحرارية هنا === polygons: controller.heatmapPolygons, // = markers: { Marker( markerId: MarkerId('MyLocation'.tr), position: locationController.myLocation, // يتم تحديثه من هنا rotation: locationController.heading, // يتم تحديثه من هنا flat: true, anchor: const Offset(0.5, 0.5), icon: controller.carIcon, ) }, mapType: controller.mapType ? MapType.satellite : MapType.terrain, myLocationButtonEnabled: false, myLocationEnabled: false, trafficEnabled: controller.mapTrafficON, buildingsEnabled: false, mapToolbarEnabled: false, compassEnabled: false, zoomControlsEnabled: false, ); // --- الكود الجديد --- // // تحويل الإحداثيات من جوجل (إذا كنت لا تزال تستخدمها) إلى latlong2 // final latlng.LatLng currentCarPosition = latlng.LatLng( // locationController.myLocation.latitude, // locationController.myLocation.longitude); // return FlutterMap( // // 1. تمرير الـ Controller الذي أنشأناه في الخطوة 2 // mapController: homeController.mapController, // options: MapOptions( // // 2. هذا بديل initialCameraPosition // initialCenter: currentCarPosition, // initialZoom: 15, // // هذا بديل padding // // (ملاحظة: flutter_map لا يدعم padding مباشرة، قد تحتاج لتعديل الواجهة // // أو استخدام خاصية nonRotatedChildren لبدائل أخرى) // // هذا بديل minMaxZoomPreference // minZoom: 12, // maxZoom: 16, onMapReady: homeController.onMapReady, // ), // // 3. الخرائط في flutter_map عبارة عن "طبقات" (Layers) // children: [ // // --- الطبقة الأولى: الخريطة الأساسية (OSM) --- // TileLayer( // urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', // userAgentPackageName: // 'com.your.app.name', // هام: ضع اسم تطبيقك هنا // ), // // --- (اختياري) طبقة القمر الصناعي بناءً على MapType --- // if (controller.mapType) // إذا كنت لا تزال تستخدم mapType // // TileLayer( // // // ملاحظة: هذا الرابط يحتاج مفتاح API من MapTiler أو مزود آخر // // urlTemplate: // // 'https://api.maptiler.com/maps/satellite/{z}/{x}/{y}.jpg?key=YOUR_API_KEY', // // userAgentPackageName: 'com.your.app.name', // // ), // // --- الطبقة الثانية: أيقونة السيارة (Marker) --- // MarkerLayer( // markers: [ // Marker( // point: currentCarPosition, // الإحداثيات // width: 80, // height: 80, // child: Transform.rotate( // // 4. هذا بديل rotation // angle: locationController.heading * // (3.1415926535 / 180), // تحويل من درجات إلى راديان // // 5. هذا بديل carIcon (أصبح أسهل!) // child: Image.asset( // 'assets/images/car.png', // نفس المسار الذي استخدمته من قبل // width: 30, // الحجم الذي حددته في addCustomCarIcon // height: 35, // ), // ), // ), // ], // ), // ], // ); }, ); }, ); } } /// 3. The floating "Status Pod" at the bottom of the screen. class _StatusPodOverlay extends StatelessWidget { const _StatusPodOverlay(); void _showDetailsDialog( BuildContext context, HomeCaptainController controller) { Get.dialog( _DriverDetailsDialog(controller), // تمرير الكنترولر هنا barrierColor: Colors.black.withOpacity(0.3), ); } @override Widget build(BuildContext context) { final homeCaptainController = Get.find(); return Positioned( bottom: 16, left: 16, right: 16, child: GestureDetector( onTap: () => _showDetailsDialog(context, homeCaptainController), child: ClipRRect( borderRadius: BorderRadius.circular(24), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Colors.white.withOpacity(0.85), borderRadius: BorderRadius.circular(24), border: Border.all(color: Colors.white.withOpacity(0.5)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, spreadRadius: -5, ) ], ), child: Row( children: [ const ConnectWidget(), const Spacer(), _buildQuickStat( icon: Icons.directions_car_rounded, value: homeCaptainController.countRideToday, label: 'Rides'.tr, color: AppColor.blueColor, ), const SizedBox(width: 16), _buildQuickStat( icon: Entypo.wallet, value: homeCaptainController.totalMoneyToday.toString(), label: 'Today'.tr, color: AppColor.greenColor, ), const SizedBox(width: 8), ], ), ), ), ), ), ); } Widget _buildQuickStat( {required IconData icon, required String value, required String label, required Color color}) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( children: [ Icon(icon, color: color, size: 20), const SizedBox(width: 4), Text(value, style: AppStyle.title .copyWith(fontSize: 16, fontWeight: FontWeight.bold)), ], ), Text(label, style: AppStyle.title .copyWith(fontSize: 12, color: Colors.grey.shade700)), ], ); } } /// 4. The Dialog that shows detailed driver stats. class _DriverDetailsDialog extends StatelessWidget { // 1. إضافة متغير للكنترولر final HomeCaptainController controller; // 2. تحديث البناء لاستقباله const _DriverDetailsDialog(this.controller); @override Widget build(BuildContext context) { // 3. حذف السطر الذي يسبب الخطأ: final homeCaptainController = Get.find... return BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: AlertDialog( backgroundColor: Colors.white.withOpacity(0.95), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), titlePadding: const EdgeInsets.only(top: 20), title: Center( child: Text( 'Your Activity'.tr, style: AppStyle.title .copyWith(fontSize: 20, fontWeight: FontWeight.bold), ), ), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Divider(height: 20), _buildStatRow( icon: Entypo.wallet, color: AppColor.greenColor, label: 'Today'.tr, // استخدام المتغير controller الذي تم تمريره value: controller.totalMoneyToday.toString(), ), const SizedBox(height: 12), _buildStatRow( icon: Entypo.wallet, color: AppColor.yellowColor, label: AppInformation.appName, value: controller.totalMoneyInSEFER.toString(), ), const Divider(height: 24), _buildDurationRow( icon: Icons.timer_outlined, label: 'Active Duration:'.tr, value: controller.stringActiveDuration, color: AppColor.greenColor, ), const SizedBox(height: 12), _buildDurationRow( icon: Icons.access_time, label: 'Total Connection Duration:'.tr, value: controller.totalDurationToday, color: AppColor.accentColor, ), const Divider(height: 24), _buildStatRow( icon: Icons.star_border_rounded, color: AppColor.blueColor, label: 'Total Points'.tr, value: controller.totalPoints.toString(), ), ], ), ), actions: [ TextButton( onPressed: () => Get.back(), child: Text('Close'.tr, style: AppStyle.title.copyWith( color: AppColor.blueColor, fontWeight: FontWeight.bold)), ) ], ), ); } // ... بقية الدوال المساعدة (_buildStatRow, _buildDurationRow) تبقى كما هي ... Widget _buildStatRow( {required IconData icon, required Color color, required String label, required String value}) { return Row( children: [ Icon(icon, color: color, size: 22), const SizedBox(width: 12), Text('$label:', style: AppStyle.title), const Spacer(), Text( value, style: AppStyle.title.copyWith( color: color, fontWeight: FontWeight.bold, fontSize: 18), ), ], ); } Widget _buildDurationRow( {required IconData icon, required String label, required String value, required Color color}) { return Row( children: [ Icon(icon, color: color, size: 20), const SizedBox(width: 12), Text(label, style: AppStyle.title), const Spacer(), Text( value, style: AppStyle.title.copyWith( fontWeight: FontWeight.bold, color: color, fontSize: 16), ), ], ); } } class _MapControlButton extends StatelessWidget { final IconData icon; final VoidCallback onPressed; final String tooltip; const _MapControlButton({ required this.icon, required this.onPressed, required this.tooltip, required MaterialColor iconColor, }); @override Widget build(BuildContext context) { return Tooltip( message: tooltip, child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(12), onTap: onPressed, child: Container( padding: const EdgeInsets.all(8), child: Icon( icon, size: 24, color: AppColor.blueColor, ), ), ), ), ); } } class FloatingActionButtons extends StatelessWidget { const FloatingActionButtons(); @override Widget build(BuildContext context) { // نفس الكود الأصلي للأزرار return Positioned( bottom: Get.height * .2, right: 6, child: GetBuilder(builder: (homeCaptainController) { return Column( children: [ Platform.isAndroid ? AnimatedContainer( duration: const Duration(microseconds: 200), width: homeCaptainController.widthMapTypeAndTraffic, decoration: BoxDecoration( border: Border.all(color: AppColor.blueColor), color: AppColor.secondaryColor, borderRadius: BorderRadius.circular(15)), child: IconButton( onPressed: () async { Bubble().startBubbleHead(sendAppToBackground: true); }, icon: Image.asset( 'assets/images/logo1.png', fit: BoxFit.cover, width: 35, height: 35, ), ), ) : const SizedBox(), const SizedBox( height: 5, ), AnimatedContainer( duration: const Duration(microseconds: 200), width: homeCaptainController.widthMapTypeAndTraffic, decoration: BoxDecoration( border: Border.all(color: AppColor.blueColor), color: AppColor.secondaryColor, borderRadius: BorderRadius.circular(15)), child: IconButton( onPressed: () { Get.to(() => const AvailableRidesPage()); }, icon: const Icon( Icons.train_sharp, size: 29, color: AppColor.blueColor, ), ), ), const SizedBox( height: 5, ), // هذا الكود يوضع داخل الـ Stack في ملف الواجهة (HomeCaptain View) box.read(BoxName.rideStatus) == 'Applied' || box.read(BoxName.rideStatus) == 'Begin' ? Positioned( bottom: Get.height * .2, // جعلنا الزر يظهر في المنتصف أو يمتد ليكون واضحاً جداً right: 20, left: 20, child: Center( child: AnimatedContainer( duration: const Duration( milliseconds: 200), // تم تصحيح microseconds إلى milliseconds لحركة أنعم // أزلنا العرض الثابت homeCaptainController.widthMapTypeAndTraffic لكي يتسع للنص // width: homeCaptainController.widthMapTypeAndTraffic, decoration: BoxDecoration( border: Border.all( color: AppColor.blueColor, width: 2), // تعريض الإطار قليلاً color: AppColor.secondaryColor, // لون الخلفية borderRadius: BorderRadius.circular( 30), // تدوير الحواف ليشبه الأزرار الحديثة boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ) ]), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(30), onLongPress: () { // وظيفة الحذف عند الضغط الطويل (للطوارئ) box.write(BoxName.rideStatus, 'delete'); homeCaptainController.update(); }, onTap: () { // نفس منطقك الأصلي للانتقال if (box.read(BoxName.rideStatus) == 'Applied') { Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Get.put(MapDriverController()) .changeRideToBeginToPassenger(); } else { Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Get.put(MapDriverController()) .startRideFromStartApp(); } }, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 12), child: Row( mainAxisSize: MainAxisSize.min, // حجم الزر على قد المحتوى mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Icons .directions_car_filled_rounded, // تغيير الأيقونة لسيارة أو اتجاهات لتكون معبرة أكثر size: 24, color: AppColor.blueColor, ), const SizedBox( width: 10), // مسافة بين الأيقونة والنص Text( "متابعة الرحلة", // النص الواضح للسائق style: const TextStyle( color: AppColor.blueColor, fontSize: 16, fontWeight: FontWeight.bold, fontFamily: 'Cairo', // تأكد من نوع الخط المستخدم عندك ), ), if (box.read(BoxName.rideStatus) == 'Begin') ...[ const SizedBox(width: 5), // إضافة مؤشر صغير (نقطة حمراء) إذا كانت الرحلة قد بدأت بالفعل (اختياري) const Icon(Icons.circle, size: 8, color: Colors.green) ] ], ), ), ), ), ), ), ) : const SizedBox() ], ); }), ); } } Future checkForAppliedRide(BuildContext context) async { checkForPendingOrderFromServer(); } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/osm_view_map.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:get/get.dart'; import 'package:latlong2/latlong.dart'; import '../../../../controller/functions/location_controller.dart'; import '../../../../controller/home/captin/home_captain_controller.dart'; // هذه ويدجت بديلة للـ _MapView في الكود الخاص بك // V3 - MapView Replacement using flutter_map class OsmMapView extends StatelessWidget { const OsmMapView({super.key}); @override Widget build(BuildContext context) { // افترض أنك تحصل على الموقع والاتجاه بنفس الطريقة من الكونترولر final LocationController locationController = Get.find(); final HomeCaptainController homeCaptainController = Get.find(); // يمكنك استخدام GetBuilder لمراقبة التغييرات في الموقع return Obx(() { final LatLng currentLocation = LatLng( locationController.myLocation.latitude, locationController.myLocation.longitude); final double currentHeading = locationController.heading; return FlutterMap( // يمكنك ربط هذا بـ MapController الخاص بـ flutter_map // mapController: homeCaptainController.flutterMapController, options: MapOptions( initialCenter: currentLocation, initialZoom: 15, maxZoom: 18, minZoom: 6, // تدوير الخريطة (اختياري) initialRotation: currentHeading, ), children: [ // 1. طبقة الخريطة الأساسية (Tiles) // هذا هو الرابط لخرائط OSM الأساسية TileLayer( urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c'], userAgentPackageName: 'com.example.app', // استبدل باسم الباكج الخاص بك // لاستخدام الخرائط الأوفلاين (بعد إعداد flutter_map_tile_caching) // tileProvider: CachedTileProvider(), ), // 2. طبقة العلامات (Markers) MarkerLayer( markers: [ Marker( width: 80.0, height: 80.0, point: currentLocation, child: Transform.rotate( angle: currentHeading * (3.1415926535 / 180), // تحويل من درجات إلى راديان child: Image.asset( 'assets/images/car_icon.png', // تأكد أن لديك أيقونة السيارة // يمكنك استخدام نفس الـ carIcon من الكونترولر // icon: homeCaptainController.carIcon, (ملاحظة: flutter_map تستخدم ويدجت) ), ), ), ], ), // يمكنك إضافة طبقات أخرى هنا (مثل الخطوط Polylines أو المضلعات Polygons) ], ); }); } } // ملاحظة: ستحتاج إلى تعديل بسيط في HomeCaptainController // لإنشاء MapController الخاص بـ flutter_map بدلاً من GoogleMapController // import 'package:flutter_map/flutter_map.dart'; // MapController flutterMapController = MapController(); ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/widget/call_page.dart ================================================== // import 'package:SEFER/constant/colors.dart'; // import 'package:SEFER/constant/style.dart'; // import 'package:SEFER/controller/firebase/firbase_messge.dart'; // import 'package:SEFER/controller/home/captin/map_driver_controller.dart'; // import 'package:SEFER/views/widgets/my_scafold.dart'; // import 'package:flutter/material.dart'; // import 'package:get/get.dart'; // import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; // import '../../../../../controller/functions/call_controller.dart'; // class CallPage extends StatelessWidget { // const CallPage({super.key}); // @override // Widget build(BuildContext context) { // return MyScafolld( // title: 'Call Page'.tr, isleading: true, body: [callPage()]); // } // } // GetBuilder callPage() { // CallController callController = Get.put(CallController()); // Get.put(MapDriverController()); // // callController.join(); // return GetBuilder( // builder: (controller) => Positioned( // top: Get.height * .2, // child: Container( // height: 100, width: Get.width, // decoration: AppStyle.boxDecoration, // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // GestureDetector( // onTap: () async { // callController.join(); // }, // child: Container( // width: 50, // height: 50, // decoration: const BoxDecoration( // shape: BoxShape.circle, color: AppColor.greenColor), // child: const Icon( // Icons.phone, // size: 35, // color: AppColor.secondaryColor, // )), // ), // Column( // children: [ // Text(callController.status), // Text(Get.find().passengerName.toString()), // ], // ), // GestureDetector( // onTap: () async { // FirebaseMessagesController().sendNotificationToPassengerToken( // 'Call End'.tr, // 'Call End', // Get.find().tokenPassenger, // [], // 'iphone_ringtone.wav'); // callController.leave(); // Get.back(); // }, // child: Container( // width: 50, // height: 50, // decoration: const BoxDecoration( // shape: BoxShape.circle, color: AppColor.redColor), // child: const Icon( // Icons.phone_disabled_sharp, // size: 35, // color: AppColor.secondaryColor, // )), // ) // ], // ), // // ignore: prefer_const_constructors // ), // ), // ); // } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/widget/zones_controller.dart ================================================== import 'dart:convert'; import 'dart:math'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class ZonesController extends GetxController { Map> generateZoneMap( LatLng southwest, LatLng southEast, LatLng northeast) { const double desiredZoneArea = 4; // in square kilometers final double width = (southEast.longitude - southwest.longitude) * 100; final double height = (northeast.latitude - southEast.latitude) * 100; final double totalArea = width * height; // final int numZones = (totalArea / desiredZoneArea).ceil(); final double zoneWidth = width / sqrt(desiredZoneArea); final double zoneHeight = height / sqrt(desiredZoneArea); final numRows = ((northeast.latitude - southwest.latitude) / zoneHeight).ceil(); final numCols = ((southEast.longitude - southwest.longitude) / zoneWidth).ceil(); List zoneNames = []; List zoneCoordinates = []; for (int row = 0; row < numRows; row++) { for (int col = 0; col < numCols; col++) { final double zoneSouthwestLat = southwest.latitude + (row * zoneHeight / 100); final double zoneSouthwestLng = southwest.longitude + (col * zoneWidth / 100); final double zoneNortheastLat = zoneSouthwestLat + zoneHeight / 100; final double zoneNortheastLng = zoneSouthwestLng + zoneWidth / 100; LatLng zoneSouthwest = LatLng(zoneSouthwestLat, zoneSouthwestLng); LatLng zoneNortheast = LatLng(zoneNortheastLat, zoneNortheastLng); String zoneName = 'Zone${row + col}'; // Assign a unique name to each zone zoneNames.add(zoneName); zoneCoordinates.add(zoneSouthwest); zoneCoordinates.add(zoneNortheast); } } Map> zoneMap = {}; for (int i = 0; i < zoneNames.length; i++) { zoneMap[zoneNames[i]] = [ zoneCoordinates[i], // Southwest LatLng zoneCoordinates[i + 1], // Northeast LatLng ]; } return zoneMap; } void getJsonOfZones() { LatLng southwest = const LatLng(32.111107, 36.062222); LatLng southEast = const LatLng(32.108333, 36.101667); LatLng northeast = const LatLng(32.143889, 36.058889); Map> zoneMap = generateZoneMap(southwest, southEast, northeast); String jsonMap = json.encode(zoneMap); } } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/widget/connect.dart ================================================== import 'package:sefer_driver/controller/functions/tts.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import '../../../../../constant/style.dart'; import '../../../../../controller/functions/encrypt_decrypt.dart'; import '../../../../widgets/elevated_btn.dart'; import '../../../../../controller/home/captin/home_captain_controller.dart'; class ConnectWidget extends StatelessWidget { const ConnectWidget({ super.key, }); @override Widget build(BuildContext context) { // final OrderRequestController orderRequestController = // Get.put(OrderRequestController()); CaptainWalletController captainWalletController = Get.put(CaptainWalletController()); captainWalletController.getCaptainWalletFromBuyPoints(); return Center( child: GetBuilder( builder: (homeCaptainController) => double.parse( (captainWalletController.totalPoints)) < -300 ? CupertinoButton( onPressed: () { Get.defaultDialog( // backgroundColor: CupertinoColors.destructiveRed, barrierDismissible: false, title: double.parse( (captainWalletController.totalPoints)) < -300 ? 'You dont have Points'.tr : 'You Are Stopped For this Day !'.tr, titleStyle: AppStyle.title, content: Column( children: [ IconButton( onPressed: () async { double.parse((captainWalletController .totalPoints)) < -300 ? await Get.find() .speakText( 'You must be recharge your Account' .tr) : await Get.find() .speakText( 'You Refused 3 Rides this Day that is the reason \nSee you Tomorrow!' .tr); }, icon: const Icon(Icons.headphones), ), Text( double.parse((captainWalletController .totalPoints)) < -300 ? 'You must be recharge your Account'.tr : 'You Refused 3 Rides this Day that is the reason \nSee you Tomorrow!' .tr, style: AppStyle.title, ), ], ), confirm: double.parse( (captainWalletController.totalPoints)) < -300 ? MyElevatedButton( title: 'Recharge my Account'.tr, onPressed: () { homeCaptainController.goToWalletFromConnect(); }) : MyElevatedButton( title: 'Ok , See you Tomorrow'.tr, onPressed: () { Get.back(); Get.back(); })); }, color: CupertinoColors.destructiveRed, child: Text( 'You are Stopped'.tr, style: AppStyle.title, ), ) : Container( decoration: BoxDecoration( gradient: LinearGradient( colors: homeCaptainController.isActive ? [Colors.green.shade400, Colors.green.shade700] : [Colors.grey.shade400, Colors.grey.shade700], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: homeCaptainController.isActive ? Colors.green.withOpacity(0.3) : Colors.grey.withOpacity(0.3), spreadRadius: 1, blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: CupertinoButton( onPressed: homeCaptainController.onButtonSelected, padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 12), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( homeCaptainController.isActive ? CupertinoIcons.check_mark_circled_solid : CupertinoIcons.circle, color: Colors.white, size: 24, ), const SizedBox(width: 8), Text( homeCaptainController.isActive ? 'Connected'.tr : 'Not Connected'.tr, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ), ), )), ); } } ================================================== FILE PATH: ./lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart ================================================== import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/firebase/local_notification.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/captin/otp_page.dart'; import 'package:sefer_driver/views/home/Captin/driver_map_page.dart'; import 'package:sefer_driver/views/home/Captin/orderCaptin/vip_order_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import '../../../../../constant/colors.dart'; import '../../../../../constant/links.dart'; import '../../../../../controller/firebase/firbase_messge.dart'; import '../../../../../controller/firebase/notification_service.dart'; import '../../../../../controller/functions/crud.dart'; import '../../../../../controller/home/captin/order_request_controller.dart'; import '../../../../../controller/home/navigation/navigation_view.dart'; import '../../../../../print.dart'; import '../../../../Rate/ride_calculate_driver.dart'; GetBuilder leftMainMenuCaptainIcons() { final firebaseMessagesController = Get.isRegistered() ? Get.find() : Get.put(FirebaseMessagesController()); return GetBuilder( builder: (controller) => Positioned( bottom: Get.height * .2, left: 6, child: Column( children: [ AnimatedContainer( duration: const Duration(microseconds: 200), width: controller.widthMapTypeAndTraffic, decoration: BoxDecoration( color: AppColor.secondaryColor, border: Border.all(color: AppColor.blueColor), borderRadius: BorderRadius.circular(15)), child: Builder(builder: (context) { return IconButton( onPressed: () async { await checkForPendingOrderFromServer(); box.read(BoxName.rideArgumentsFromBackground) != 'failure' ? Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArgumentsFromBackground)) : MyDialog().getDialog( 'Ride info'.tr, 'you dont have accepted ride'.tr, () { Get.back(); }, ); // 'box.read(BoxName.rideArgumentsFromBackground): ${box.read(BoxName.rideArgumentsFromBackground)}'); }, icon: Icon( Icons.directions_car_rounded, size: 29, color: box.read(BoxName.rideArgumentsFromBackground) == 'failure' ? AppColor.redColor : AppColor.greenColor, ), ); }), ), const SizedBox( height: 5, ), AnimatedContainer( duration: const Duration(microseconds: 200), width: controller.widthMapTypeAndTraffic, decoration: BoxDecoration( color: AppColor.secondaryColor, border: Border.all(color: AppColor.blueColor), borderRadius: BorderRadius.circular(15)), child: IconButton( onLongPress: () { box.write(BoxName.statusDriverLocation, 'off'); }, onPressed: () { // NotificationController1() // .showNotification('Sefer Driver'.tr, ''.tr, '', ''); final now = DateTime.now(); DateTime? lastRequestTime = box.read(BoxName.lastTimeStaticThrottle); if (lastRequestTime == null || now.difference(lastRequestTime).inMinutes >= 2) { // Update the last request time to now lastRequestTime = now; box.write(BoxName.lastTimeStaticThrottle, lastRequestTime); // Navigate to the RideCalculateDriver page Get.to(() => RideCalculateDriver()); } else { // Optionally show a message or handle the throttling case final minutesLeft = 2 - now.difference(lastRequestTime).inMinutes; // Get.snackbar( // '${'Please wait'.tr} $minutesLeft ${"minutes before trying again.".tr}', // ''); NotificationController1().showNotification( 'Intaleq Driver'.tr, '${'Please wait'.tr} $minutesLeft ${"minutes before trying again.".tr}', 'ding', ''); } }, icon: const Icon( FontAwesome5.chart_bar, size: 29, color: AppColor.blueColor, ), ), ), const SizedBox( height: 5, ), // Platform.isAndroid // ? int.parse(box.read(BoxName.carYear).toString()) > 2023 ? AnimatedContainer( duration: const Duration(microseconds: 200), width: controller.widthMapTypeAndTraffic, decoration: BoxDecoration( color: AppColor.secondaryColor, border: Border.all(color: AppColor.blueColor), borderRadius: BorderRadius.circular(15)), child: Builder(builder: (context) { return IconButton( onPressed: () async { // mySnakeBarError('ad'); Get.to(() => const VipOrderPage()); }, icon: const Icon( Octicons.watch, size: 29, color: AppColor.blueColor, ), ); }), ) : const SizedBox(), // const SizedBox( // height: 5, // ), AnimatedContainer( duration: const Duration(microseconds: 200), width: controller.widthMapTypeAndTraffic, decoration: BoxDecoration( color: AppColor.secondaryColor, border: Border.all(color: AppColor.blueColor), borderRadius: BorderRadius.circular(15)), child: Builder(builder: (context) { return IconButton( onPressed: () async { box.remove(BoxName.agreeTerms); Get.to(() => const NavigationView()); // box.write(BoxName.statusDriverLocation, 'off'); }, icon: const Icon( FontAwesome5.map, size: 29, color: AppColor.blueColor, ), ); }), ), // AnimatedContainer( // duration: const Duration(microseconds: 200), // width: controller.widthMapTypeAndTraffic, // decoration: BoxDecoration( // color: AppColor.secondaryColor, // border: Border.all(color: AppColor.blueColor), // borderRadius: BorderRadius.circular(15)), // child: Builder(builder: (context) { // return IconButton( // onPressed: () async { // NotificationService.sendNotification( // target: 'service', // الإرسال لجميع المشتركين في "service" // title: 'طلب خدمة جديد', // body: 'تم استلام طلب خدمة جديد. الرجاء مراجعة التفاصيل.', // isTopic: true, // category: 'new_service_request', // فئة توضح نوع الإشعار // ); // }, // icon: const Icon( // FontAwesome5.grin_tears, // size: 29, // color: AppColor.blueColor, // ), // ); // }), // ), const SizedBox( height: 5, ), ], ), ), ); } Future checkForPendingOrderFromServer() async { bool _isProcessingOrder = false; if (_isProcessingOrder) return; final driverId = box.read(BoxName.driverID)?.toString(); if (driverId == null) return; // Can't check without a driver ID _isProcessingOrder = true; // Lock try { // You need to create this CRUD method var response = await CRUD().post( link: AppLink.getArgumentAfterAppliedFromBackground, payload: {'driver_id': driverId}, ); Log.print('response: ${response}'); // Assuming the server returns order data if found, or 'failure'/'none' if not if (response['status'] == 'success') { final Map orderInfoFromServer = response['message']; final Map rideArguments = _transformServerDataToAppArguments(orderInfoFromServer); // 2. Build the new arguments map, matching your Flutter structure ///////////// final customerToken = (response)['message']['token_passenger']; final orderId = (response)['message']['ride_id'].toString(); box.write(BoxName.rideArgumentsFromBackground, rideArguments); box.write(BoxName.statusDriverLocation, 'on'); box.write(BoxName.rideStatus, 'Apply'); Get.put(OrderRequestController()).changeApplied(); // MyDialog().getDialog(orderId.toString(), customerToken, () {}); // Now proceed with the UI flow // _sendAcceptanceNotification(customerToken, orderId.toString()); // await _bringAppToForegroundAndNavigate(orderId); Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArgumentsFromBackground)); } else { box.write(BoxName.rideArgumentsFromBackground, 'failure'); } } catch (e) { } finally { _isProcessingOrder = false; // Release lock } } Map _transformServerDataToAppArguments( Map serverData) { // Helper function to safely get and convert values to String String _getString(String key, [String defaultValue = 'unknown']) { // serverData[key] might be an int, double, or string. .toString() handles all. // If it's null, use the default value. return serverData[key]?.toString() ?? defaultValue; } return { 'passengerLocation': _getString('passenger_location'), 'passengerDestination': _getString('passenger_destination'), 'Duration': _getString('duration'), 'totalCost': _getString('total_cost'), 'Distance': _getString('distance'), 'name': _getString('name'), 'phone': _getString('phone'), 'email': _getString('email'), 'tokenPassenger': _getString('token_passenger'), 'direction': _getString('direction_url'), 'DurationToPassenger': _getString('duration_to_passenger'), 'rideId': _getString('ride_id'), 'passengerId': _getString('passenger_id'), 'driverId': _getString('driver_id'), 'durationOfRideValue': _getString('duration_of_ride'), 'paymentAmount': _getString('payment_amount'), 'paymentMethod': _getString('payment_method'), 'passengerWalletBurc': _getString('passenger_wallet_burc'), 'timeOfOrder': _getString('time_of_order'), 'totalPassenger': _getString('total_passenger'), 'carType': _getString('car_type'), 'kazan': _getString('kazan'), 'startNameLocation': _getString('start_name_location'), 'endNameLocation': _getString('end_name_location'), // --- Special Handling --- // Steps (handle null values by providing an empty string) 'step0': _getString('step0'), 'step1': _getString('step1'), 'step2': _getString('step2'), 'step3': _getString('step3'), 'step4': _getString('step4'), // Boolean conversion (1/0 from server to 'true'/'false' string for the app) 'WalletChecked': (serverData['wallet_checked'] == 1).toString(), // Logic-based conversion for isHaveSteps // Your app's `rideArguments` expects 'startEnd', so we provide that if has_steps is 1. // You might need to adjust this logic if 'haveSteps' is also a possibility. 'isHaveSteps': (serverData['has_steps'] == 1) ? 'startEnd' : 'noSteps', // Providing a default }; } void _sendAcceptanceNotification(String? customerToken, rideId) { try { if (customerToken == null) return; List bodyToPassenger = [ box.read(BoxName.driverID).toString(), box.read(BoxName.nameDriver).toString(), box.read(BoxName.tokenDriver).toString(), rideId.toString() ]; // Safely check for customer token final String? token = customerToken; if (token != null && token.isNotEmpty) { NotificationService.sendNotification( target: token.toString(), title: 'Accepted Ride'.tr, body: 'your ride is Accepted'.tr, isTopic: false, // Important: this is a token tone: 'start', driverList: bodyToPassenger, category: 'Accepted Ride', ); } else {} } catch (e) {} } ================================================== FILE PATH: ./lib/views/home/profile/profile_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/profile/captain_profile_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/captin/criminal_documents_page.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import '../../../constant/links.dart'; import '../../../controller/functions/crud.dart'; import 'behavior_page.dart'; import 'captains_cars.dart'; // الصفحة الرئيسية الجديدة class ProfileCaptain extends StatelessWidget { const ProfileCaptain({super.key}); @override Widget build(BuildContext context) { // Get.put() يجب أن يكون في مكان يتم استدعاؤه مرة واحدة فقط، // لكن سنبقيه هنا حسب الكود الأصلي final controller = Get.put(CaptainProfileController()); return MyScafolld( title: 'My Profile'.tr, isleading: true, body: [ GetBuilder( builder: (controller) { if (controller.isLoading) { return const Center(child: MyCircularProgressIndicator()); } if (controller.captainProfileData.isEmpty) { return Center(child: Text('Failed to load profile data.'.tr)); } return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), child: Column( children: [ // 1. رأس الصفحة: صورة واسم وتقييم ProfileHeader( name: '${controller.captainProfileData['first_name'] ?? ''} ${controller.captainProfileData['last_name'] ?? ''}', rating: controller.captainProfileData['ratingDriver'] != null ? double.tryParse(controller .captainProfileData['ratingDriver'] .toString()) ?? 0.0 : 0.0, ratingCount: int.tryParse(controller .captainProfileData['ratingCount'] .toString()) ?? 0, ), const SizedBox(height: 24), // 2. قسم الإجراءات السريعة ActionsGrid(), const SizedBox(height: 24), // 3. بطاقة المعلومات الشخصية PersonalInfoCard( data: controller.captainProfileData .cast()), const SizedBox(height: 16), // 4. بطاقة معلومات المركبة (قابلة للتوسيع) VehicleInfoCard( data: controller.captainProfileData .cast()), ], ), ); }, ), ], ); } } // --- الويدجتس الجديدة المنفصلة لتحسين التصميم --- /// 1. ويدجت رأس الصفحة class ProfileHeader extends StatelessWidget { final String name; final double rating; final int ratingCount; const ProfileHeader({ super.key, required this.name, required this.rating, required this.ratingCount, }); @override Widget build(BuildContext context) { return Column( children: [ CircleAvatar( radius: 50, backgroundColor: Get.theme.primaryColor.withOpacity(0.1), child: Icon(Icons.person, size: 60, color: Get.theme.primaryColor), ), const SizedBox(height: 12), Text( name, style: Get.textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.star, color: Colors.amber, size: 20), const SizedBox(width: 4), Text( '${rating.toStringAsFixed(1)} (${'reviews'.tr} $ratingCount)', style: Get.textTheme.titleMedium ?.copyWith(color: Colors.grey.shade600), ), ], ), ], ); } } /// 2. ويدجت شبكة الأزرار class ActionsGrid extends StatelessWidget { const ActionsGrid({super.key}); @override Widget build(BuildContext context) { return GridView.count( crossAxisCount: 2, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisSpacing: 16, mainAxisSpacing: 16, childAspectRatio: 2.5, // للتحكم في ارتفاع الأزرار children: [ // _ActionTile( // title: 'My Cars'.tr, // icon: Icons.directions_car_filled, // onTap: () => Get.to(() => CaptainsCars()), // ), // _ActionTile( // title: 'Criminal Record'.tr, // icon: Icons.description, // onTap: () => Get.to(() => CriminalDocumemtPage()), // ), _ActionTile( title: 'ShamCash Account'.tr, // غيرت الاسم ليكون أوضح icon: Icons.account_balance_wallet_rounded, // أيقونة محفظة // trailing: Icon(Icons.arrow_forward_ios, // size: 16, color: Colors.grey), // سهم صغير للجمالية onTap: () { // استدعاء دالة فتح النافذة showShamCashInput(); }, ), _ActionTile( title: 'Behavior Page'.tr, icon: Icons.checklist_rtl, onTap: () => Get.to(() => BehaviorPage()), ), ], ); } } void showShamCashInput() { // 1. القراءة من الذاكرة المحلية (GetStorage) عند فتح النافذة // إذا لم يتم العثور على قيمة، يتم تعيينها إلى نص فارغ final String existingName = box.read('shamcash_name') ?? ''; final String existingCode = box.read('shamcash_code') ?? ''; // تعريف أدوات التحكم للحقلين مع تحميل القيمة المحفوظة final TextEditingController nameController = TextEditingController(text: existingName); final TextEditingController codeController = TextEditingController(text: existingCode); Get.bottomSheet( Container( padding: const EdgeInsets.all(25), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(30)), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 10, offset: Offset(0, -2)) ], ), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // --- 1. المقبض العلوي --- Center( child: Container( height: 5, width: 50, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(10)), margin: const EdgeInsets.only(bottom: 20), ), ), // --- 2. العنوان والأيقونة --- Image.asset( 'assets/images/shamCash.png', height: 50, ), // const Icon(Icons.account_balance_wallet_rounded, // size: 45, color: Colors.blueAccent), const SizedBox(height: 10), Text( "ربط حساب شام كاش 🔗", textAlign: TextAlign.center, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.blueGrey[900]), ), const SizedBox(height: 5), const Text( "أدخل بيانات حسابك لاستقبال الأرباح فوراً", textAlign: TextAlign.center, style: TextStyle(fontSize: 13, color: Colors.grey), ), const SizedBox(height: 25), // --- 3. الحقل الأول: اسم الحساب (أعلى الباركود) --- const Text("1. اسم الحساب (أعلى الباركود)", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)), const SizedBox(height: 8), Container( decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[300]!), ), child: TextField( controller: nameController, decoration: InputDecoration( hintText: "مثال: intaleq", hintStyle: TextStyle(color: Colors.grey[400], fontSize: 13), border: InputBorder.none, prefixIcon: const Icon(Icons.person_outline_rounded, color: Colors.blueGrey), contentPadding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10), ), ), ), const SizedBox(height: 15), // --- 4. الحقل الثاني: الكود (أسفل الباركود) --- const Text("2. كود المحفظة (أسفل الباركود)", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)), const SizedBox(height: 8), Container( decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[300]!), ), child: TextField( controller: codeController, style: const TextStyle( fontSize: 13, letterSpacing: 0.5), // خط أصغر قليلاً للكود الطويل decoration: InputDecoration( hintText: "مثال: 80f23afe40...", hintStyle: TextStyle(color: Colors.grey[400], fontSize: 13), border: InputBorder.none, prefixIcon: const Icon(Icons.qr_code_2_rounded, color: Colors.blueGrey), contentPadding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10), // زر لصق الكود suffixIcon: IconButton( icon: const Icon(Icons.paste_rounded, color: Colors.blue), tooltip: "لصق الكود", onPressed: () async { ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); if (data != null && data.text != null) { codeController.text = data.text!; // تحريك المؤشر للنهاية بعد اللصق codeController.selection = TextSelection.fromPosition( TextPosition(offset: codeController.text.length), ); } }, ), ), ), ), const SizedBox(height: 30), // --- 5. زر الحفظ --- SizedBox( height: 50, child: ElevatedButton( onPressed: () async { String name = nameController.text.trim(); String code = codeController.text.trim(); // التحقق من صحة البيانات if (name.isNotEmpty && code.length > 5) { // 1. إرسال البيانات إلى السيرفر var res = await CRUD() .post(link: AppLink.updateShamCashDriver, payload: { "id": box.read(BoxName.driverID), "accountBank": name, "bankCode": code, }); if (res != 'failure') { // 2. 🔴 الحفظ في الذاكرة المحلية (GetStorage) بعد نجاح التحديث box.write('shamcash_name', name); box.write('shamcash_code', code); Get.back(); // إغلاق النافذة Get.snackbar( "تم الحفظ بنجاح", "تم ربط حساب ($name) لاستلام الأرباح.", backgroundColor: Colors.green, colorText: Colors.white, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(20), icon: const Icon(Icons.check_circle_outline, color: Colors.white), ); return; } else { // في حال فشل الإرسال إلى السيرفر Get.snackbar( "خطأ في السيرفر", "فشل تحديث البيانات، يرجى المحاولة لاحقاً.", backgroundColor: Colors.redAccent, colorText: Colors.white, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(20), ); } } else { Get.snackbar( "بيانات ناقصة", "يرجى التأكد من إدخال الاسم والكود بشكل صحيح.", backgroundColor: Colors.orange, colorText: Colors.white, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(20), ); } }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2ecc71), // الأخضر المالي shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), elevation: 2, ), child: const Text( "حفظ وتفعيل الحساب", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), const SizedBox(height: 10), // مسافة سفلية إضافية للأمان ], ), ), ), isScrollControlled: true, // ضروري لرفع النافذة عند فتح الكيبورد ); } /// ويدجت داخلية لزر في الشبكة class _ActionTile extends StatelessWidget { final String title; final IconData icon; final VoidCallback onTap; const _ActionTile( {required this.title, required this.icon, required this.onTap}); @override Widget build(BuildContext context) { return Material( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(12), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: Get.theme.primaryColor, size: 20), const SizedBox(width: 8), Flexible( child: Text( title, style: Get.textTheme.labelLarge, textAlign: TextAlign.center, )), ], ), ), ), ); } } /// 3. بطاقة المعلومات الشخصية class PersonalInfoCard extends StatelessWidget { final Map data; PersonalInfoCard({super.key, required this.data}); final controller = Get.find(); @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Personal Information'.tr, style: Get.textTheme.titleLarge), const Divider(height: 24), _InfoRow( icon: Icons.phone, label: 'Phone Number'.tr, value: data['phone'] ?? ''), if (data['email'] != null && data['email'].toString().contains('intaleqapp')) ...[ TextFormField( controller: controller.emailController, keyboardType: TextInputType.emailAddress, // ✅ لوحة مفاتيح خاصة بالإيميل decoration: InputDecoration( border: OutlineInputBorder(), labelText: 'Email'.tr, hintText: 'Enter your email'.tr, prefixIcon: Icon(Icons.email), ), autofillHints: [ AutofillHints.email ], // اختياري لتحسين تجربة المستخدم ), const SizedBox(height: 10), ElevatedButton( onPressed: () async { await controller.updateEmail(); }, child: Text('Update'.tr), ), ] else _InfoRow( icon: Icons.email, label: 'Email'.tr, value: data['email'] ?? '', ), _InfoRow( icon: Icons.cake, label: 'Age'.tr, value: data['age']?.toString() ?? 'N/A'), _InfoRow( icon: Icons.wc, label: 'Gender'.tr, value: data['gender'] ?? 'N/A'), ], ), ), ); } } /// 4. بطاقة معلومات المركبة class VehicleInfoCard extends StatelessWidget { final Map data; const VehicleInfoCard({super.key, required this.data}); @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: ExpansionTile( title: Text('Vehicle Details'.tr, style: Get.textTheme.titleLarge), leading: Icon(Icons.directions_car, color: Get.theme.primaryColor), childrenPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), children: [ _InfoRow( icon: Icons.branding_watermark, label: 'Make'.tr, value: data['make'] ?? ''), _InfoRow( icon: Icons.category, label: 'Model'.tr, value: data['model'] ?? ''), _InfoRow( icon: Icons.palette, label: 'Color'.tr, value: data['color'] ?? ''), _InfoRow( icon: Icons.pin, label: 'Plate Number'.tr, value: data['car_plate'] ?? ''), _InfoRow( icon: Icons.confirmation_number, label: 'VIN'.tr, value: data['vin'] ?? ''), _InfoRow( icon: Icons.event, label: 'Expiration Date'.tr, value: data['expiration_date'] ?? ''), ], ), ); } } /// ويدجت لعرض سطر معلومة (أيقونة + عنوان + قيمة) لتجنب التكرار class _InfoRow extends StatelessWidget { final IconData icon; final String label; final String value; const _InfoRow( {required this.icon, required this.label, required this.value}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ Icon(icon, color: Colors.grey.shade500, size: 20), const SizedBox(width: 16), Text(label, style: Get.textTheme.bodyLarge), const Spacer(), Flexible( child: Text( value, style: Get.textTheme.bodyLarge?.copyWith( color: Colors.grey.shade700, fontWeight: FontWeight.w500), textAlign: TextAlign.end, ), ), ], ), ); } } ================================================== FILE PATH: ./lib/views/home/profile/cars_inserting_page.dart ================================================== import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../constant/colors.dart'; import '../../../constant/links.dart'; import '../../../constant/style.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../controller/functions/gemeni.dart'; import '../../auth/captin/driver_car_controller.dart'; class CarsInsertingPage extends StatelessWidget { CarsInsertingPage({super.key}); final driverCarController = Get.put(DriverCarController()); @override Widget build(BuildContext context) { Get.put(AI()); return MyScafolld( title: "Add new car".tr, body: [ Container( color: AppColor.accentColor.withOpacity(.2), child: Padding( padding: const EdgeInsets.all(22), child: ListView( // crossAxisAlignment: CrossAxisAlignment.center, children: [ syriaCarLicenceFront(), syriaCarLicenceBack(), const SizedBox(height: 10), Text('Please make sure to read the license carefully.'.tr), Text( 'If your car license has the new design, upload the front side with two images.' .tr), const SizedBox(height: 10), MyElevatedButton( title: 'Please upload this license.'.tr, onPressed: () { final aiFront = Get.find().responseIdCardDriverEgyptFront; final aiBack = Get.find().responseIdCardDriverEgyptBack; driverCarController.addCarsForDrivers( aiBack['chassis'].toString(), aiBack['car_plate'].toString(), aiBack['make'].toString(), aiBack['model'].toString(), aiBack['year'].toString(), aiFront['LicenseExpirationDate'].toString(), aiBack['color'].toString(), aiBack['color_hex'].toString(), aiFront['address'].toString(), aiFront['owner'].toString(), aiBack['inspection_date'].toString(), aiBack['engine'].toString(), aiBack['fuel'].toString(), ); }) ], ), ), ) ], isleading: true); } } GetBuilder syriaCarLicenceFront() { return GetBuilder( builder: (ai) { if (ai.responseIdCardDriverEgyptFront.isNotEmpty) { // No need to access ai.responseIdCardDriverEgyptBack anymore final licenseExpiryDate = DateTime.parse( ai.responseIdCardDriverEgyptFront['LicenseExpirationDate']); // Check if license has expired final today = DateTime.now(); final isLicenseExpired = licenseExpiryDate.isBefore(today); return Card( elevation: 4.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text('Vehicle Details Front'.tr, style: AppStyle.headTitle2), IconButton( onPressed: () async { ai.allMethodForAI((ai.prompts[3]['prompt'].toString()), AppLink.uploadEgypt, 'car_front'); }, icon: const Icon(Icons.refresh), ), ], ), const SizedBox(height: 8.0), const Divider(color: AppColor.accentColor), const SizedBox(height: 8.0), // Removed Make, Model, etc. as they are not available Text( '${'Plate Number'.tr}: ${ai.responseIdCardDriverEgyptFront['car_plate']}', ), const SizedBox(height: 8.0), Text( '${'Owner Name'.tr}: ${ai.responseIdCardDriverEgyptFront['owner']}', ), const SizedBox(height: 8.0), Text( '${'Address'.tr}: ${ai.responseIdCardDriverEgyptFront['address']}', ), const SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'License Expiry Date'.tr}: ${licenseExpiryDate.toString().substring(0, 10)}', style: TextStyle( color: isLicenseExpired ? Colors.red : Colors.green, ), ), // Removed Fuel as it's not available ], ), // Removed Inspection Date as it's not available ], ), ), ); } return Card( child: InkWell( onTap: () async { ai.allMethodForAINewCar((ai.prompts[3]['prompt'].toString()), AppLink.uploadEgypt1, 'car_front', 'carId'); //todo }, child: Column( children: [ Image.asset( 'assets/images/3.png', height: Get.height * .25, width: double.maxFinite, fit: BoxFit.fitHeight, ), Text( 'Capture an Image of Your car license front '.tr, style: AppStyle.title, ), ], ), ), ); }, ); } GetBuilder syriaCarLicenceBack() { return GetBuilder( builder: (ai) { if (ai.responseIdCardDriverEgyptBack.isNotEmpty) { // Get the tax expiry date from the response final taxExpiryDate = ai.responseIdCardDriverEgyptBack['tax_expiry'].toString(); // final displacement = ai.responseIdCardDriverEgyptBack['displacement']; // if (int.parse(displacement) < 1000) {} // Get the inspection date from the response final inspectionDate = ai.responseIdCardDriverEgyptBack['inspection_date'].toString(); final year = int.parse(inspectionDate.toString().split('-')[0]); // Set inspectionDateTime to December 31st of the given year final inspectionDateTime = DateTime(year, 12, 31); String carBackLicenseExpired = inspectionDateTime.toString().split(' ')[0]; // Get the current date final today = DateTime.now(); // Try parsing the tax expiry date. If it fails, set it to null. final taxExpiryDateTime = DateTime.tryParse(taxExpiryDate ?? ''); final isExpired = taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today); // Check if the inspection date is before today bool isInspectionExpired = inspectionDateTime.isBefore(today); return Card( elevation: 4.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Vehicle Details Back'.tr, style: AppStyle.headTitle2), IconButton( onPressed: () async { ai.allMethodForAI((ai.prompts[4]['prompt'].toString()), AppLink.uploadEgypt, 'car_back'); }, icon: const Icon(Icons.refresh), ), ], ), const SizedBox(height: 8.0), const Divider(color: AppColor.accentColor), const SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Make'.tr}: ${ai.responseIdCardDriverEgyptBack['make']}'), Text( '${'Model'.tr}: ${ai.responseIdCardDriverEgyptBack['model']}'), ], ), const SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Year'.tr}: ${ai.responseIdCardDriverEgyptBack['year']}'), Text( '${'Chassis'.tr}: ${ai.responseIdCardDriverEgyptBack['chassis']}'), ], ), const SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Color'.tr}: ${ai.responseIdCardDriverEgyptBack['color']}'), Text( '${'Displacement'.tr}: ${ai.responseIdCardDriverEgyptBack['displacement']} cc'), ], ), const SizedBox(height: 8.0), Text( '${'Fuel'.tr}: ${ai.responseIdCardDriverEgyptBack['fuel']}'), const SizedBox(height: 8.0), if (taxExpiryDateTime != null) Text( '${'Tax Expiry Date'.tr}: $taxExpiryDate', style: TextStyle( color: isExpired ? Colors.red : Colors.green, ), ), const SizedBox(height: 8.0), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Inspection Date'.tr}: $carBackLicenseExpired', style: TextStyle( color: isInspectionExpired ? Colors.red : Colors.green, ), ), ], ), ], ), ), ); } return Card( child: InkWell( onTap: () async { ai.allMethodForAI((ai.prompts[4]['prompt'].toString()), AppLink.uploadEgypt, 'car_back'); }, child: Column( children: [ Image.asset( 'assets/images/4.png', height: Get.height * .25, width: double.maxFinite, fit: BoxFit.fitHeight, ), Text( 'Capture an Image of Your car license back'.tr, style: AppStyle.title, ), ], ), ), ); }, ); } ================================================== FILE PATH: ./lib/views/home/profile/taarif_page.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; class TaarifPage extends StatelessWidget { const TaarifPage({super.key}); @override Widget build(BuildContext context) { return MyScafolld(isleading: true, title: 'Tariffs'.tr, body: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: ListView( // mainAxisAlignment: MainAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.stretch, clipBehavior: Clip.hardEdge, children: [ Table( defaultVerticalAlignment: TableCellVerticalAlignment.middle, border: TableBorder.symmetric(), textBaseline: TextBaseline.alphabetic, children: [ TableRow( // decoration: AppStyle.boxDecoration, children: [ Text('Minimum fare'.tr, style: AppStyle.title), box.read(BoxName.countryCode) == 'Jordan' ? Text('1 ${'JOD'.tr}', style: AppStyle.title) : Text('20 ${'LE'.tr}', style: AppStyle.title), ], ), TableRow( children: [ Text('Maximum fare'.tr, style: AppStyle.title), box.read(BoxName.countryCode) == 'Jordan' ? Text('200 ${'JOD'.tr}', style: AppStyle.title) : Text('15000 ${'LE'.tr}', style: AppStyle.title), ], ), TableRow( children: [ Text('Flag-down fee'.tr, style: AppStyle.title), box.read(BoxName.countryCode) == 'Jordan' ? Text('0.47 ${'JOD'.tr}', style: AppStyle.title) : Text('15 ${'LE'.tr}', style: AppStyle.title), ], ), TableRow( children: [ box.read(BoxName.countryCode) == 'Jordan' ? Text('0.05 ${'JOD'.tr}/min and 0.21 ${'JOD'.tr}/km', style: AppStyle.title) : Text('1 ${'LE'.tr}/min and 4 ${'LE'.tr}/km', style: AppStyle.title), Text('Including Tax'.tr, style: AppStyle.title), ], ), ], ), const SizedBox(height: 10), Text('BookingFee'.tr, style: AppStyle.headTitle2), const SizedBox(height: 10), Text('10%', style: AppStyle.title), const SizedBox(height: 20), Text('Morning'.tr, style: AppStyle.headTitle2), const SizedBox(height: 10), Text( 'from 07:30 till 10:30 (Thursday, Friday, Saturday, Monday)'.tr, style: AppStyle.title), const SizedBox(height: 20), Text('Evening'.tr, style: AppStyle.headTitle2), const SizedBox(height: 10), Text( 'from 12:00 till 15:00 (Thursday, Friday, Saturday, Monday)'.tr, style: AppStyle.title), const SizedBox(height: 20), Text('Night'.tr, style: AppStyle.headTitle2), const SizedBox(height: 10), Text('from 23:59 till 05:30'.tr, style: AppStyle.title), ], ), ), ]); } } ================================================== FILE PATH: ./lib/views/home/profile/promos_passenger_page.dart ================================================== import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/profile/promos_controller.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import '../../../constant/colors.dart'; import '../../../constant/style.dart'; import '../../widgets/mycircular.dart'; class PromosPassengerPage extends StatelessWidget { const PromosPassengerPage({super.key}); @override Widget build(BuildContext context) { Get.put(PromosController()); return MyScafolld( title: 'Promos For today'.tr, isleading: true, body: [ GetBuilder( builder: (orderHistoryController) => orderHistoryController.isLoading ? const MyCircularProgressIndicator() : ListView.builder( itemCount: orderHistoryController.promoList.length, itemBuilder: (BuildContext context, int index) { final rides = orderHistoryController.promoList[index]; return Padding( padding: const EdgeInsets.all(8.0), child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), color: AppColor.secondaryColor, boxShadow: [ BoxShadow( color: AppColor.accentColor, offset: Offset(-3, -3), blurRadius: 0, spreadRadius: 0, blurStyle: BlurStyle.outer), BoxShadow( color: AppColor.accentColor, offset: Offset(3, 3), blurRadius: 0, spreadRadius: 0, blurStyle: BlurStyle.outer) ]), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AnimatedTextKit( animatedTexts: [ ScaleAnimatedText(rides['promo_code'], textStyle: AppStyle.title), WavyAnimatedText(rides['promo_code'], textStyle: AppStyle.title), FlickerAnimatedText( rides['promo_code'], textStyle: AppStyle.title), WavyAnimatedText(rides['promo_code'], textStyle: AppStyle.title), ], isRepeatingAnimation: true, onTap: () {}, ), Text( rides['description'], style: AppStyle.title, ), ], ), Column( children: [ Text( rides['validity_start_date'], style: AppStyle.title, ), Text( rides['validity_end_date'], style: AppStyle.title, ), ], ), ], ), Text( 'Copy this Promo to use it in your Ride!'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2 .copyWith(color: AppColor.accentColor), ) ], ), ), ), ); }, ), ) ], ); } } ================================================== FILE PATH: ./lib/views/home/profile/captains_cars.dart ================================================== import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import '../../auth/captin/driver_car_controller.dart'; import '../../widgets/elevated_btn.dart'; import 'cars_inserting_page.dart'; class CaptainsCars extends StatelessWidget { const CaptainsCars({super.key}); @override Widget build(BuildContext context) { Get.put(DriverCarController()); return MyScafolld( title: "Add new car".tr, body: [ Column( children: [ MyElevatedButton( title: "Add new car".tr, onPressed: () async { Get.to(() => CarsInsertingPage()); }, ), Expanded( child: GetBuilder( builder: (controller) { return controller.isLoading ? const MyCircularProgressIndicator() : ListView.builder( itemCount: controller.cars.length, itemBuilder: (context, index) { final car = controller.cars[index]; return Padding( padding: const EdgeInsets.all(4.0), child: Card( color: car['isDefault'].toString() == '0' ? AppColor.accentColor : AppColor.blueColor, elevation: 2, child: ListTile( leading: Icon( Fontisto.car, size: 50, color: Color(int.parse(car['color_hex'] .replaceFirst('#', '0xff'))), ), title: Text( car['make'], style: AppStyle.title, ), // Assuming `make` is a field in each car item subtitle: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( car['model'], style: AppStyle.title, ), Container( decoration: BoxDecoration( border: Border.all( color: AppColor.blueColor)), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 4), child: Text( (car['car_plate']), style: AppStyle.title, ), ), ), Text( car['year'], style: AppStyle.title, ), ], ), // Assuming `model` is a field in each car item // trailing: IconButton( // icon: const Icon( // Icons.delete, // color: AppColor.redColor, // ), // onPressed: () { // // Add logic here to remove a car // MyDialog() // .getDialog('Are you sure to delete this car', '', () { // controller // .removeCar(car['id'].toString()); // }); // }, // ), onTap: () { MyDialog().getDialog( 'Are you sure to make this car as default' .tr, '', () { Get.back(); //make it default controller.updateCarRegistration( car['id'].toString(), box.read(BoxName.driverID).toString(), ); }); // Add logic to view or edit the car details }, ), ), ); }, ); }, ), ), ], ) ], isleading: true); } } ================================================== FILE PATH: ./lib/views/home/profile/passenger_profile_page.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/profile/profile_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/functions/log_out.dart'; class PassengerProfilePage extends StatelessWidget { PassengerProfilePage({super.key}); LogOutController logOutController = Get.put(LogOutController()); @override Widget build(BuildContext context) { Get.put(ProfileController()); return MyScafolld( isleading: true, title: 'My Profile'.tr, body: [ GetBuilder( builder: (controller) => controller.isloading ? const MyCircularProgressIndicator() : Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: SizedBox( height: Get.height, child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Edit Profile'.tr, style: AppStyle.headTitle2, ), ListTile( title: Text( 'Name'.tr, style: AppStyle.title, ), leading: const Icon( Icons.person_pin_rounded, size: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text( '${controller.prfoileData['first_name']} ${controller.prfoileData['last_name']}'), onTap: () { controller.updatField( 'first_name', TextInputType.name); }, ), ListTile( title: Text( 'Gender'.tr, style: AppStyle.title, ), leading: Image.asset( 'assets/images/gender.png', width: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text( controller.prfoileData['gender'].toString()), onTap: () { Get.defaultDialog( title: 'Update Gender'.tr, content: Column( children: [ GenderPicker(), MyElevatedButton( title: 'Update'.tr, onPressed: () { controller.updateColumn({ 'id': controller.prfoileData['id'] .toString(), 'gender': controller.gender, }); Get.back(); }, ) ], )); // controller.updatField('gender'); }, ), ListTile( title: Text( 'Education'.tr, style: AppStyle.title, ), leading: Image.asset( 'assets/images/education.png', width: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text(controller.prfoileData['education'] .toString()), onTap: () { Get.defaultDialog( barrierDismissible: true, title: 'Update Education'.tr, content: SizedBox( height: 200, child: Column( children: [ EducationDegreePicker(), ], ), ), confirm: MyElevatedButton( title: 'Update Education'.tr, onPressed: () { controller.updateColumn({ 'id': controller.prfoileData['id'] .toString(), 'education': controller.selectedDegree, }); Get.back(); }, )); }, ), ListTile( title: Text( 'Employment Type'.tr, style: AppStyle.title, ), leading: Image.asset( 'assets/images/employmentType.png', width: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text(controller .prfoileData['employmentType'] .toString()), onTap: () { controller.updatField( 'employmentType', TextInputType.name); }, ), ListTile( title: Text( 'Marital Status'.tr, style: AppStyle.title, ), leading: Image.asset( 'assets/images/maritalStatus.png', width: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text(controller .prfoileData['maritalStatus'] .toString()), onTap: () { controller.updatField( 'maritalStatus', TextInputType.name); }, ), ListTile( title: Text( 'SOS Phone'.tr, style: AppStyle.title, ), leading: const Icon( Icons.sos, color: AppColor.redColor, size: 35, ), trailing: const Icon(Icons.arrow_forward_ios), subtitle: Text(controller.prfoileData['sosPhone'] .toString()), onTap: () async { await controller.updatField( 'sosPhone', TextInputType.phone); box.write(BoxName.sosPhonePassenger, controller.prfoileData['sosPhone']); }, ), // const Spacer(), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ MyElevatedButton( title: 'Sign Out'.tr, onPressed: () { LogOutController().logOutPassenger(); }), GetBuilder( builder: (logOutController) { return MyElevatedButton( title: 'Delete My Account'.tr, onPressed: () { Get.defaultDialog( title: 'Are you sure to delete your account?' .tr, content: Form( key: logOutController.formKey1, child: MyTextForm( controller: logOutController .emailTextController, label: 'Type your Email'.tr, hint: 'Type your Email'.tr, type: TextInputType.emailAddress, ), ), confirm: MyElevatedButton( title: 'Delete My Account'.tr, kolor: AppColor.redColor, onPressed: () async { await logOutController .deletePassengerAccount(); }), cancel: MyElevatedButton( title: 'No I want'.tr, onPressed: () { logOutController .emailTextController .clear(); logOutController.update(); Get.back(); })); }); }), ], ), ], ), ), ), )), ], ); } } class GenderPicker extends StatelessWidget { final ProfileController controller = Get.put(ProfileController()); final List genderOptions = ['Male'.tr, 'Female'.tr, 'Other'.tr]; GenderPicker({super.key}); @override Widget build(BuildContext context) { return SizedBox( height: 100, child: CupertinoPicker( itemExtent: 32.0, onSelectedItemChanged: (int index) { controller.setGender(genderOptions[index]); }, children: genderOptions.map((String value) { return Text(value); }).toList(), ), ); } } class EducationDegreePicker extends StatelessWidget { final ProfileController controller = Get.put(ProfileController()); final List degreeOptions = [ 'High School Diploma'.tr, 'Associate Degree'.tr, 'Bachelor\'s Degree'.tr, 'Master\'s Degree'.tr, 'Doctoral Degree'.tr, ]; EducationDegreePicker({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 200, child: CupertinoPicker( // backgroundColor: AppColor.accentColor, // looping: true, squeeze: 2, // diameterRatio: 5, itemExtent: 32, onSelectedItemChanged: (int index) { controller.setDegree(degreeOptions[index]); }, children: degreeOptions.map((String value) { return Text(value); }).toList(), ), ); } } ================================================== FILE PATH: ./lib/views/home/profile/feed_back_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/home/profile/feed_back_controller.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../widgets/elevated_btn.dart'; class FeedBackPage extends StatelessWidget { FeedBackPage({super.key}); FeedBackController feedBackController = Get.put(FeedBackController()); @override Widget build(BuildContext context) { return MyScafolld( title: 'Feed Back'.tr, body: [ Padding( padding: const EdgeInsets.all(26), child: Form( key: feedBackController.formKey, child: Column( children: [ TextFormField( controller: feedBackController.feedbackController, decoration: InputDecoration( border: const OutlineInputBorder(), hintText: 'Enter your feedback here'.tr, labelText: 'Feedback', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your feedback.'; } return null; }, ), const SizedBox(height: 20), feedBackController.isLoading ? const MyCircularProgressIndicator() : MyElevatedButton( onPressed: () { if (feedBackController.formKey.currentState! .validate()) { feedBackController.addFeedBack(); // Clear the feedback form feedBackController.formKey.currentState!.reset(); } }, title: 'Submit '.tr, ), ], ), ), ), ], isleading: true, ); } } ================================================== FILE PATH: ./lib/views/home/profile/behavior_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../controller/home/captin/behavior_controller.dart'; class BehaviorPage extends StatelessWidget { const BehaviorPage({ super.key, }); @override Widget build(BuildContext context) { final controller = Get.put(DriverBehaviorController()); controller.fetchDriverBehavior(); return Scaffold( appBar: AppBar( title: Text('Driver Behavior'.tr), centerTitle: true, ), body: Obx(() { if (controller.isLoading.value) { return const Center(child: CircularProgressIndicator()); } return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), elevation: 4, child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Text("Overall Behavior Score".tr, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 10), Text( "${controller.overallScore.value.toStringAsFixed(1)} / 100", style: const TextStyle( fontSize: 28, color: Colors.blue)), ], ), ), ), const SizedBox(height: 20), Text("Last 10 Trips".tr, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 10), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: controller.lastTrips.length, itemBuilder: (context, index) { var trip = controller.lastTrips[index]; return Card( elevation: 3, child: ListTile( leading: CircleAvatar( backgroundColor: Colors.blue, child: Text("${index + 1}", style: const TextStyle(color: Colors.white)), ), title: Text("Trip ID: ${trip['trip_id']}"), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${'Behavior Score'.tr}: ${trip['behavior_score']}"), Text("${'Max Speed'.tr}: ${trip['max_speed']} km/h"), Text("${'Hard Brake'.tr}s: ${trip['hard_brakes']}"), Text( "${'Distance'.tr}: ${trip['total_distance']} km"), ], ), ), ); }, ), ], ), ); }), ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/weekly_payment_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/payment/driver_payment_controller.dart'; class WeeklyPaymentPage extends StatelessWidget { const WeeklyPaymentPage({super.key}); @override Widget build(BuildContext context) { Get.put(DriverWalletHistoryController()); return Scaffold( appBar: AppBar( title: Text('Weekly Summary'.tr), backgroundColor: Colors.white, elevation: 1, ), backgroundColor: Colors.grey[100], body: GetBuilder( builder: (controller) { if (controller.isLoading) { return const Center(child: MyCircularProgressIndicator()); } return Column( children: [ // 1. Prominent Summary Card at the top _buildSummaryCard(controller), // 2. A title for the transactions list Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 10), child: Row( children: [ Icon(Icons.list_alt, color: Colors.grey[600]), const SizedBox(width: 8), Text( 'Transactions this week'.tr, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: Colors.grey[700], ), ), ], ), ), // 3. The animated list of transactions Expanded( child: controller.weeklyList.isEmpty ? _buildEmptyState(context) : AnimationLimiter( child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16.0), itemCount: controller.weeklyList.length, itemBuilder: (BuildContext context, int index) { var transaction = controller.weeklyList[index]; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: _TransactionListItem( transaction: transaction), ), ), ); }, ), ), ), ], ); }, ), ); } // A widget for the top summary card. Widget _buildSummaryCard(DriverWalletHistoryController controller) { final String totalAmount = controller.weeklyList.isEmpty ? '0.00' : controller.weeklyList[0]['totalAmount']?.toString() ?? '0.00'; return Card( margin: const EdgeInsets.all(16.0), elevation: 4, shadowColor: AppColor.primaryColor.withOpacity(0.2), clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), child: Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( gradient: LinearGradient( colors: [AppColor.primaryColor, AppColor.greenColor], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: Row( children: [ const Icon(Icons.account_balance_wallet, color: Colors.white, size: 40), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Total Weekly Earnings'.tr, style: AppStyle.title .copyWith(color: Colors.white70, fontSize: 16), ), const SizedBox(height: 4), Text( '$totalAmount ${'SYP'.tr}', style: AppStyle.number .copyWith(color: Colors.white, fontSize: 32), ), ], ), ), ], ), ), ); } // A dedicated widget for the list item. Widget _TransactionListItem({required Map transaction}) { final String paymentMethod = transaction['paymentMethod'] ?? 'Unknown'; final String amount = transaction['amount']?.toString() ?? '0'; final DateTime? date = DateTime.tryParse(transaction['dateUpdated'] ?? ''); return Card( elevation: 2, shadowColor: Colors.black.withOpacity(0.05), margin: const EdgeInsets.only(bottom: 12.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: ListTile( leading: CircleAvatar( backgroundColor: AppColor.primaryColor.withOpacity(0.1), child: Icon(_getPaymentIcon(paymentMethod), color: AppColor.primaryColor, size: 22), ), title: Text( '$amount ${'SYP'.tr}', style: AppStyle.title.copyWith(fontWeight: FontWeight.bold), ), subtitle: Text( date != null ? DateFormat('EEEE, hh:mm a', Get.locale?.toString()) .format(date) // e.g., Tuesday, 10:11 AM : 'Invalid Date', style: AppStyle.title.copyWith(fontSize: 12, color: Colors.grey[600]), ), trailing: Chip( label: Text( _getTranslatedPaymentMethod(paymentMethod), style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600), ), backgroundColor: Colors.grey.shade200, padding: const EdgeInsets.symmetric(horizontal: 6), side: BorderSide.none, ), ), ); } Widget _buildEmptyState(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.receipt_long_outlined, size: 80, color: Colors.grey[400]), const SizedBox(height: 16), Text( 'No transactions this week'.tr, style: Theme.of(context) .textTheme .headlineSmall ?.copyWith(color: Colors.grey[600]), ), ], ), ); } // Helper to get a specific icon for each payment method. IconData _getPaymentIcon(String paymentMethod) { switch (paymentMethod.toLowerCase()) { case 'visa': return Icons.credit_card; case 'frombudget': return Icons.account_balance_wallet_outlined; case 'remainder': return Icons.receipt_long; case 'cash': return Icons.money; default: return Icons.payment; } } // Helper to get translated or formatted payment method names. String _getTranslatedPaymentMethod(String paymentMethod) { switch (paymentMethod) { case 'Remainder': return 'Remainder'.tr; case 'fromBudget': return 'From Budget'.tr; default: return paymentMethod; } } } ================================================== FILE PATH: ./lib/views/home/my_wallet/bank_account_egypt.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; class BankController extends GetxController { String selectedBank = ''; Map bankNames = { 'Ahli United Bank'.tr: 'AUB', 'Citi Bank N.A. Egypt'.tr: 'CITI', 'MIDBANK'.tr: 'MIDB', 'Banque Du Caire'.tr: 'BDC', 'HSBC Bank Egypt S.A.E'.tr: 'HSBC', 'Credit Agricole Egypt S.A.E'.tr: 'ECAE', 'Egyptian Gulf Bank'.tr: 'EGB', 'The United Bank'.tr: 'UB', 'Qatar National Bank Alahli'.tr: 'QNB', 'Arab Bank PLC'.tr: 'ARAB', 'Emirates National Bank of Dubai'.tr: 'ENBD', 'Al Ahli Bank of Kuwait – Egypt'.tr: 'ABK', 'National Bank of Kuwait – Egypt'.tr: 'NBK', 'Arab Banking Corporation - Egypt S.A.E'.tr: 'EABC', 'First Abu Dhabi Bank'.tr: 'FAB', 'Abu Dhabi Islamic Bank – Egypt'.tr: 'ADIB', 'Commercial International Bank - Egypt S.A.E'.tr: 'CIB', 'Housing And Development Bank'.tr: 'HDB', 'Banque Misr'.tr: 'MISR', 'Arab African International Bank'.tr: 'AAIB', 'Egyptian Arab Land Bank'.tr: 'EALB', 'Export Development Bank of Egypt'.tr: 'EDBE', 'Faisal Islamic Bank of Egypt'.tr: 'FAIB', 'Blom Bank'.tr: 'BLOM', 'Abu Dhabi Commercial Bank – Egypt'.tr: 'ADCB', 'Alex Bank Egypt'.tr: 'BOA', 'Societe Arabe Internationale De Banque'.tr: 'SAIB', 'National Bank of Egypt'.tr: 'NBE', 'Al Baraka Bank Egypt B.S.C.'.tr: 'ABRK', 'Egypt Post'.tr: 'POST', 'Nasser Social Bank'.tr: 'NSB', 'Industrial Development Bank'.tr: 'IDB', 'Suez Canal Bank'.tr: 'SCB', 'Mashreq Bank'.tr: 'MASHA', 'Arab Investment Bank'.tr: 'AIB', 'General Authority For Supply Commodities'.tr: 'GASCA', 'Arab International Bank'.tr: 'AIB', 'Agricultural Bank of Egypt'.tr: 'PDAC', 'National Bank of Greece'.tr: 'NBG', 'Central Bank Of Egypt'.tr: 'CBE', 'ATTIJARIWAFA BANK Egypt'.tr: 'BBE', }; @override void onInit() { super.onInit(); selectedBank = bankNames.values.first; } void updateSelectedBank(String? bankShortName) { selectedBank = bankShortName ?? ''; update(); } List> getDropdownItems() { return bankNames.keys.map>((bankFullName) { return DropdownMenuItem( value: bankNames[bankFullName], child: Text(bankFullName), ); }).toList(); } void showBankPicker(BuildContext context) { showCupertinoModalPopup( context: context, builder: (BuildContext context) => CupertinoActionSheet( title: Text('Select a Bank'.tr), actions: bankNames.keys.map((String bankFullName) { return CupertinoActionSheetAction( child: Text(bankFullName), onPressed: () { updateSelectedBank(bankNames[bankFullName]); Navigator.pop(context); }, ); }).toList(), cancelButton: CupertinoActionSheetAction( child: Text('Cancel'.tr), onPressed: () { Navigator.pop(context); }, ), ), ); } } class BankDropdown extends StatelessWidget { final BankController bankController = Get.put(BankController()); @override Widget build(BuildContext context) { return GetBuilder( init: bankController, builder: (controller) { return CupertinoButton( padding: EdgeInsets.zero, onPressed: () => controller.showBankPicker(context), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( border: Border.all(color: CupertinoColors.systemGrey4), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( controller.selectedBank != null ? controller.bankNames.keys.firstWhere( (key) => controller.bankNames[key] == controller.selectedBank, orElse: () => 'Select a Bank'.tr, ) : 'Select a Bank'.tr, style: TextStyle( color: controller.selectedBank != null ? CupertinoColors.black : CupertinoColors.systemGrey, ), ), const Icon(CupertinoIcons.chevron_down, size: 20), ], ), ), ); }, ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/ecash.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:local_auth/local_auth.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../constant/style.dart'; import '../../../controller/functions/crud.dart'; import '../../../main.dart'; // --- ملاحظات هامة --- // 1. تأكد من إضافة الرابط الجديد إلى ملف AppLink الخاص بك: // static const String payWithEcashDriver = "$server/payment/payWithEcashDriver.php"; // // 2. تأكد من أنك تخزن 'driverId' في الـ box الخاص بك، مثلاً: // box.read(BoxName.driverID) /// دالة جديدة لبدء عملية الدفع للسائق عبر ecash Future payWithEcashDriver(BuildContext context, String amount) async { try { // يمكنك استخدام نفس طريقة التحقق بالبصمة إذا أردت bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment'.tr, ); if (didAuthenticate) { // استدعاء الـ Endpoint الجديد على السيرفر الخاص بك var res = await CRUD().postWallet( link: AppLink.payWithEcashDriver, payload: { // أرسل البيانات التي يحتاجها السيرفر "amount": amount, // "driverId": box.read(BoxName.driverID), // تأكد من وجود هذا المتغير "driverId": box.read(BoxName.driverID), // تأكد من وجود هذا المتغير }, ); // التأكد من أن السيرفر أعاد رابط الدفع بنجاح if (res != null && res['status'] == 'success' && res['message'] != null) { final String paymentUrl = res['message']; // الانتقال إلى شاشة الدفع الجديدة الخاصة بـ ecash للسائق Navigator.push( context, MaterialPageRoute( builder: (context) => EcashDriverPaymentScreen(paymentUrl: paymentUrl), ), ); } else { // عرض رسالة خطأ في حال فشل السيرفر في إنشاء الرابط Get.defaultDialog( title: 'Error'.tr, content: Text( 'Failed to initiate payment. Please try again.'.tr, style: AppStyle.title, ), ); } } } } catch (e) { Get.defaultDialog( title: 'Error'.tr, content: Text( 'An error occurred during the payment process.'.tr, style: AppStyle.title, ), ); } } /// شاشة جديدة ومبسطة خاصة بدفع السائقين عبر ecash class EcashDriverPaymentScreen extends StatefulWidget { final String paymentUrl; const EcashDriverPaymentScreen({required this.paymentUrl, Key? key}) : super(key: key); @override State createState() => _EcashDriverPaymentScreenState(); } class _EcashDriverPaymentScreenState extends State { late final WebViewController _controller; @override void initState() { super.initState(); _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate(NavigationDelegate( onPageFinished: (url) { print('Ecash Driver WebView URL Finished: $url'); // هنا نتحقق فقط من أن المستخدم عاد إلى صفحة النجاح // لا حاجة لاستدعاء أي API هنا، فالـ Webhook يقوم بكل العمل if (url.contains("success.php")) { showProcessingDialog(); } }, )) ..loadRequest(Uri.parse(widget.paymentUrl)); } // دالة لعرض رسالة "العملية قيد المعالجة" void showProcessingDialog() { showDialog( barrierDismissible: false, context: Get.context!, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), title: Row( children: [ Icon(Icons.check_circle, color: Colors.green), const SizedBox(width: 8), Text( "Payment Successful".tr, style: TextStyle( color: Colors.green, fontWeight: FontWeight.bold, ), ), ], ), content: Text( "Your payment is being processed and your wallet will be updated shortly." .tr, style: const TextStyle(fontSize: 16), ), actions: [ TextButton( onPressed: () { // أغلق مربع الحوار، ثم أغلق شاشة الدفع Navigator.pop(context); // Close the dialog Navigator.pop(context); // Close the payment screen }, style: TextButton.styleFrom( backgroundColor: Colors.green, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), child: Text( "OK".tr, style: const TextStyle(color: Colors.white), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Complete Payment'.tr)), body: WebViewWidget(controller: _controller), ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/walet_captain.dart ================================================== import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:sefer_driver/controller/functions/tts.dart'; import 'package:sefer_driver/views/home/my_wallet/payment_history_driver_page.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/info.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/payment/driver_payment_controller.dart'; import '../../widgets/my_scafold.dart'; import 'card_wallet_widget.dart'; import 'points_captain.dart'; import 'transfer_budget_page.dart'; import 'weekly_payment_page.dart'; class WalletCaptainRefactored extends StatelessWidget { WalletCaptainRefactored({super.key}); final CaptainWalletController captainWalletController = Get.put(CaptainWalletController()); // دالة مساعدة لتحديد لون خلفية النقاط Color _getPointsColor(String pointsStr) { final points = double.tryParse(pointsStr) ?? 0.0; if (points < -30000) { return AppColor.redColor; } else if (points < 0 && points >= -30000) { return AppColor.yellowColor; } else { return AppColor.greenColor; } } @override Widget build(BuildContext context) { captainWalletController.refreshCaptainWallet(); return MyScafolld( title: 'Driver Balance'.tr, isleading: true, action: IconButton( icon: const Icon(Icons.refresh), onPressed: () => captainWalletController.refreshCaptainWallet(), tooltip: 'Refresh'.tr, ), body: [ GetBuilder( builder: (controller) { if (controller.isLoading) { return const MyCircularProgressIndicator(); } return SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildTotalPointsSection(context, controller), const SizedBox(height: 16), const CardSeferWalletDriver(), // This can be redesigned if needed const SizedBox(height: 16), _buildWalletDetailsCard(context, controller), const SizedBox(height: 24), _buildPromoSection(controller), const SizedBox(height: 24), _buildNavigationButtons(), ], ), ); }, ) ], ); } /// القسم العلوي لعرض النقاط الإجمالية Widget _buildTotalPointsSection( BuildContext context, CaptainWalletController controller) { return Card( elevation: 4, color: _getPointsColor(controller.totalPoints.toString()), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: InkWell( onTap: () { showCupertinoDialog( context: context, builder: (BuildContext context) => CupertinoAlertDialog( title: Text('Info'.tr), content: Text( 'The 30000 points equal 30000 S.P for you \nSo go and gain your money' .tr), actions: [ CupertinoDialogAction( child: Text("OK".tr), onPressed: () => Navigator.of(context).pop(), ), ], ), ); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: Column( children: [ Text( 'رصيد التشغيل 💎', style: AppStyle.headTitle2.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( controller.totalPoints.toString(), style: AppStyle.headTitle2.copyWith( color: Colors.white, fontSize: 28, fontWeight: FontWeight.w900), textAlign: TextAlign.center, ), if (double.parse(controller.totalPoints.toString()) < -30000) Padding( padding: const EdgeInsets.only(top: 12.0), child: CupertinoButton( color: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 20), onPressed: () { // Add your charge account logic here }, child: Text( 'Charge your Account'.tr, style: TextStyle( color: AppColor.redColor, fontWeight: FontWeight.bold), ), ), ), ], ), ), ), ); } /// بطاقة لعرض تفاصيل المحفظة وخيارات الشراء Widget _buildWalletDetailsCard( BuildContext context, CaptainWalletController controller) { return Card( elevation: 4, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _BudgetInfoRow( title: 'Total Budget from trips is '.tr, amount: controller.totalAmount, onTap: () { Get.snackbar( icon: InkWell( onTap: () async => await Get.put(TextToSpeechController()) .speakText( 'This amount for all trip I get from Passengers' .tr), child: const Icon(Icons.headphones)), '${'Total Amount:'.tr} ${controller.totalAmount} ${'SYP'.tr}', 'This amount for all trip I get from Passengers'.tr, duration: const Duration(seconds: 6), backgroundColor: AppColor.yellowColor, snackPosition: SnackPosition.BOTTOM, ); }, ), const Divider(height: 32), _BudgetInfoRow( title: 'Total Budget from trips by\nCredit card is '.tr, amount: controller.totalAmountVisa, onTap: () { Get.snackbar( icon: InkWell( onTap: () async => await Get.find() .speakText( 'This amount for all trip I get from Passengers and Collected For me in' .tr + ' Intaleq Wallet'.tr), child: const Icon(Icons.headphones), ), '${'Total Amount:'.tr} ${controller.totalAmountVisa} ${'SYP'.tr}', 'This amount for all trip I get from Passengers and Collected For me in' .tr + ' ${AppInformation.appName} Wallet'.tr, duration: const Duration(seconds: 6), backgroundColor: AppColor.redColor, snackPosition: SnackPosition.BOTTOM, ); }, ), const SizedBox(height: 24), _buildBuyPointsButton(controller), const SizedBox(height: 16), // _buildTransferBudgetButton(controller), // Uncomment if needed _buildPurchaseInstructions(), const SizedBox(height: 8), _buildPointsOptions(), ], ), ), ); } /// قسم العروض الترويجية Widget _buildPromoSection(CaptainWalletController controller) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Today's Promo".tr, style: AppStyle.headTitle), const SizedBox(height: 10), _PromoProgressCard( title: 'Morning Promo'.tr, timePromo: 'Morning Promo', count: (controller.walletDate['message'][0]['morning_count']), maxCount: 5, description: "this is count of your all trips in the morning promo today from 7:00am to 10:00am" .tr, controller: controller, ), const SizedBox(height: 16), _PromoProgressCard( title: 'Afternoon Promo'.tr, timePromo: 'Afternoon Promo', count: (controller.walletDate['message'][0]['afternoon_count']), maxCount: 5, description: "this is count of your all trips in the Afternoon promo today from 3:00pm to 6:00 pm" .tr, controller: controller, ), ], ); } /// أزرار التنقل السفلية Widget _buildNavigationButtons() { return Row( children: [ Expanded( child: MyElevatedButton( kolor: AppColor.blueColor, title: 'Payment History'.tr, onPressed: () async { await Get.put(DriverWalletHistoryController()) .getArchivePayment(); Get.to(() => const PaymentHistoryDriverPage(), transition: Transition.size); }, ), ), const SizedBox(width: 16), Expanded( child: MyElevatedButton( kolor: AppColor.blueColor, title: 'Weekly Budget'.tr, onPressed: () async { await Get.put(DriverWalletHistoryController()) .getWeekllyArchivePayment(); Get.to(() => const WeeklyPaymentPage(), transition: Transition.size); }, ), ), ], ); } // --- حافظت على هذه الدوال كما هي لأنها تحتوي على منطق مهم --- Widget _buildBuyPointsButton(CaptainWalletController controller) { return MyElevatedButton( title: 'You can buy points from your budget'.tr, onPressed: () { Get.defaultDialog( title: 'Pay from my budget'.tr, content: Form( key: controller.formKey, child: MyTextForm( controller: controller.amountFromBudgetController, label: '${'You have in account'.tr} ${controller.totalAmountVisa}', hint: '${'You have in account'.tr} ${controller.totalAmountVisa}', type: TextInputType.number, ), ), confirm: MyElevatedButton( title: 'Pay'.tr, onPressed: () async { bool isAvailable = await LocalAuthentication().isDeviceSupported(); if (isAvailable) { // Authenticate the user bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'Use Touch ID or Face ID to confirm payment'.tr, options: const AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, )); if (didAuthenticate) { if (double.parse(controller.amountFromBudgetController.text) < double.parse(controller.totalAmountVisa)) { await controller.payFromBudget(); } else { Get.back(); mySnackeBarError('Your Budget less than needed'.tr); } } else { // Authentication failed, handle accordingly MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); }); } } else { MyDialog().getDialog('Biometric Authentication'.tr, 'You should use Touch ID or Face ID to confirm payment'.tr, () { Get.back(); }); } }, ), cancel: MyElevatedButton( title: 'Cancel'.tr, onPressed: () { Get.back(); }, ), ); }, ); } Widget _buildPurchaseInstructions() { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColor.accentColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.accentColor.withOpacity(0.3)), ), child: Column( children: [ Text( "You can purchase a budget to enable online access through the options listed below" .tr, textAlign: TextAlign.center, style: AppStyle.title.copyWith(fontSize: 14), ), ], ), ), ); } Widget _buildPointsOptions() { return SizedBox( height: Get.height * 0.19, child: ListView( scrollDirection: Axis.horizontal, children: [ PointsCaptain( kolor: AppColor.greyColor, pricePoint: 100, countPoint: '100'), PointsCaptain( kolor: AppColor.bronze, pricePoint: 200, countPoint: '210'), PointsCaptain( kolor: AppColor.goldenBronze, pricePoint: 400, countPoint: '450'), PointsCaptain( kolor: AppColor.gold, pricePoint: 1000, countPoint: '1100'), ], ), ); } } /// ويدجت مُحسّن لعرض صف معلومات الرصيد class _BudgetInfoRow extends StatelessWidget { final String title; final String amount; final VoidCallback onTap; const _BudgetInfoRow({ required this.title, required this.amount, required this.onTap, }); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( title, style: AppStyle.title.copyWith(fontSize: 16), ), ), const SizedBox(width: 10), Container( decoration: BoxDecoration( color: AppColor.accentColor.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Text( '$amount ${'S.P'.tr}', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ), ], ), ), ); } } /// ويدجت مُحسّن لعرض بطاقة العرض الترويجي class _PromoProgressCard extends StatelessWidget { final String title; final String timePromo; final int count; final int maxCount; final String description; final CaptainWalletController controller; const _PromoProgressCard({ required this.title, required this.timePromo, required this.count, required this.maxCount, required this.description, required this.controller, }); @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), clipBehavior: Clip.antiAlias, child: InkWell( onTap: () { MyDialog().getDialog(title, description, () async { if (count >= maxCount) { controller.addDriverWalletFromPromo(timePromo, 50); } Get.back(); }); }, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)), Text( '$count / $maxCount', style: AppStyle.title.copyWith(color: AppColor.blueColor), ), ], ), const SizedBox(height: 12), ClipRRect( borderRadius: BorderRadius.circular(10), child: LinearProgressIndicator( minHeight: 12, value: count / maxCount, backgroundColor: AppColor.accentColor.withOpacity(0.2), color: count >= maxCount ? AppColor.greenColor : AppColor.blueColor, ), ), ], ), ), ), ); } } // --- الدوال والويدجتس الخاصة بالدفع في سوريا تبقى كما هي --- // This function is a placeholder for adding Syrian payment methods. // You would implement the UI and logic for mobile wallets or other local options here. Future addSyrianPaymentMethod( CaptainWalletController captainWalletController) { return Get.defaultDialog( title: "Insert Payment Details".tr, content: Form( key: captainWalletController.formKeyAccount, child: Column( children: [ Text( "Insert your mobile wallet details to receive your money weekly" .tr), MyTextForm( controller: captainWalletController .cardBank, // Re-using for mobile number label: "Insert mobile wallet number".tr, hint: '0912 345 678', type: TextInputType.phone), const SizedBox( height: 10, ), MyDropDownSyria() // Dropdown for Syrian providers ], )), confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () async { if (captainWalletController.formKeyAccount.currentState! .validate()) { Get.back(); // Replace with your actual API endpoint and payload for Syria var res = await CRUD().post(link: AppLink.updateAccountBank, payload: { "paymentProvider": Get.find().dropdownValue.toString(), "accountNumber": captainWalletController.cardBank.text.toString(), "id": box.read(BoxName.driverID).toString() }); print('res: $res'); if (res != 'failure') { mySnackbarSuccess('Payment details added successfully'.tr); } } })); } // A new GetX controller for the Syrian payout dropdown class SyrianPayoutController extends GetxController { String dropdownValue = 'syriatel'; void changeValue(String? newValue) { if (newValue != null) { dropdownValue = newValue; update(); } } } // A new Dropdown widget for Syrian mobile wallet providers class MyDropDownSyria extends StatelessWidget { const MyDropDownSyria({super.key}); @override Widget build(BuildContext context) { Get.put(SyrianPayoutController()); return GetBuilder(builder: (controller) { return DropdownButton( value: controller.dropdownValue, icon: const Icon(Icons.arrow_drop_down), elevation: 16, isExpanded: true, style: const TextStyle(color: Colors.deepPurple), underline: Container( height: 2, color: Colors.deepPurpleAccent, ), onChanged: (String? newValue) { controller.changeValue(newValue); }, items: ['syriatel', 'mtn'] .map>((String value) { return DropdownMenuItem( value: value, child: Text(value.tr), ); }).toList(), ); }); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/points_captain.dart ================================================== import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:sefer_driver/controller/payment/payment_controller.dart'; import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../controller/functions/crud.dart'; import '../../../controller/payment/mtn_new/mtn_payment_new_screen.dart'; import '../../../main.dart'; import '../../../print.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/my_textField.dart'; import 'ecash.dart'; class PointsCaptain extends StatelessWidget { PaymentController paymentController = Get.put(PaymentController()); CaptainWalletController captainWalletController = Get.put(CaptainWalletController()); PointsCaptain({ super.key, required this.kolor, required this.countPoint, required this.pricePoint, }); final Color kolor; final String countPoint; double pricePoint; @override Widget build(BuildContext context) { return InkWell( onTap: () async { Get.defaultDialog( title: 'Which method you will pay'.tr, titleStyle: AppStyle.title, content: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${'you can buy '.tr}$countPoint ${'L.S'.tr}${'by '.tr}${'$pricePoint'.tr}', style: AppStyle.title, ), // Add some spacing between buttons GestureDetector( onTap: () async { Get.back(); payWithEcashDriver(context, pricePoint.toString()); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Pay with Debit Card'.tr), const SizedBox(width: 10), Icon(Icons.credit_card_sharp, color: AppColor.blueColor, size: 70), ], )), // GestureDetector( // onTap: () async { // Get.back(); // Get.defaultDialog( // barrierDismissible: false, // title: 'Insert Wallet phone number'.tr, // content: Form( // key: paymentController.formKey, // child: MyTextForm( // controller: // paymentController.walletphoneController, // label: 'Insert Wallet phone number'.tr, // hint: '963941234567', // type: TextInputType.phone)), // confirm: MyElevatedButton( // title: 'OK'.tr, // onPressed: () async { // Get.back(); // if (paymentController.formKey.currentState! // .validate()) { // box.write( // BoxName.phoneWallet, // paymentController // .walletphoneController.text); // await payWithMTNWallet( // context, pricePoint.toString(), 'SYP'); // } // })); // }, // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Text('Pay by MTN Wallet'.tr), // const SizedBox(width: 10), // Image.asset( // 'assets/images/cashMTN.png', // width: 70, // height: 70, // fit: BoxFit.fill, // ), // ], // )), GestureDetector( onTap: () async { Get.back(); Get.defaultDialog( barrierDismissible: false, title: 'Insert Wallet phone number'.tr, content: Form( key: paymentController.formKey, child: MyTextForm( controller: paymentController.walletphoneController, label: 'Insert Wallet phone number'.tr, hint: '963991234567', type: TextInputType.phone)), confirm: MyElevatedButton( title: 'OK'.tr, onPressed: () async { Get.back(); if (paymentController.formKey.currentState! .validate()) { box.write( BoxName.phoneWallet, paymentController .walletphoneController.text); await payWithSyriaTelWallet( context, pricePoint.toString(), 'SYP'); } })); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Pay by Syriatel Wallet'.tr), const SizedBox(width: 10), Image.asset( 'assets/images/syriatel.jpeg', width: 70, height: 70, fit: BoxFit.fill, ), ], )), GestureDetector( onTap: () async { // التحقق بالبصمة قبل أي شيء bool isAuthSupported = await LocalAuthentication().isDeviceSupported(); if (isAuthSupported) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', ); if (!didAuthenticate) { print("❌ User did not authenticate with biometrics"); return; } } // الانتقال مباشرة لإنشاء الفاتورة بعد النجاح بالبصمة Get.to( () => PaymentScreenSmsProvider(amount: pricePoint)); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Pay by Sham Cash'.tr), const SizedBox(width: 10), Image.asset( 'assets/images/shamCash.png', width: 70, height: 70, fit: BoxFit.fill, ), ], )), // GestureDetector( // onTap: () async { // Get.back(); // Get.defaultDialog( // barrierDismissible: false, // title: 'Insert Wallet phone number'.tr, // content: Form( // key: paymentController.formKey, // child: MyTextForm( // controller: // paymentController.walletphoneController, // label: 'Insert Wallet phone number'.tr, // hint: '963941234567', // type: TextInputType.phone)), // confirm: MyElevatedButton( // title: 'OK'.tr, // onPressed: () async { // Get.back(); // if (paymentController.formKey.currentState! // .validate()) { // box.write( // BoxName.phoneWallet, // paymentController // .walletphoneController.text); // // await payWithSyriaTelWallet( // // context, pricePoint.toString(), 'SYP'); // bool isAuthSupported = // await LocalAuthentication() // .isDeviceSupported(); // if (isAuthSupported) { // bool didAuthenticate = // await LocalAuthentication() // .authenticate( // localizedReason: // 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', // ); // if (!didAuthenticate) { // if (Get.isDialogOpen ?? false) Get.back(); // print( // "❌ User did not authenticate with biometrics"); // return; // } // } // Get.to(() => PaymentScreenMtn( // amount: pricePoint, // userType: 'Driver', // )); // } // })); // }, // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Text('Pay by MTN Wallet'.tr), // const SizedBox(width: 10), // Image.asset( // 'assets/images/cashMTN.png', // width: 70, // height: 70, // fit: BoxFit.fill, // ), // ], // )), ], )); }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 3, vertical: 8), child: Container( width: Get.width * .22, height: Get.width * .22, margin: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( colors: [ kolor.withOpacity(0.3), kolor, kolor.withOpacity(0.7), kolor, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), border: Border.all(color: AppColor.accentColor), borderRadius: BorderRadius.circular(12), shape: BoxShape.rectangle, ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text( '$countPoint ${'L.S'.tr}', style: AppStyle.subtitle .copyWith(color: AppColor.secondaryColor), ), Text( '$pricePoint ${'L.S'.tr}', style: AppStyle.title.copyWith(color: AppColor.secondaryColor), textAlign: TextAlign.center, ), ], ), ), ), ), ); } } class PaymentScreen extends StatefulWidget { final String iframeUrl; final String countPrice; const PaymentScreen( {required this.iframeUrl, Key? key, required this.countPrice}) : super(key: key); @override State createState() => _PaymentScreenState(); } class _PaymentScreenState extends State { late final WebViewController _controller; final controller = Get.find(); @override void initState() { super.initState(); _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate(NavigationDelegate( onPageFinished: (url) { if (url.contains("success")) { _fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع } else if (url.contains("failed")) { showCustomDialog( title: "Error".tr, message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم isSuccess: false, ); } }, )) ..loadRequest(Uri.parse(widget.iframeUrl)); } Future _fetchPaymentStatus() async { final String userId = box.read(BoxName.phoneDriver); await Future.delayed(const Duration(seconds: 2)); try { final response = await CRUD().postWallet( link: AppLink.paymetVerifyDriver, payload: { 'user_id': userId, 'driverID': box.read(BoxName.driverID), 'paymentMethod': 'visa-in', }, ); if (response != 'failure' && response != 'token_expired') { if (response['status'] == 'success') { final payment = response['message']; final amount = payment['amount'].toString(); final bonus = payment['bonus'].toString(); final paymentID = payment['paymentID'].toString(); await controller.getCaptainWalletFromBuyPoints(); showCustomDialog( title: "payment_success".tr, message: "${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}", isSuccess: true, ); } else { showCustomDialog( title: "transaction_failed".tr, message: response['message'].toString(), isSuccess: false, ); } } else { showCustomDialog( title: "connection_failed".tr, message: response.toString(), isSuccess: false, ); } } catch (e) { showCustomDialog( title: "server_error".tr, message: "server_error_message".tr, isSuccess: false, ); } } void showCustomDialog({ required String title, required String message, required bool isSuccess, }) { showDialog( barrierDismissible: false, context: Get.context!, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), title: Row( children: [ Icon( isSuccess ? Icons.check_circle : Icons.error, color: isSuccess ? Colors.green : Colors.red, ), const SizedBox(width: 8), Text( title, style: TextStyle( color: isSuccess ? Colors.green : Colors.red, fontWeight: FontWeight.bold, ), ), ], ), content: Text( message, style: const TextStyle(fontSize: 16), ), actions: [ TextButton( onPressed: () { Navigator.pop(context); Navigator.pop(context); }, style: TextButton.styleFrom( backgroundColor: isSuccess ? Colors.green : Colors.red, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), child: Text( "OK", style: const TextStyle(color: Colors.white), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('إتمام الدفع')), body: WebViewWidget(controller: _controller), ); } } class PaymentScreenWallet extends StatefulWidget { final String iframeUrl; final String countPrice; const PaymentScreenWallet( {required this.iframeUrl, Key? key, required this.countPrice}) : super(key: key); @override State createState() => _PaymentScreenWalletState(); } class _PaymentScreenWalletState extends State { late final WebViewController _controller; final controller = Get.find(); @override void initState() { super.initState(); _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate(NavigationDelegate( onPageFinished: (url) { if (url.contains("success")) { _fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع } else if (url.contains("failed")) { showCustomDialog( title: "Error".tr, message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم isSuccess: false, ); } }, )) ..loadRequest(Uri.parse(widget.iframeUrl)); } Future _fetchPaymentStatus() async { final String userId = '+963' + box.read(BoxName.phoneWallet); await Future.delayed(const Duration(seconds: 2)); try { final response = await CRUD().postWallet( link: AppLink.paymetVerifyDriver, payload: { 'user_id': userId, 'driverID': box.read(BoxName.driverID), 'paymentMethod': 'visa-in', }, ); if (response != 'failure' && response != 'token_expired') { if (response['status'] == 'success') { final payment = response['message']; final amount = payment['amount'].toString(); final bonus = payment['bonus'].toString(); final paymentID = payment['paymentID'].toString(); await controller.getCaptainWalletFromBuyPoints(); showCustomDialog( title: "payment_success".tr, message: "${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}", isSuccess: true, ); } else { showCustomDialog( title: "transaction_failed".tr, message: response['message'].toString(), isSuccess: false, ); } } else { showCustomDialog( title: "connection_failed".tr, message: response.toString(), isSuccess: false, ); } } catch (e) { showCustomDialog( title: "server_error".tr, message: "server_error_message".tr, isSuccess: false, ); } } void showCustomDialog({ required String title, required String message, required bool isSuccess, }) { showDialog( barrierDismissible: false, context: Get.context!, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), title: Row( children: [ Icon( isSuccess ? Icons.check_circle : Icons.error, color: isSuccess ? Colors.green : Colors.red, ), const SizedBox(width: 8), Text( title, style: TextStyle( color: isSuccess ? Colors.green : Colors.red, fontWeight: FontWeight.bold, ), ), ], ), content: Text( message, style: const TextStyle(fontSize: 16), ), actions: [ TextButton( onPressed: () { Navigator.pop(context); Navigator.pop(context); }, style: TextButton.styleFrom( backgroundColor: isSuccess ? Colors.green : Colors.red, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), child: Text( "OK", style: const TextStyle(color: Colors.white), ), ), ], ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('إتمام الدفع')), body: WebViewWidget(controller: _controller), ); } } Future payWithMTNWallet( BuildContext context, String amount, String currency) async { // استخدام مؤشر تحميل لتجربة مستخدم أفضل Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); try { String phone = box.read(BoxName.phoneWallet); String driverID = box.read(BoxName.driverID).toString(); String formattedAmount = double.parse(amount).toStringAsFixed(0); print("🚀 بدء عملية دفع MTN"); print( "📦 Payload: driverID: $driverID, amount: $formattedAmount, phone: $phone"); // التحقق من البصمة (اختياري) bool isAuthSupported = await LocalAuthentication().isDeviceSupported(); if (isAuthSupported) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', ); if (!didAuthenticate) { if (Get.isDialogOpen ?? false) Get.back(); print("❌ المستخدم لم يؤكد بالبصمة/الوجه"); return; } } // 1️⃣ استدعاء mtn_start_payment.php (الملف الجديد) var responseData = await CRUD().postWalletMtn( link: AppLink.payWithMTNStart, payload: { "amount": formattedAmount, "passengerId": driverID, "phone": phone, "lang": box.read(BoxName.lang) ?? 'ar', }, ); print("✅ استجابة الخادم (mtn_start_payment.php):"); print(responseData); // --- بداية التعديل المهم --- // التحقق القوي من الاستجابة لتجنب الأخطاء Map startRes; if (responseData is Map) { // إذا كانت الاستجابة بالفعل Map، استخدمها مباشرة startRes = responseData; } else if (responseData is String) { // إذا كانت نص، حاول تحليلها كـ JSON try { startRes = json.decode(responseData); } catch (e) { throw Exception( "فشل في تحليل استجابة الخادم. الاستجابة: $responseData"); } } else { // نوع غير متوقع throw Exception("تم استلام نوع بيانات غير متوقع من الخادم."); } if (startRes['status'] != 'success') { final errorMsg = startRes['message']['Error']?.toString().tr ?? "فشل بدء عملية الدفع. حاول مرة أخرى."; throw Exception(errorMsg); } // --- نهاية التعديل المهم --- // استخراج البيانات بأمان final messageData = startRes["message"]; final invoiceNumber = messageData["invoiceNumber"].toString(); final operationNumber = messageData["operationNumber"].toString(); final guid = messageData["guid"].toString(); print( "📄 invoiceNumber: $invoiceNumber, 🔢 operationNumber: $operationNumber, 🧭 guid: $guid"); if (Get.isDialogOpen == true) Get.back(); // إغلاق مؤشر التحميل قبل عرض حوار OTP // 2️⃣ عرض واجهة إدخال OTP String? otp = await showDialog( context: context, barrierDismissible: false, builder: (context) { String input = ""; return AlertDialog( title: const Text("أدخل كود التحقق"), content: TextField( keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: "كود OTP"), onChanged: (val) => input = val, ), actions: [ TextButton( child: const Text("تأكيد"), onPressed: () => Navigator.of(context).pop(input), ), TextButton( child: const Text("إلغاء"), onPressed: () => Navigator.of(context).pop(), ), ], ); }, ); if (otp == null || otp.isEmpty) { print("❌ لم يتم إدخال OTP"); return; } print("🔐 تم إدخال OTP: $otp"); Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); // 3️⃣ استدعاء mtn_confirm.php var confirmRes = await CRUD().postWalletMtn( link: AppLink.payWithMTNConfirm, payload: { "invoiceNumber": invoiceNumber, "operationNumber": operationNumber, "guid": guid, "otp": otp, "phone": phone, }, ); if (Get.isDialogOpen ?? false) Get.back(); print("✅ استجابة mtn_confirm.php:"); // print(confirmRes); Log.print('confirmRes: ${confirmRes}'); if (confirmRes != null && confirmRes['status'] == 'success') { Get.defaultDialog( title: "✅ نجاح", content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."), ); } else { String errorMsg = confirmRes?['message']['message']?.toString() ?? "فشل في تأكيد الدفع"; Get.defaultDialog( title: "❌ فشل", content: Text(errorMsg.tr), ); } } catch (e, s) { print("🔥 خطأ أثناء الدفع عبر MTN:"); print(e); print(s); if (Get.isDialogOpen ?? false) Get.back(); Get.defaultDialog( title: 'حدث خطأ', content: Text(e.toString().replaceFirst("Exception: ", "")), ); } } Future payWithSyriaTelWallet( BuildContext context, String amount, String currency) async { // Show a loading indicator for better user experience Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); try { String phone = box.read(BoxName.phoneWallet); String driverID = box.read(BoxName.driverID).toString(); String formattedAmount = double.parse(amount).toStringAsFixed(0); // --- CHANGE 1: Updated log messages for clarity --- print("🚀 Starting Syriatel payment process"); print( "📦 Payload: driverID: $driverID, amount: $formattedAmount, phone: $phone"); // Optional: Biometric authentication bool isAuthSupported = await LocalAuthentication().isDeviceSupported(); if (isAuthSupported) { bool didAuthenticate = await LocalAuthentication().authenticate( localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', ); if (!didAuthenticate) { if (Get.isDialogOpen ?? false) Get.back(); print("❌ User did not authenticate with biometrics"); return; } } // --- CHANGE 2: Updated API link and payload for starting payment --- // Make sure you have defined `payWithSyriatelStart` in your AppLink class var responseData = await CRUD().postWalletMtn( link: AppLink.payWithSyriatelStart, // Use the new Syriatel start link payload: { "amount": formattedAmount, "driverId": driverID, // Key changed from 'passengerId' to 'driverId' "phone": phone, "lang": box.read(BoxName.lang) ?? 'ar', }, ); print("✅ Server response (start_payment.php):"); Log.print('responseData: ${responseData}'); // Robustly parse the server's JSON response Map startRes; if (responseData is Map) { startRes = responseData; } else if (responseData is String) { try { startRes = json.decode(responseData); } catch (e) { throw Exception( "Failed to parse server response. Response: $responseData"); } } else { throw Exception("Received an unexpected data type from the server."); } if (startRes['status'] != 'success') { String errorMsg = startRes['message']?.toString() ?? "Failed to start the payment process. Please try again."; throw Exception(errorMsg); } // --- CHANGE 3: Extract `transactionID` from the response --- // The response structure is now simpler. We only need the transaction ID. final messageData = startRes["message"]; final transactionID = messageData["transactionID"].toString(); print("📄 TransactionID: $transactionID"); if (Get.isDialogOpen == true) Get.back(); // Close loading indicator // Show the OTP input dialog String? otp = await showDialog( context: context, barrierDismissible: false, builder: (context) { String input = ""; return AlertDialog( title: const Text("أدخل كود التحقق"), content: TextField( keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: "كود OTP"), onChanged: (val) => input = val, ), actions: [ TextButton( child: const Text("تأكيد"), onPressed: () => Navigator.of(context).pop(input), ), TextButton( child: const Text("إلغاء"), onPressed: () => Navigator.of(context).pop(), ), ], ); }, ); if (otp == null || otp.isEmpty) { print("❌ OTP was not entered."); return; } print("🔐 OTP entered: $otp"); Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false); // --- CHANGE 4: Updated API link and payload for confirming payment --- // Make sure you have defined `payWithSyriatelConfirm` in your AppLink class var confirmRes = await CRUD().postWalletMtn( // Changed from postWalletMtn if they are different link: AppLink.payWithSyriatelConfirm, // Use the new Syriatel confirm link payload: { "transactionID": transactionID, // Use the transaction ID "otp": otp, // The other parameters (phone, guid, etc.) are no longer needed }, ); if (Get.isDialogOpen ?? false) Get.back(); print("✅ Response from confirm_payment.php:"); Log.print('confirmRes: ${confirmRes}'); if (confirmRes != null && confirmRes['status'] == 'success') { Get.defaultDialog( title: "✅ نجاح", content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."), ); } else { // --- CHANGE 5: Simplified error message extraction --- // The new PHP script sends the error directly in the 'message' field. String errorMsg = confirmRes?['message']?.toString() ?? "فشل في تأكيد الدفع"; Get.defaultDialog( title: "❌ فشل", content: Text(errorMsg.tr), ); } } catch (e, s) { // --- CHANGE 6: Updated general error log message --- print("🔥 Error during Syriatel Wallet payment:"); print(e); print(s); if (Get.isDialogOpen ?? false) Get.back(); Get.defaultDialog( title: 'حدث خطأ', content: Text(e.toString().replaceFirst("Exception: ", "")), ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/payment_history_driver_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; // Assuming this has your text styles import 'package:sefer_driver/views/widgets/mycircular.dart'; // Assuming this is your loading widget import '../../../controller/payment/driver_payment_controller.dart'; class PaymentHistoryDriverPage extends StatelessWidget { const PaymentHistoryDriverPage({super.key}); @override Widget build(BuildContext context) { // Initialize your controller Get.put(DriverWalletHistoryController()); return Scaffold( appBar: AppBar( title: Text('Payment History'.tr), backgroundColor: Colors.white, elevation: 1, ), backgroundColor: Colors.grey[100], body: GetBuilder( builder: (controller) { if (controller.isLoading) { // Using your custom loading indicator return const Center(child: MyCircularProgressIndicator()); } if (controller.archive.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.account_balance_wallet_outlined, size: 80, color: Colors.grey[400]), const SizedBox(height: 16), Text( 'No transactions yet'.tr, style: Theme.of(context) .textTheme .headlineSmall ?.copyWith(color: Colors.grey[600]), ), ], ), ); } return AnimationLimiter( child: ListView.builder( padding: const EdgeInsets.all(16.0), itemCount: controller.archive.length, itemBuilder: (BuildContext context, int index) { var transaction = controller.archive[index]; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 375), child: SlideAnimation( verticalOffset: 50.0, child: FadeInAnimation( child: _TransactionCard(transaction: transaction), ), ), ); }, ), ); }, ), ); } } // A dedicated widget for displaying a single transaction with a modern UI. class _TransactionCard extends StatelessWidget { final Map transaction; const _TransactionCard({required this.transaction}); @override Widget build(BuildContext context) { // Safely parse the amount to avoid errors final double amount = double.tryParse(transaction['amount']?.toString() ?? '0') ?? 0; final bool isCredit = amount >= 0; final Color indicatorColor = isCredit ? AppColor.greenColor : AppColor.redColor; final IconData iconData = isCredit ? Icons.arrow_upward_rounded : Icons.arrow_downward_rounded; final String transactionType = (isCredit ? 'Credit'.tr : 'Debit'.tr).tr; return Card( elevation: 2, shadowColor: Colors.black.withOpacity(0.05), margin: const EdgeInsets.only(bottom: 12.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), clipBehavior: Clip.antiAlias, // Ensures the color bar is clipped neatly child: IntrinsicHeight( // Ensures the color bar and content have the same height child: Row( children: [ // Left-side color indicator bar Container(width: 6, color: indicatorColor), Expanded( child: ListTile( leading: Icon(iconData, color: indicatorColor, size: 30), title: Text( // Use .abs() to remove the negative sign from the display '${amount.abs().toStringAsFixed(2)} ${'SYP'.tr}', style: AppStyle.title.copyWith( fontWeight: FontWeight.bold, color: Colors.black87, ), ), subtitle: Text( transaction['created_at'] ?? 'No date', style: AppStyle.title.copyWith( fontSize: 12, color: Colors.grey[600], ), ), trailing: Text( transactionType, style: AppStyle.title.copyWith( fontSize: 14, color: indicatorColor, fontWeight: FontWeight.w600, ), ), ), ), ], ), ), ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/transfer_budget_page.dart ================================================== import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import 'package:sefer_driver/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../controller/home/payment/captain_wallet_controller.dart'; class TransferBudgetPage extends StatelessWidget { const TransferBudgetPage({super.key}); @override Widget build(BuildContext context) { Get.put(CaptainWalletController()); return MyScafolld( title: "Transfer budget".tr, body: [ GetBuilder( builder: (captainWalletController) { return Padding( padding: const EdgeInsets.all(8.0), child: Container( decoration: AppStyle.boxDecoration1, height: Get.height * .7, width: double.infinity, child: Form( key: captainWalletController.formKeyTransfer, child: Column( children: [ const SizedBox( height: 20, ), MyTextForm( controller: captainWalletController .newDriverPhoneController, label: 'phone number of driver'.tr, hint: 'phone number of driver', type: TextInputType.phone), MyTextForm( controller: captainWalletController .amountFromBudgetController, label: 'insert amount'.tr, hint: '${'You have in account'.tr} ${captainWalletController.totalAmountVisa}', type: TextInputType.number), captainWalletController.isNewTransfer ? const MyCircularProgressIndicator() : captainWalletController .amountToNewDriverMap.isEmpty ? MyElevatedButton( title: 'Next'.tr, onPressed: () async { await captainWalletController .detectNewDriverFromMyBudget(); }) : const SizedBox(), captainWalletController.amountToNewDriverMap.isNotEmpty ? Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Container( width: double.maxFinite, decoration: AppStyle.boxDecoration1, child: Text( 'Name :'.tr + captainWalletController .amountToNewDriverMap[0]['name'] .toString(), textAlign: TextAlign.center, style: AppStyle.title, ), ), const SizedBox( height: 5, ), Container( width: double.maxFinite, decoration: AppStyle.boxDecoration1, child: Text( "${"NationalID".tr} ${captainWalletController.amountToNewDriverMap[0]['national_number']}", style: AppStyle.title, textAlign: TextAlign.center, ), ), const SizedBox( height: 5, ), Container( width: double.maxFinite, decoration: AppStyle.boxDecoration1, child: Text( "${"amount".tr} ${captainWalletController.amountFromBudgetController.text} ${'LE'.tr}", style: AppStyle.title, textAlign: TextAlign.center, ), ), const SizedBox( height: 15, ), captainWalletController .amountToNewDriverMap.isNotEmpty ? MyElevatedButton( title: 'Transfer'.tr, onPressed: () async { if (double.parse( captainWalletController .amountFromBudgetController .text) < double.parse( captainWalletController .totalAmountVisa) - 5) { await captainWalletController .addTransferDriversWallet( 'TransferFrom', 'TransferTo', ); } else { MyDialog().getDialog( "You dont have money in your Wallet" .tr, "You dont have money in your Wallet or you should less transfer 5 LE to activate" .tr, () { Get.back(); }); } }) : const SizedBox() ], ), ) : const SizedBox() ], )), ), ); }), ], isleading: true); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/pay_out_screen.dart ================================================== import 'package:flutter/material.dart'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/main.dart'; import '../../../controller/payment/smsPaymnet/pay_out_syria_controller.dart'; class PayoutScreen extends StatefulWidget { // استقبال كل البيانات المطلوبة جاهزة final double amountToWithdraw; final String payoutPhoneNumber; final String walletType; const PayoutScreen({ super.key, required this.amountToWithdraw, required this.payoutPhoneNumber, required this.walletType, }); @override _PayoutScreenState createState() => _PayoutScreenState(); } class _PayoutScreenState extends State { final _payoutService = PayoutService(); final _localAuth = LocalAuthentication(); bool _isLoading = false; Future _handlePayoutRequest() async { try { // 1. طلب المصادقة البيومترية bool didAuthenticate = await _localAuth.authenticate( localizedReason: 'استخدم بصمة الإصبع لتأكيد عملية السحب', options: const AuthenticationOptions( biometricOnly: true, sensitiveTransaction: true, ), ); if (didAuthenticate && mounted) { setState(() => _isLoading = true); // 2. إرسال الطلب إلى السيرفر بالبيانات الجاهزة final result = await _payoutService.requestPayout( driverId: box.read(BoxName.driverID).toString(), // استبدله بـ box.read amount: widget.amountToWithdraw, payoutPhoneNumber: widget.payoutPhoneNumber, walletType: widget.walletType, ); setState(() => _isLoading = false); if (result != null && result.contains("successfully")) { // 3. عرض رسالة النجاح النهائية _showSuccessDialog(); } else { _showErrorDialog(result ?? "حدث خطأ غير معروف."); } } } catch (e) { setState(() => _isLoading = false); _showErrorDialog("جهازك لا يدعم المصادقة البيومترية أو لم يتم إعدادها."); debugPrint("Biometric error: $e"); } } @override Widget build(BuildContext context) { // حساب المبلغ الإجمالي المخصوم final totalDeducted = widget.amountToWithdraw + PayoutService.payoutFee; return Scaffold( appBar: AppBar(title: const Text("تأكيد سحب الأموال")), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Icon(Icons.wallet, size: 64, color: Colors.blue), const SizedBox(height: 16), Text( "تأكيد تفاصيل عملية السحب", style: Theme.of(context).textTheme.headlineSmall, textAlign: TextAlign.center, ), const SizedBox(height: 24), _buildSummaryCard(totalDeducted), const SizedBox(height: 32), _isLoading ? const Center(child: CircularProgressIndicator()) : ElevatedButton.icon( onPressed: _handlePayoutRequest, icon: const Icon(Icons.fingerprint), label: const Text("تأكيد السحب بالبصمة"), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), textStyle: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), ), ], ), ), ); } Widget _buildSummaryCard(double totalDeducted) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ _summaryRow("المبلغ المسحوب:", "${widget.amountToWithdraw.toStringAsFixed(2)} ل.س"), const Divider(), _summaryRow("عمولة السحب:", "${PayoutService.payoutFee.toStringAsFixed(2)} ل.س"), const Divider(thickness: 1.5), _summaryRow( "الإجمالي المخصوم من رصيدك:", "${totalDeducted.toStringAsFixed(2)} ل.س", isTotal: true, ), const SizedBox(height: 16), _summaryRow("سيتم التحويل إلى هاتف:", widget.payoutPhoneNumber), _summaryRow("عبر محفظة:", widget.walletType), ], ), ), ); } Widget _summaryRow(String title, String value, {bool isTotal = false}) { final titleStyle = TextStyle( fontSize: 16, color: isTotal ? Theme.of(context).primaryColor : Colors.black87, fontWeight: isTotal ? FontWeight.bold : FontWeight.normal, ); final valueStyle = titleStyle.copyWith( fontWeight: FontWeight.bold, ); return Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: titleStyle), Text(value, style: valueStyle), ], ), ); } void _showErrorDialog(String message) { if (!mounted) return; showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('حدث خطأ'), content: Text(message), actions: [ TextButton( child: const Text('موافق'), onPressed: () => Navigator.of(ctx).pop()) ], ), ); } void _showSuccessDialog() { if (!mounted) return; showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( title: const Text('تم إرسال طلبك بنجاح'), content: Text( "سيتم تحويل المال إلى المحفظة التي أوردتها (${widget.walletType})، إلى الرقم ${widget.payoutPhoneNumber}، خلال مدة قصيرة. يرجى الانتظار، ستصلك رسالة تأكيد من محفظتك حال وصولها. شكراً لك."), actions: [ TextButton( child: const Text('موافق'), onPressed: () { Navigator.of(ctx).pop(); Navigator.of(context).pop(); }, ), ], ), ); } } ================================================== FILE PATH: ./lib/views/home/my_wallet/card_wallet_widget.dart ================================================== import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/home/my_wallet/pay_out_screen.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/style.dart'; import '../../../controller/home/payment/captain_wallet_controller.dart'; import '../../../controller/home/payment/paymob_payout.dart'; import '../../../main.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/my_textField.dart'; // تذكير: ستحتاج إلى إضافة حزمة flutter_svg إلى ملف pubspec.yaml // dependencies: // flutter_svg: ^2.0.7 /// بطاقة المحفظة بتصميم سوري فاخر مستوحى من فن الأرابيسك والفسيفساء class CardSeferWalletDriver extends StatelessWidget { const CardSeferWalletDriver({super.key}); // SVG لنقشة أرابيسك هندسية لاستخدامها كخلفية final String arabesquePattern = ''' '''; @override Widget build(BuildContext context) { return Center( child: GetBuilder( builder: (captainWalletController) { return GestureDetector( onTap: () => _showCashOutDialog(context, captainWalletController), child: Container( width: Get.width * 0.9, height: Get.height * 0.25, decoration: BoxDecoration( borderRadius: BorderRadius.circular(28), boxShadow: [ BoxShadow( color: const Color(0xFF003C43).withOpacity(0.5), blurRadius: 25, spreadRadius: -5, offset: const Offset(0, 10), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(28), child: Stack( children: [ // الخلفية الرئيسية Container(color: const Color(0xFF003C43)), // طبقة النقشة SvgPicture.string(arabesquePattern, fit: BoxFit.cover), // طبقة التأثير الزجاجي (Glassmorphism) BackdropFilter( filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0), child: Container(color: Colors.black.withOpacity(0.1)), ), // محتوى البطاقة _buildCardContent(captainWalletController), ], ), ), ), ); }, ), ); } Widget _buildCardContent(CaptainWalletController captainWalletController) { return Padding( padding: const EdgeInsets.fromLTRB(24, 20, 24, 20), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( 'رصيد انطلق', style: AppStyle.headTitle.copyWith( fontFamily: 'Amiri', // خط يوحي بالفخامة color: Colors.white, fontSize: 26, fontWeight: FontWeight.bold, ), ), // أيقونة شريحة البطاقة const Icon(Icons.sim_card_outlined, color: Color(0xFFE7C582), size: 30), ], ), Column( children: [ Text( 'الرصيد الحالي'.tr, style: AppStyle.title.copyWith( color: Colors.white.withOpacity(0.7), fontSize: 16, ), ), const SizedBox(height: 4), // استخدام AnimatedSwitcher لإضافة حركة عند تحديث الرصيد AnimatedSwitcher( duration: const Duration(milliseconds: 500), transitionBuilder: (child, animation) { return FadeTransition(opacity: animation, child: child); }, child: Text( '${captainWalletController.totalAmountVisa} ${'ل.س'.tr}', key: ValueKey(captainWalletController.totalAmountVisa), style: AppStyle.headTitle2.copyWith( color: const Color(0xFFE7C582), // Antique Gold fontSize: 40, fontWeight: FontWeight.w900, ), ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( box.read(BoxName.nameDriver).toString().split(' ')[0], style: AppStyle.title.copyWith( color: Colors.white.withOpacity(0.9), fontSize: 16, letterSpacing: 0.5, ), ), Text( "سحب الرصيد".tr, style: AppStyle.title.copyWith( color: Colors.white.withOpacity(0.9), fontSize: 16, ), ), ], ), ], ), ); } void _showCashOutDialog( BuildContext context, CaptainWalletController captainWalletController) { double minAmount = 20000.0; // الحد الأدنى للسحب if (double.parse(captainWalletController.totalAmountVisa) >= minAmount) { Get.defaultDialog( barrierDismissible: false, title: 'هل تريد سحب أرباحك؟'.tr, titleStyle: AppStyle.title .copyWith(fontSize: 18, fontWeight: FontWeight.bold), content: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const Icon(Icons.account_balance_wallet, color: AppColor.primaryColor, size: 30), const SizedBox(height: 15), Text( '${'رصيدك الإجمالي:'.tr} ${captainWalletController.totalAmountVisa} ${'ل.س'.tr}', style: AppStyle.title.copyWith(fontSize: 16), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'طريقة الدفع:'.tr, style: AppStyle.title.copyWith(fontSize: 16), ), const SizedBox(width: 10), const MyDropDownSyria(), ], ), const SizedBox(height: 20), Form( key: captainWalletController.formKey, child: MyTextForm( controller: captainWalletController.phoneWallet, label: "أدخل رقم محفظتك".tr, hint: "مثال: 0912345678".tr, type: TextInputType.phone, ), ), ], ), confirm: MyElevatedButton( title: 'تأكيد'.tr, onPressed: () async { box.write( BoxName.phoneWallet, captainWalletController.phoneWallet); box.write(BoxName.walletType, Get.find().dropdownValue.toString()); if (captainWalletController.formKey.currentState!.validate()) { Get.back(); Get.to(() => PayoutScreen( amountToWithdraw: double.parse(captainWalletController.totalAmountVisa), payoutPhoneNumber: captainWalletController.phoneWallet.text.toString(), walletType: Get.find() .dropdownValue .toString(), )); // String amountAfterFee = // (double.parse(captainWalletController.totalAmountVisa) - 5) // .toStringAsFixed(0); // await Get.put(PaymobPayout()).payToWalletDriverAll( // amountAfterFee, // Get.find().dropdownValue.toString(), // captainWalletController.phoneWallet.text.toString(), // ); } }, kolor: AppColor.greenColor, ), cancel: MyElevatedButton( title: 'إلغاء'.tr, onPressed: () { Get.back(); }, kolor: AppColor.redColor, )); } else { showCupertinoDialog( context: context, builder: (BuildContext context) { return CupertinoAlertDialog( title: Text("تنبيه".tr), content: Text( '${'المبلغ في محفظتك أقل من الحد الأدنى للسحب وهو'.tr} $minAmount ${'ل.س'.tr}', ), actions: [ CupertinoDialogAction( isDefaultAction: true, child: Text("موافق".tr), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }, ); } } } // هذا الكود من الملف الأصلي وهو ضروري لعمل الحوار class MyDropDownSyria extends StatelessWidget { const MyDropDownSyria({super.key}); @override Widget build(BuildContext context) { Get.put(SyrianPayoutController()); return GetBuilder(builder: (controller) { return DropdownButton( value: controller.dropdownValue, icon: const Icon(Icons.arrow_drop_down), elevation: 16, style: const TextStyle(color: Colors.deepPurple, fontSize: 16), underline: Container( height: 2, color: Colors.deepPurpleAccent, ), onChanged: (String? newValue) { controller.changeValue(newValue); }, items: ['Syriatel', 'Cash Mobile', 'Sham Cash'] .map>((String value) { return DropdownMenuItem( value: value, child: Text(value.tr), ); }).toList(), ); }); } } // هذا المتحكم ضروري لعمل القائمة المنسدلة class SyrianPayoutController extends GetxController { String dropdownValue = 'Syriatel'; void changeValue(String? newValue) { if (newValue != null) { dropdownValue = newValue; update(); } } } ================================================== FILE PATH: ./lib/views/Rate/rate_app_page.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../controller/rate/rate_app_controller.dart'; class RatingScreen extends StatelessWidget { final RatingController ratingController = Get.put(RatingController()); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text( "Rate Our App".tr, style: const TextStyle(fontWeight: FontWeight.bold), ), ), child: SafeArea( child: SingleChildScrollView( child: Center( child: Obx(() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // App logo or visual ClipRRect( borderRadius: BorderRadius.circular(16), child: Image.asset( 'assets/images/logo.gif', height: 120, ), ), const SizedBox(height: 20), // Rating Prompt Text( "How would you rate our app?".tr, textAlign: TextAlign.center, style: CupertinoTheme.of(context) .textTheme .navTitleTextStyle .copyWith(fontSize: 18, fontWeight: FontWeight.w600), ), const SizedBox(height: 20), // Comment Box CupertinoTextField( controller: ratingController.comment, placeholder: 'Write your comment here'.tr, padding: const EdgeInsets.all(12), decoration: BoxDecoration( border: Border.all(color: CupertinoColors.systemGrey4), borderRadius: BorderRadius.circular(12), color: CupertinoColors.white, ), prefix: Padding( padding: const EdgeInsets.only(left: 8.0), child: Icon(CupertinoIcons.pencil_ellipsis_rectangle, color: CupertinoColors.systemGrey), ), ), const SizedBox(height: 20), // Star Rating Section _buildRatingStars(), const SizedBox(height: 30), // Submit Button CupertinoButton( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 14), borderRadius: BorderRadius.circular(12), color: CupertinoColors.activeGreen, onPressed: () { if (ratingController.userRating.value > 0) { ratingController .submitRating(ratingController.userRating.value); Get.snackbar( "Thank You!".tr, "Your rating has been submitted.".tr, backgroundColor: CupertinoColors.systemGrey6, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(16), borderRadius: 12, ); } else { Get.snackbar( "Error".tr, "Please select a rating before submitting.".tr, backgroundColor: CupertinoColors.systemRed, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(16), borderRadius: 12, ); } }, child: Text( "Submit Rating".tr, style: const TextStyle( color: CupertinoColors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ], ), ); }), ), ), ), ); } // Widget for building rating stars with animations Widget _buildRatingStars() { return Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(5, (index) { return GestureDetector( onTap: () { ratingController.userRating.value = index + 1; }, child: AnimatedContainer( duration: const Duration(milliseconds: 300), margin: const EdgeInsets.symmetric(horizontal: 4), child: Icon( CupertinoIcons.star_fill, size: 40, color: index < ratingController.userRating.value ? CupertinoColors.systemYellow : CupertinoColors.systemGrey3, ), ), ); }), ); } } ================================================== FILE PATH: ./lib/views/Rate/rate_passenger.dart ================================================== import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; // Import this for formatting import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../constant/style.dart'; import '../../controller/rate/rate_conroller.dart'; class RatePassenger extends StatelessWidget { final RateController controller = Get.put(RateController()); // Format: 1,234.5 final NumberFormat currencyFormatter = NumberFormat("#,##0.0", "en_US"); RatePassenger({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( title: Text('Trip Completed'.tr, style: const TextStyle(color: Colors.black)), centerTitle: true, automaticallyImplyLeading: false, backgroundColor: Colors.white, elevation: 0, ), body: GetBuilder( builder: (controller) { return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 1. The HERO Section: Big Price Display _buildHeroPriceDisplay(context), const SizedBox(height: 24), // 2. Wallet Section (Conditional) if (controller.walletChecked != 'true') _buildWalletSection(context, controller), const SizedBox(height: 24), // 3. Rating Section _buildRatingSection(context, controller), const SizedBox(height: 30), // 4. Submit Button SizedBox( height: 55, child: MyElevatedButton( title: 'Finish & Submit'.tr, onPressed: () => controller.addRateToPassenger(), // isFullWidth: true, ), ), ], ), ), ); }, ), ); } // --- WIDGETS --- Widget _buildHeroPriceDisplay(BuildContext context) { final MapDriverController mapController = Get.find(); // Parse the string to double to format it correctly double amount = double.tryParse(mapController.paymentAmount.toString()) ?? 0.0; String formattedAmount = currencyFormatter.format(amount); return Container( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), decoration: BoxDecoration( color: AppColor.primaryColor, // Use your brand color or a dark color borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: AppColor.primaryColor.withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 10), ), ], ), child: Column( children: [ Text( 'Collect Cash'.tr.toUpperCase(), style: const TextStyle( color: Colors.white70, fontSize: 16, fontWeight: FontWeight.w600, letterSpacing: 1.2, ), ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Currency Symbol (Small) Padding( padding: const EdgeInsets.only(top: 8.0), child: Text( 'SYP'.tr, // Replace with your local currency symbol if needed style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 24, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 4), // The Price (Huge) Text( formattedAmount, style: const TextStyle( color: Colors.white, fontSize: 56, // Very Large Font fontWeight: FontWeight.w900, height: 1.0, ), ), ], ), const SizedBox(height: 10), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(20), ), child: Text( 'Passenger: ${mapController.passengerName}', style: const TextStyle(color: Colors.white, fontSize: 14), ), ), ], ), ); } Widget _buildWalletSection(BuildContext context, RateController controller) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.shade200), ), child: Padding( padding: const EdgeInsets.all(20.0), child: AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: controller.ispassengerWantWalletFromDriver ? _buildAmountInput(controller) : _buildWalletQuery(controller), ), ), ); } Widget _buildWalletQuery(RateController controller) { return Column( key: const ValueKey('walletQuery'), children: [ Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.orange.withOpacity(0.1), shape: BoxShape.circle, ), child: const Icon(Icons.account_balance_wallet, color: Colors.orange), ), const SizedBox(width: 15), Expanded( child: Text( "Pay remaining to Wallet?".tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 20), Row( children: [ Expanded( child: OutlinedButton( onPressed: () {}, // Optional logic style: OutlinedButton.styleFrom( foregroundColor: Colors.grey, side: BorderSide(color: Colors.grey.shade300), padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), child: Text('No'.tr), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: () => controller.passengerWantPay(), style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), child: Text('Yes, Pay'.tr, style: const TextStyle(color: Colors.white)), ), ), ], ) ], ); } Widget _buildAmountInput(RateController controller) { return Column( key: const ValueKey('amountInput'), crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Enter Amount Paid".tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), Form( key: controller.formKey, child: MyTextForm( controller: controller.passengerPayAmount, label: "Amount".tr, hint: "0.00", type: const TextInputType.numberWithOptions(decimal: true), // Suggestion: Add a suffix icon for currency if available in your widget ), ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => controller.addPassengerWallet(), style: ElevatedButton.styleFrom( backgroundColor: Colors.green, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), child: Text("Confirm Payment".tr, style: const TextStyle(color: Colors.white)), ), ) ], ); } Widget _buildRatingSection(BuildContext context, RateController controller) { return Column( children: [ Text( 'Rate Passenger'.tr, style: TextStyle( color: Colors.grey[600], fontSize: 14, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 12), RatingBar.builder( initialRating: 0, minRating: 1, direction: Axis.horizontal, allowHalfRating: false, itemCount: 5, itemSize: 45, // Large stars itemPadding: const EdgeInsets.symmetric(horizontal: 2.0), itemBuilder: (context, _) => const Icon( Icons.star_rounded, color: Colors.amber, ), onRatingUpdate: (rating) { controller.selectRateItem(rating); }, ), const SizedBox(height: 20), // Simplified comment box TextField( controller: controller.comment, maxLines: 2, decoration: InputDecoration( hintText: 'Any comments about the passenger?'.tr, filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ), ), ), ], ); } } ================================================== FILE PATH: ./lib/views/Rate/ride_calculate_driver.dart ================================================== import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/info.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import 'package:intl/intl.dart'; import '../../controller/home/captin/duration_controller .dart'; class RideCalculateDriver extends StatelessWidget { RideCalculateDriver({super.key}); // DurationController durationController = Get.put(DurationController()); @override Widget build(BuildContext context) { Get.put(DurationController()); return MyScafolld( title: 'Ride Summaries'.tr, body: [ Center( child: GetBuilder( builder: (durationController) => durationController.isLoading ? const Center(child: MyCircularProgressIndicator()) : durationController.jsonData1.isEmpty || durationController.jsonData2.isEmpty ? Center( child: Text('No data yet!'.tr), ) : ListView( // mainAxisAlignment: MainAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( '${'Average of Hours of'.tr} ${AppInformation.appName}${' is ON for this month'.tr}${' ${durationController.jsonData1['message'][0]['day'].toString().split('-')[1]}'.tr}', style: AppStyle.title, textAlign: TextAlign.center, ), Padding( padding: const EdgeInsets.all(6), child: Container( decoration: AppStyle.boxDecoration1, height: Get.height * .4, child: LineChart( duration: const Duration(milliseconds: 150), curve: Curves.ease, LineChartData( lineBarsData: [ LineChartBarData( isStepLineChart: true, spots: durationController.chartData, isCurved: true, color: Colors .deepPurpleAccent, // Custom color barWidth: 3, // Thinner line dotData: const FlDotData( show: true), // Show dots on each point belowBarData: BarAreaData( // Add gradient fill below the line show: true, color: AppColor.deepPurpleAccent, ), isStrokeJoinRound: true, shadow: const BoxShadow( color: AppColor.yellowColor, blurRadius: 4, offset: Offset(2, 2), ), ), ], showingTooltipIndicators: const [], titlesData: FlTitlesData( show: true, topTitles: AxisTitles( axisNameWidget: Text( 'Days'.tr, style: AppStyle.title, ), axisNameSize: 30, ), bottomTitles: AxisTitles( axisNameWidget: Text( 'Total Hours on month'.tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), leftTitles: AxisTitles( axisNameWidget: Text( 'Counts of Hours on days'.tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), ), gridData: const FlGridData( show: true, ), borderData: FlBorderData( show: true, border: const Border( bottom: BorderSide( color: AppColor.accentColor), left: BorderSide( color: AppColor.accentColor), ), ), ), ), ), ), const SizedBox( height: 5, ), Padding( padding: const EdgeInsets.all(6), child: Container( decoration: AppStyle.boxDecoration1, height: Get.height * .4, child: LineChart( duration: const Duration(milliseconds: 150), curve: Curves.ease, LineChartData( lineBarsData: [ LineChartBarData( spots: durationController.chartRideCount, // isCurved: true, color: Colors .deepPurpleAccent, // Custom color barWidth: 3, // Thinner line dotData: const FlDotData( show: true), // Show dots on each point belowBarData: BarAreaData( // Add gradient fill below the line show: true, color: AppColor.deepPurpleAccent, ), isStrokeJoinRound: true, shadow: const BoxShadow( color: AppColor.yellowColor, blurRadius: 4, offset: Offset(2, 2), ), ), ], showingTooltipIndicators: const [], titlesData: FlTitlesData( show: true, topTitles: AxisTitles( axisNameWidget: Text( 'Days'.tr, style: AppStyle.title, ), axisNameSize: 30, // sideTitles: const SideTitles( // reservedSize: 30, showTitles: true), ), bottomTitles: AxisTitles( axisNameWidget: Text( '${"Total rides on month".tr} = ${durationController.jsonData2['message'][0]['totalCount'].toString()}' .tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), leftTitles: AxisTitles( axisNameWidget: Text( 'Counts of rides on days'.tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), ), gridData: const FlGridData( show: true, ), borderData: FlBorderData( show: true, border: const Border( bottom: BorderSide( color: AppColor.accentColor), left: BorderSide( color: AppColor.accentColor), ), ), ), ), ), ), const SizedBox( height: 5, ), Padding( padding: const EdgeInsets.all(6), child: Container( decoration: AppStyle.boxDecoration1, height: Get.height * .4, child: LineChart( duration: const Duration(milliseconds: 150), curve: Curves.ease, LineChartData( lineBarsData: [ LineChartBarData( isStepLineChart: true, spots: durationController .chartRidePriceDriver, isCurved: true, isStrokeCapRound: true, preventCurveOverShooting: true, color: Colors .deepPurpleAccent, // Custom color barWidth: 3, // Thinner line dotData: const FlDotData( show: true), // Show dots on each point belowBarData: BarAreaData( // Add gradient fill below the line show: true, color: AppColor.deepPurpleAccent, ), isStrokeJoinRound: true, shadow: const BoxShadow( color: AppColor.yellowColor, blurRadius: 4, offset: Offset(2, 2), ), ), ], showingTooltipIndicators: const [], titlesData: FlTitlesData( show: true, topTitles: AxisTitles( axisNameWidget: Text( 'Days'.tr, style: AppStyle.title, ), axisNameSize: 30, // sideTitles: const SideTitles( // reservedSize: 30, showTitles: true), ), bottomTitles: AxisTitles( axisNameWidget: Text( '${"Total budgets on month".tr} = ${durationController.jsonData2['message'][0]['totalPrice'].toString()}' .tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), leftTitles: AxisTitles( axisNameWidget: Text( 'Counts of budgets on days'.tr, style: AppStyle.title, ), axisNameSize: 30, sideTitles: const SideTitles( reservedSize: 30, showTitles: true)), ), gridData: const FlGridData( show: true, ), borderData: FlBorderData( show: true, border: const Border( bottom: BorderSide( color: AppColor.accentColor), left: BorderSide( color: AppColor.accentColor), ), ), ), ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: Container( decoration: AppStyle.boxDecoration1, child: durationController.monthlyList.isEmpty ? SizedBox( height: Get.height * .2, child: Center( child: Text( "No data yet".tr, style: AppStyle.title, ), ), ) : DriverStatsTable( monthlyList: durationController.monthlyList, ))) ], ), ) // BarChartWidget(), ), ], isleading: true); } } class DriverStatsTable extends StatelessWidget { final List monthlyList; const DriverStatsTable({Key? key, required this.monthlyList}) : super(key: key); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3), ), ], ), padding: const EdgeInsets.all(16), child: DataTable( columnSpacing: 12, columns: [ DataColumn(label: Text('Statistic'.tr)), DataColumn(label: Text('Value'.tr)), ], rows: _buildRows(), ), ); } List _buildRows() { return [ DataRow(cells: [ DataCell(Text( 'Total Orders'.tr, style: AppStyle.title, )), DataCell(Text( monthlyList[0]['total_orders'].toString(), style: AppStyle.number, )), ]), DataRow(cells: [ DataCell(Text( 'Completed'.tr, style: AppStyle.title, )), DataCell(Text( monthlyList[0]['completed_orders'].toString(), style: AppStyle.number, )), ]), DataRow(cells: [ DataCell(Text( 'Canceled Orders'.tr, style: AppStyle.title, )), DataCell(Text( monthlyList[0]['canceled_orders'].toString(), style: AppStyle.number, )), ]), DataRow(cells: [ DataCell(Text( 'Rejected Orders'.tr, style: AppStyle.title, )), DataCell(Text( monthlyList[0]['rejected_orders'].toString(), style: AppStyle.number, )), ]), DataRow(cells: [ DataCell(Text( 'Percent Rejected'.tr, style: AppStyle.title, )), DataCell(Text( '${(monthlyList[0]['percent_rejected']).toString()}%', style: AppStyle.number.copyWith( color: double.parse(monthlyList[0]['percent_canceled']) < .3 ? AppColor.greenColor : AppColor.redColor), )), ]), DataRow(cells: [ DataCell(Text( 'Percent Canceled'.tr, style: AppStyle.title, )), DataCell(Text( '${(monthlyList[0]['percent_canceled']).toString()}%', style: AppStyle.number.copyWith( color: double.parse(monthlyList[0]['percent_canceled']) < .3 ? AppColor.greenColor : AppColor.redColor), )), ]), DataRow(cells: [ DataCell(Text( 'Percent Completed'.tr, style: AppStyle.title, )), DataCell(Text( '${(monthlyList[0]['percent_completed']).toString()}%', style: AppStyle.number.copyWith( color: double.parse(monthlyList[0]['percent_completed']) > .7 ? AppColor.greenColor : AppColor.redColor), )), ]), ]; } } class StaticDriverOrder extends StatelessWidget { const StaticDriverOrder({ Key? key, required this.title, required this.jsonTitle, }) : super(key: key); final String title, jsonTitle; @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10.0), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.3), spreadRadius: 3, blurRadius: 5, offset: const Offset(0, 3), // changes position of shadow ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black54, ), ), const SizedBox(height: 8.0), Text( jsonTitle, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black, ), ), ], ), ); } } ================================================== FILE PATH: ./lib/views/auth/register_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/auth/register_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import '../../constant/colors.dart'; class RegisterPage extends StatelessWidget { const RegisterPage({super.key}); @override Widget build(BuildContext context) { Get.put(RegisterController()); return MyScafolld( title: 'Register'.tr, body: [ GetBuilder( builder: (controller) => Form( key: controller.formKey, child: Padding( padding: const EdgeInsets.all(16.0), child: SingleChildScrollView( child: Container( decoration: const BoxDecoration( boxShadow: [ BoxShadow( offset: Offset(3, 3), color: AppColor.accentColor, blurRadius: 3) ], color: AppColor.secondaryColor, ), child: Padding( padding: const EdgeInsets.all(16), child: Column(children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( width: Get.width * .4, child: TextFormField( keyboardType: TextInputType.text, controller: controller.firstNameController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), fillColor: AppColor.accentColor, hoverColor: AppColor.accentColor, focusColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(12))), labelText: 'First name'.tr, hintText: 'Enter your first name'.tr, ), validator: (value) { if (value!.isEmpty) { return 'Please enter your first name.'.tr; } return null; }, ), ), SizedBox( width: Get.width * .4, child: TextFormField( keyboardType: TextInputType.text, controller: controller.lastNameController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), focusColor: AppColor.accentColor, fillColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(12))), labelText: 'Last name'.tr, hintText: 'Enter your last name'.tr, ), validator: (value) { if (value!.isEmpty) { return 'Please enter your last name.'.tr; } return null; }, ), ), ], ), const SizedBox( height: 15, ), TextFormField( keyboardType: TextInputType.emailAddress, controller: controller.emailController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), fillColor: AppColor.accentColor, hoverColor: AppColor.accentColor, focusColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(12))), labelText: 'Email'.tr, hintText: 'Enter your email address'.tr, ), validator: (value) { if (value!.isEmpty || (!value.contains('@') || !value.contains('.'))) { return 'Please enter Your Email.'.tr; } return null; }, ), const SizedBox( height: 15, ), TextFormField( obscureText: true, keyboardType: TextInputType.emailAddress, controller: controller.passwordController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), fillColor: AppColor.accentColor, hoverColor: AppColor.accentColor, focusColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(12))), labelText: 'Password'.tr, hintText: 'Enter your Password'.tr, ), validator: (value) { if (value!.isEmpty) { return 'Please enter Your Password.'.tr; } if (value.length < 6) { return 'Password must br at least 6 character.' .tr; } return null; }, ), const SizedBox( height: 15, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( width: Get.width * .4, child: TextFormField( keyboardType: TextInputType.phone, cursorColor: AppColor.accentColor, controller: controller.phoneController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), focusColor: AppColor.accentColor, fillColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(12))), labelText: 'Phone'.tr, hintText: 'Enter your phone number'.tr, ), validator: (value) { if (value!.isEmpty || value.length != 10) { return 'Please enter your phone number.'.tr; } return null; }, ), ), SizedBox( width: Get.width * .4, child: TextFormField( keyboardType: TextInputType.text, controller: controller.siteController, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderSide: const BorderSide( color: AppColor.primaryColor, width: 2.0, ), borderRadius: BorderRadius.circular(10), ), focusColor: AppColor.accentColor, fillColor: AppColor.accentColor, border: const OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(12))), labelText: 'City'.tr, hintText: 'Enter your City'.tr, ), validator: (value) { if (value!.isEmpty) { return 'Please enter your City.'.tr; } return null; }, ), ), ], ), const SizedBox( height: 15, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ InkWell( onTap: () => controller.getBirthDate(), child: Container( height: 50, width: Get.width * .4, decoration: BoxDecoration( border: Border.all(), borderRadius: BorderRadius.circular(13)), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 20), child: Text( controller.birthDate, style: AppStyle.title, ), ), ), ), // DropdownButton( // value: controller.gender, // items: [ // DropdownMenuItem( // value: 'Male'.tr, // child: Text('Male'.tr), // ), // DropdownMenuItem( // value: 'Female'.tr, // child: Text('Female'.tr), // ), // DropdownMenuItem( // value: '--'.tr, // child: Text('--'.tr), // ), // ], // onChanged: (value) { // controller.changeGender(value!); // }, // ) ], ), MyElevatedButton( title: 'Register'.tr, onPressed: () => controller.register()) ]), ), ), ), ), ), ) ], isleading: true); } } ================================================== FILE PATH: ./lib/views/auth/verify_email_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/auth/register_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; class VerifyEmailPage extends StatelessWidget { const VerifyEmailPage({super.key}); @override Widget build(BuildContext context) { Get.put(RegisterController()); return MyScafolld( title: 'Verify Email'.tr, body: [ Positioned( top: 10, left: 20, right: 20, child: Text( 'We sent 5 digit to your Email provided'.tr, style: AppStyle.title.copyWith(fontSize: 20), )), GetBuilder( builder: (controller) => Positioned( top: 100, left: 80, right: 80, child: Padding( padding: const EdgeInsets.all(10), child: Column( children: [ SizedBox( width: 100, child: TextField( controller: controller.verfyCode, decoration: InputDecoration( labelStyle: AppStyle.title, border: const OutlineInputBorder(), hintText: '5 digit'.tr, counterStyle: AppStyle.number, hintStyle: AppStyle.subtitle .copyWith(color: AppColor.accentColor), ), maxLength: 5, keyboardType: TextInputType.number, ), ), const SizedBox( height: 30, ), MyElevatedButton( title: 'Send Verfication Code'.tr, onPressed: () => controller.sendVerifications()) ], ), ), )), ], isleading: true, ); } Padding verifyEmail() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Container( decoration: BoxDecoration( border: Border.all( color: AppColor.accentColor, width: 2, ), borderRadius: BorderRadius.circular(8), ), child: const Padding( padding: EdgeInsets.all(10), child: SizedBox( width: 20, child: TextField( maxLength: 1, keyboardType: TextInputType.number, ), ), ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/country_widget.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../controller/auth/captin/login_captin_controller.dart'; import '../../controller/profile/profile_controller.dart'; import '../../main.dart'; import '../widgets/elevated_btn.dart'; import 'captin/login_captin.dart'; class CountryPicker extends StatelessWidget { final ProfileController controller = Get.put(ProfileController()); final List countryOptions = [ 'Jordan', 'USA', 'Egypt', 'Turkey', 'Saudi Arabia', 'Qatar', 'Bahrain', 'Kuwait', ]; CountryPicker({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetBuilder(builder: (controller) { return Padding( padding: const EdgeInsets.all(20), child: ListView( children: [ const SizedBox( height: 20, ), Text( "Select Your Country".tr, style: AppStyle.headTitle2, textAlign: TextAlign.center, ), // const SizedBox( // height: 20, // ), Padding( padding: const EdgeInsets.all(10), child: Text( "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country." .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), SizedBox( height: 200, child: CupertinoPicker( itemExtent: 32, onSelectedItemChanged: (int index) { controller.setCountry(countryOptions[index]); box.write(BoxName.countryCode, countryOptions[index]); // Save in English }, children: List.generate( countryOptions.length, (index) => Center( child: Text( countryOptions[index] .tr, // Display translated if not English style: AppStyle.title, ), ), ), ), ), MyElevatedButton( title: 'Select Country'.tr, // Use translated text for button onPressed: () { Get.find().saveCountryCode(controller .selectedCountry .toString()); // No conversion needed box.write( BoxName.countryCode, // controller.selectedCountry); // Already saved in English Get.snackbar(controller.selectedCountry.toString().tr, ''); Get.off(LoginCaptin()); }, ) ], ), ); }); } } class CountryPickerFromSetting extends StatelessWidget { final ProfileController controller = Get.put(ProfileController()); final LoginDriverController loginController = Get.put(LoginDriverController()); final List countryOptions = [ 'Jordan', 'Egypt', 'Turkey', 'Saudi Arabia', 'Qatar', 'Bahrain', 'Kuwait', 'USA', ]; CountryPickerFromSetting({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetBuilder(builder: (controller) { return Padding( padding: const EdgeInsets.all(20.0), child: ListView( children: [ const SizedBox( height: 20, ), Text( "Select Your Country".tr, style: AppStyle.headTitle2, textAlign: TextAlign.center, ), // const SizedBox( // height: 20, // ), Padding( padding: const EdgeInsets.all(10), child: Text( "To ensure you receive the most accurate information for your location, please select your country below. This will help tailor the app experience and content to your country." .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), SizedBox( height: 200, child: CupertinoPicker( itemExtent: 32, onSelectedItemChanged: (int index) { controller.setCountry(countryOptions[index]); box.write(BoxName.countryCode, countryOptions[index]); // Save in English }, children: List.generate( countryOptions.length, (index) => Center( child: Text( countryOptions[index] .tr, // Display translated if not English style: AppStyle.title, ), ), ), ), ), MyElevatedButton( title: 'Select Country'.tr, // Use translated text for button onPressed: () async { loginController.saveCountryCode(controller.selectedCountry .toString()); // No conversion needed box.write( BoxName.countryCode, // controller.selectedCountry); // Already saved in English Get.snackbar(controller.selectedCountry.toString().tr, '', backgroundColor: AppColor.greenColor); // Get.back();// // Get.back(); }, ) ], ), ); }); } } ================================================== FILE PATH: ./lib/views/auth/syria/pending_driver_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'dart:math' as math; class DriverVerificationScreen extends StatefulWidget { const DriverVerificationScreen({super.key}); @override State createState() => _DriverVerificationScreenState(); } class _DriverVerificationScreenState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 2), )..repeat(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( backgroundColor: const Color(0xFFF8F9FA), body: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ // Animated Icon AnimatedBuilder( animation: _controller, builder: (_, child) { return Transform.rotate( angle: _controller.value * 2 * math.pi, child: child, ); }, child: Icon( Icons.sync, size: 80, color: theme.primaryColor.withOpacity(0.8), ), ), const SizedBox(height: 32), // Title Text( "Your Application is Under Review".tr, textAlign: TextAlign.center, style: TextStyle( fontSize: 26, fontWeight: FontWeight.bold, color: theme.textTheme.titleLarge?.color, ), ), const SizedBox(height: 16), // Main Message Text( "We have received your application to join us as a driver. Our team is currently reviewing it. Thank you for your patience." .tr, textAlign: TextAlign.center, style: const TextStyle( fontSize: 16, color: Colors.black54, height: 1.5, ), ), const SizedBox(height: 32), // Notification Card Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: theme.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all( color: theme.primaryColor.withOpacity(0.3), width: 1, ), ), child: Row( children: [ Icon(Icons.notifications_active_outlined, color: theme.primaryColor, size: 30), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "You Will Be Notified".tr, style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: theme.primaryColor, ), ), const SizedBox(height: 4), Text( "We will send you a notification as soon as your account is approved. You can safely close this page, and we'll let you know when the review is complete." .tr, style: const TextStyle( fontSize: 14, color: Colors.black87, height: 1.4, ), ), ], ), ), ], ), ), const SizedBox(height: 40), // Refresh Button // ElevatedButton.icon( // onPressed: () { // // TODO: Add logic to check status from your API // Get.snackbar( // "Status", // This can also be a key if you want // "Checking for updates...".tr, // snackPosition: SnackPosition.BOTTOM, // ); // }, // icon: const Icon(Icons.refresh, color: Colors.white), // label: Text( // "Refresh Status".tr, // style: const TextStyle(fontSize: 16, color: Colors.white), // ), // style: ElevatedButton.styleFrom( // backgroundColor: theme.primaryColor, // padding: const EdgeInsets.symmetric( // horizontal: 40, vertical: 15), // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(30.0), // ), // elevation: 3, // ), // ), ], ), ), ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/syria/registration_view.dart ================================================== import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../controller/auth/syria/registration_controller.dart'; class RegistrationView extends StatelessWidget { const RegistrationView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final RegistrationController controller = Get.put(RegistrationController()); return Scaffold( appBar: AppBar( title: Text('Driver Registration'.tr), centerTitle: true, ), body: Column( children: [ SizedBox( height: 90, child: Obx( () => Stepper( currentStep: controller.currentPage.value, type: StepperType.horizontal, controlsBuilder: (_, __) => const SizedBox.shrink(), steps: [ Step( title: Text('Driver'.tr), content: const SizedBox.shrink()), Step( title: Text('Vehicle'.tr), content: const SizedBox.shrink()), Step( title: Text('Docs'.tr), content: const SizedBox.shrink()), ], ), ), ), Expanded( child: PageView( controller: controller.pageController, physics: const NeverScrollableScrollPhysics(), onPageChanged: (i) => controller.currentPage.value = i, children: [ _buildDriverInfoStep(context, controller), _buildCarInfoStep(context, controller), _buildDocumentUploadStep(context, controller), ], ), ), ], ), bottomNavigationBar: _buildBottomNavBar(controller), ); } // STEP 1 Widget _buildDriverInfoStep(BuildContext ctx, RegistrationController c) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Form( key: c.driverInfoFormKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Driver's Personal Information".tr, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20), TextFormField( controller: c.firstNameController, decoration: InputDecoration( labelText: 'First Name'.tr, border: const OutlineInputBorder(), ), validator: (v) { if (v == null || v.isEmpty) { return 'Required field'.tr; } if (v.length < 2) { return 'Name must be at least 2 characters'.tr; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: c.lastNameController, decoration: InputDecoration( labelText: 'Last Name'.tr, border: const OutlineInputBorder(), ), validator: (v) { if (v == null || v.isEmpty) { return 'Required field'.tr; } if (v.length < 2) { return 'Name must be at least 2 characters'.tr; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: c.nationalIdController, decoration: InputDecoration( labelText: 'National ID Number'.tr, border: const OutlineInputBorder(), ), keyboardType: TextInputType.number, validator: (v) { if (v == null || v.isEmpty) { return 'Required field'.tr; } if (v.length != 11) { return 'National ID must be 11 digits'.tr; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: c.bithdateController, decoration: InputDecoration( labelText: 'سنة الميلاد'.tr, hintText: '1999'.tr, border: const OutlineInputBorder(), ), keyboardType: TextInputType.number, validator: (v) { if (v == null || v.isEmpty) { return 'Required field'.tr; } if (v.length != 4) { return 'Birth year must be 4 digits'.tr; } // Optional: check if it’s a valid number if (int.tryParse(v) == null) { return 'Enter a valid year'.tr; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: c.driverLicenseExpiryController, decoration: InputDecoration( labelText: 'License Expiry Date'.tr, hintText: 'YYYY-MM-DD'.tr, border: const OutlineInputBorder()), readOnly: true, onTap: () async { DateTime? d = await showDatePicker( context: ctx, initialDate: DateTime.now(), firstDate: DateTime(2000), lastDate: DateTime(2101), ); if (d != null) { c.driverLicenseExpiryDate = d; c.driverLicenseExpiryController.text = d.toLocal().toString().split(' ')[0]; } }, validator: (v) => (v?.isEmpty ?? true) ? 'Please select a date'.tr : null, ), ], ), ), ); } // STEP 2 Widget _buildCarInfoStep(BuildContext ctx, RegistrationController c) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Form( key: c.carInfoFormKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Vehicle Information'.tr, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20), TextFormField( controller: c.carPlateController, decoration: InputDecoration( labelText: 'Car Plate Number'.tr, border: const OutlineInputBorder()), validator: (v) => (v?.isEmpty ?? true) ? 'Required field'.tr : null, ), const SizedBox(height: 16), TextFormField( controller: c.carMakeController, decoration: InputDecoration( labelText: 'Car Make (e.g., Toyota)'.tr, border: const OutlineInputBorder()), validator: (v) => (v?.isEmpty ?? true) ? 'Required field'.tr : null, ), const SizedBox(height: 16), TextFormField( controller: c.carModelController, decoration: InputDecoration( labelText: 'Car Model (e.g., Corolla)'.tr, border: const OutlineInputBorder()), validator: (v) => (v?.isEmpty ?? true) ? 'Required field'.tr : null, ), const SizedBox(height: 16), TextFormField( controller: c.carYearController, keyboardType: TextInputType.number, decoration: InputDecoration( labelText: 'Year of Manufacture'.tr, border: const OutlineInputBorder()), validator: (v) => (v?.isEmpty ?? true) ? 'Required field'.tr : null, ), const SizedBox(height: 16), // حقل اسم اللون (يبقى اختياري أو نملؤه تلقائيًا عند اختيار الهكس) // TextFormField( // controller: c.carColorController, // decoration: InputDecoration( // labelText: 'Car Color (Name)'.tr, // border: const OutlineInputBorder(), // ), // validator: (v) => // (v?.isEmpty ?? true) ? 'Required field'.tr : null, // ), // const SizedBox(height: 16), // الدروب داون للهكس + دائرة اللون GetBuilder( id: 'carColor', // اختياري لتحديث انتقائي builder: (c) { return DropdownButtonFormField( value: (c.colorHex != null && c.colorHex!.isNotEmpty) ? c.colorHex : null, isExpanded: true, decoration: InputDecoration( labelText: 'Car Color (Hex)'.tr, border: const OutlineInputBorder(), // prefixIcon: Padding( // padding: // const EdgeInsetsDirectional.only(start: 12, end: 8), // child: Container( // width: 18, // height: 18, // decoration: BoxDecoration( // color: (c.colorHex?.isNotEmpty ?? false) // ? c.hexToColor(c.colorHex!) // : Colors.transparent, // shape: BoxShape.circle, // border: Border.all(color: Colors.black26), // ), // ), // ), ), items: RegistrationController.kCarColorOptions.map((opt) { final hex = opt['hex']!; final key = opt['key']!; return DropdownMenuItem( value: hex, child: Row( children: [ Container( width: 18, height: 18, decoration: BoxDecoration( color: c.hexToColor(hex), shape: BoxShape.circle, border: Border.all(color: Colors.black12), ), ), const SizedBox(width: 8), Expanded(child: Text(key.tr)), ], ), ); }).toList(), onChanged: (hex) { c.colorHex = hex; // خزّن الهكس final key = RegistrationController.kCarColorOptions .firstWhere((o) => o['hex'] == hex)['key']!; c.carColorController.text = key.tr; c.update([ 'carColor' ]); // <-- مهم: يعيد بناء الودجت ويحدّث الدائرة }, validator: (v) => (v == null || v.isEmpty) ? 'Required field'.tr : null, ); }, ) ], ), ), ); } // STEP 3 Widget _buildDocumentUploadStep(BuildContext ctx, RegistrationController c) { final String linkUpload = 'https://syria.intaleq.xyz/intaleq/auth/syria/uploadImage.php'; return GetBuilder( builder: (ctrl) => SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Upload Documents'.tr, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20), _buildImagePickerBox( 'Driver License (Front)'.tr, ctrl.docUrls['driver_license_front'], // () => ctrl.pickImage(ImageType.driverLicenseFront), () async => await ctrl.choosImage(linkUpload, 'driver_license_front'), ), _buildImagePickerBox( 'Driver License (Back)'.tr, ctrl.docUrls['driver_license_back'], () async => await ctrl.choosImage(linkUpload, 'driver_license_back'), // () => ctrl.pickImage(ImageType.driverLicenseBack), ), _buildImagePickerBox( 'Car Registration (Front)'.tr, ctrl.docUrls['car_license_front'], () async => await ctrl.choosImage(linkUpload, 'car_license_front'), // () => ctrl.pickImage(ImageType.carLicenseFront), ), _buildImagePickerBox( 'Car Registration (Back)'.tr, ctrl.docUrls['car_license_back'], () async => await ctrl.choosImage(linkUpload, 'car_license_back'), // () => ctrl.pickImage(ImageType.carLicenseBack), ), ], ), ), ); } Widget signedImageWithAuth(String fileUrl, String bearerToken) { return Image.network( fileUrl, headers: {'Authorization': 'Bearer $bearerToken'}, fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Text('Image expired or unauthorized'), ); } Widget _buildImagePickerBox(String title, String? img, VoidCallback onTap) { return Card( margin: const EdgeInsets.only(bottom: 16), child: InkWell( onTap: onTap, child: SizedBox( height: 150, width: double.infinity, child: (img != null && img.isNotEmpty) ? Image.network( img, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.broken_image, size: 40, color: Colors.red), const SizedBox(height: 8), Text('Image not available', style: TextStyle(color: Colors.red[700])), ], ), ); }, ) : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.camera_alt_outlined, size: 40, color: Colors.grey[600]), const SizedBox(height: 8), Text(title, style: TextStyle(color: Colors.grey[700])), Text('Tap to upload'.tr, style: const TextStyle(color: Colors.grey, fontSize: 12)), ], ), ), ), ); } Widget _buildBottomNavBar(RegistrationController c) { return Obx(() => Padding( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (c.currentPage.value > 0) TextButton( onPressed: c.goToPreviousStep, child: Text('<< BACK'.tr), ), const Spacer(), ElevatedButton( style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 12), backgroundColor: c.currentPage.value == 2 ? Colors.green : Theme.of(Get.context!).primaryColor, ), onPressed: c.isLoading.value ? null : () { if (c.currentPage.value == 2) { c.submitRegistration(); } else { c.goToNextStep(); } }, child: c.isLoading.value ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2)) : Text( c.currentPage.value == 2 ? 'SUBMIT'.tr : 'NEXT >>'.tr, style: const TextStyle(fontSize: 16, color: Colors.white), ), ), ], ), )); } } ================================================== FILE PATH: ./lib/views/auth/captin/contact_us_page.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import '../../../constant/colors.dart'; import '../../../constant/style.dart'; import '../../../controller/functions/tts.dart'; import '../../../controller/home/captin/contact_us_controller.dart'; import '../../widgets/my_scafold.dart'; class ContactUsPage extends StatelessWidget { ContactUsPage({super.key}); @override Widget build(BuildContext context) { Get.put(ContactUsController()); return GetBuilder(builder: (controller) { return MyScafolld( title: "Contact Us".tr, body: [ Padding( padding: const EdgeInsets.all(8.0), child: ListView( // crossAxisAlignment: CrossAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( decoration: AppStyle.boxDecoration1, child: Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(15), child: Image.asset('assets/images/logo.gif')), IconButton( onPressed: () async { Get.put(TextToSpeechController()).speakText( 'Intaleq is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.' .tr); }, icon: const Icon(Icons.headphones), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( 'Intaleq is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.' .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), ], ), ), const SizedBox( height: 30, ), Container( decoration: AppStyle.boxDecoration1, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( "You can contact us during working hours from 10:00 - 17:00." .tr, style: AppStyle.title, textAlign: TextAlign.center, ), ), ), InkWell( onTap: () => controller.showContactDialog(context), child: const Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Icon( Icons.phone, color: AppColor.blueColor, ), Icon( FontAwesome.whatsapp, color: AppColor.greenColor, ), Icon( Icons.email, color: AppColor.redColor, ), ], ), ), const SizedBox( height: 30, ) ], ), ) ], isleading: true); }); } } ================================================== FILE PATH: ./lib/views/auth/captin/forget.dart ================================================== ================================================== FILE PATH: ./lib/views/auth/captin/register_captin.dart ================================================== import 'package:sefer_driver/constant/style.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/auth/captin/register_captin_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import '../../../constant/colors.dart'; import '../../../controller/auth/google_sign.dart'; class RegisterCaptin extends StatelessWidget { const RegisterCaptin({super.key}); @override Widget build(BuildContext context) { Get.put(RegisterCaptainController()); return MyScafolld( title: 'Register Driver'.tr, body: [ // GetBuilder( // builder: (controller) => Form( // key: controller.formKey, // child: Padding( // padding: const EdgeInsets.all(16.0), // child: SingleChildScrollView( // child: Container( // decoration: const BoxDecoration( // boxShadow: [ // BoxShadow( // offset: Offset(3, 3), // color: AppColor.accentColor, // blurRadius: 3) // ], // color: AppColor.secondaryColor, // ), // child: Padding( // padding: const EdgeInsets.all(16), // child: Column( // children: [ // SizedBox( // width: Get.width * .8, // child: TextFormField( // keyboardType: TextInputType.emailAddress, // controller: controller.emailController, // decoration: InputDecoration( // focusedBorder: OutlineInputBorder( // borderSide: const BorderSide( // color: AppColor.primaryColor, // width: 2.0, // ), // borderRadius: BorderRadius.circular(10), // ), // fillColor: AppColor.accentColor, // hoverColor: AppColor.accentColor, // focusColor: AppColor.accentColor, // border: const OutlineInputBorder( // borderRadius: // BorderRadius.all(Radius.circular(12))), // labelText: 'Email'.tr, // hintText: 'Enter your email address'.tr, // ), // validator: (value) { // if (value!.isEmpty || // (!value.contains('@') || // !value.contains('.'))) { // return 'Please enter Your Email.'.tr; // } // return null; // }, // ), // ), // const SizedBox( // height: 15, // ), // SizedBox( // width: Get.width * .8, // child: TextFormField( // obscureText: true, // keyboardType: TextInputType.emailAddress, // controller: controller.passwordController, // decoration: InputDecoration( // focusedBorder: OutlineInputBorder( // borderSide: const BorderSide( // color: AppColor.primaryColor, // width: 2.0, // ), // borderRadius: BorderRadius.circular(10), // ), // fillColor: AppColor.accentColor, // hoverColor: AppColor.accentColor, // focusColor: AppColor.accentColor, // border: const OutlineInputBorder( // borderRadius: // BorderRadius.all(Radius.circular(12))), // labelText: 'Password'.tr, // hintText: 'Enter your Password'.tr, // ), // validator: (value) { // if (value!.isEmpty) { // return 'Please enter Your Password.'.tr; // } // if (value.length < 6) { // return 'Password must br at least 6 character.' // .tr; // } // return null; // }, // ), // ), // const SizedBox( // height: 15, // ), // SizedBox( // width: Get.width * .8, // child: TextFormField( // keyboardType: TextInputType.phone, // cursorColor: AppColor.accentColor, // controller: controller.phoneController, // decoration: InputDecoration( // focusedBorder: OutlineInputBorder( // borderSide: const BorderSide( // color: AppColor.primaryColor, // width: 2.0, // ), // borderRadius: BorderRadius.circular(10), // ), // focusColor: AppColor.accentColor, // fillColor: AppColor.accentColor, // border: const OutlineInputBorder( // borderRadius: // BorderRadius.all(Radius.circular(12))), // labelText: 'Phone'.tr, // hintText: 'Enter your phone number'.tr, // ), // validator: (value) { // if (value!.isEmpty || value.length != 10) { // return 'Please enter your phone number.'.tr; // } // return null; // }, // ), // ), // const SizedBox( // height: 15, // ), // MyElevatedButton( // title: 'Next'.tr, // onPressed: () => controller.nextToAIDetection()), // ], // ), // ), // ), // ), // ), // ), // ) Image.asset( 'assets/images/on1.png', fit: BoxFit.cover, height: double.maxFinite, width: double.maxFinite, ), Center( child: Container( decoration: AppStyle.boxDecoration1, height: Get.height * .7, width: Get.width * .9, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Image.asset( 'assets/images/logo.gif', height: Get.width * .3, width: Get.width * .3, fit: BoxFit.fill, ), Container( decoration: AppStyle.boxDecoration1, height: Get.height * .3, width: Get.width * .8, child: Center( child: Text( 'Sign in with Google for easier email and name entry'.tr, textAlign: TextAlign.center, style: AppStyle.title, ), ), ), MyElevatedButton( title: 'Sign In by Google'.tr, onPressed: () async { // await GoogleSignInHelper.signIn(); }, kolor: AppColor.blueColor, ), ], ), )) ], isleading: true); } } ================================================== FILE PATH: ./lib/views/auth/captin/logout_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/controller/functions/log_out.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; class LogoutCaptain extends StatelessWidget { const LogoutCaptain({super.key}); @override Widget build(BuildContext context) { return MyScafolld( title: 'Log Out Page'.tr, body: [ Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ MyElevatedButton( title: 'Log Off'.tr, onPressed: () { LogOutController().logOutCaptain(); }), const SizedBox( height: 30, ), MyElevatedButton( title: 'Delete My Account'.tr, onPressed: () { LogOutController().deletecaptainAccount(); }, kolor: AppColor.redColor, ), ], ), ) ], isleading: true, ); } } ================================================== FILE PATH: ./lib/views/auth/captin/invite_driver_screen.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../controller/auth/captin/invit_controller.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../main.dart'; class InviteScreen extends StatelessWidget { final InviteController controller = Get.put(InviteController()); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: CupertinoColors.systemBackground, appBar: AppBar( backgroundColor: CupertinoColors.systemBackground, elevation: 0, title: Text( 'Invite'.tr, style: const TextStyle(color: CupertinoColors.label), ), leading: IconButton( icon: const Icon(Icons.arrow_back_ios, color: AppColor.blueColor), onPressed: () => Get.back(), ), ), body: SafeArea( child: GetBuilder( builder: (controller) { return Column( children: [ Padding( padding: const EdgeInsets.all(16.0), child: Container( decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(8), ), child: SegmentedButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.resolveWith( (states) => states.contains(WidgetState.selected) ? CupertinoColors.white : Colors.transparent, ), foregroundColor: WidgetStateProperty.resolveWith( (states) => states.contains(WidgetState.selected) ? AppColor.blueColor : CupertinoColors.label, ), ), segments: [ ButtonSegment( value: 0, label: Padding( padding: const EdgeInsets.all(8.0), child: Text('Drivers'.tr), ), ), ButtonSegment( value: 1, label: Padding( padding: const EdgeInsets.all(8.0), child: Text('Passengers'.tr), ), ), ], selected: {controller.selectedTab}, onSelectionChanged: (Set newSelection) { controller.updateSelectedTab(newSelection.first); }, ), ), ), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: controller.selectedTab == 0 ? _buildDriverTab(context) : _buildPassengerTab(context), ), ), ], ); }, ), ), ); } Widget _buildDriverTab(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 20), Text( "Invite another driver and both get a gift after he completes 100 trips!" .tr, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, color: CupertinoColors.label, ), ), const SizedBox(height: 20), _buildPhoneInput(), const SizedBox(height: 20), _buildActionButtons(), const SizedBox(height: 20), _buildInvitationsList(context), ], ); } Widget _buildPassengerTab(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Text( "Share this code with passengers and earn rewards when they use it!" .tr, textAlign: TextAlign.center, style: const TextStyle( color: CupertinoColors.secondaryLabel, fontSize: 13, ), ), ], ), ), const SizedBox(height: 20), _buildPhoneInput(), const SizedBox(height: 20), _buildActionButtonsPassengers(), const SizedBox(height: 20), const SizedBox(height: 20), _buildInvitationsListPassengers(context), ], ); } Widget _buildPhoneInput() { return Container( decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Expanded( child: CupertinoTextField.borderless( controller: controller.invitePhoneController, placeholder: 'Enter phone'.tr, padding: const EdgeInsets.all(12), keyboardType: TextInputType.phone, ), ), CupertinoButton( child: const Icon(CupertinoIcons.person_badge_plus, color: AppColor.blueColor), onPressed: () async { await controller.pickContactFromNativeApp(); if (controller.contacts.isNotEmpty) { if (box.read(BoxName.isSavedPhones) == null) { // controller.savePhoneToServer(); box.write(BoxName.isSavedPhones, true); } _showContactsDialog(Get.context!); } }, ), ], ), ); } Widget _buildActionButtons() { return Padding( padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0), child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3), ), ], ), child: CupertinoButton( color: AppColor.blueColor, borderRadius: BorderRadius.circular(10), padding: const EdgeInsets.symmetric(vertical: 14), onPressed: controller.sendInvite, child: Text( 'Send Invite'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: CupertinoColors.white, ), ), ), ), ), const SizedBox(width: 16), Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3), ), ], ), child: CupertinoButton( color: AppColor.blueColor, borderRadius: BorderRadius.circular(10), padding: const EdgeInsets.symmetric(vertical: 14), child: Text( 'Show Invitations'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: CupertinoColors.white, ), ), onPressed: () async { controller.fetchDriverStats(); }, ), ), ), ], ), ); } Widget _buildActionButtonsPassengers() { return Padding( padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0), child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3), ), ], ), child: CupertinoButton( color: AppColor.blueColor, borderRadius: BorderRadius.circular(10), padding: const EdgeInsets.symmetric(vertical: 14), onPressed: controller.sendInviteToPassenger, child: Text( 'Send Invite'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: CupertinoColors.white, ), ), ), ), ), const SizedBox(width: 16), Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 6, offset: const Offset(0, 3), ), ], ), child: CupertinoButton( color: AppColor.blueColor, borderRadius: BorderRadius.circular(10), padding: const EdgeInsets.symmetric(vertical: 14), child: Text( 'Show Invitations'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: CupertinoColors.white, ), ), onPressed: () async { controller.fetchDriverStatsPassengers(); }, ), ), ), ], ), ); } Widget _buildInvitationsList(BuildContext context) { return SizedBox( height: Get.height * .4, child: controller.driverInvitationData.isEmpty ? Center( child: Text( "No invitation found yet!".tr, style: const TextStyle( color: CupertinoColors.secondaryLabel, fontSize: 17, ), ), ) : ListView.builder( itemCount: controller.driverInvitationData.length, itemBuilder: (context, index) { return _buildInvitationItem(context, index); }, ), ); } Widget _buildInvitationsListPassengers(BuildContext context) { return SizedBox( height: Get.height * .4, child: controller.driverInvitationDataToPassengers.isEmpty ? Center( child: Text( "No invitation found yet!".tr, style: const TextStyle( color: CupertinoColors.secondaryLabel, fontSize: 17, ), ), ) : ListView.builder( itemCount: controller.driverInvitationDataToPassengers.length, itemBuilder: (context, index) { return _buildInvitationItemPassengers(context, index); }, ), ); } Widget _buildInvitationItem(BuildContext context, int index) { int countOfInvitDriver = int.tryParse( (controller.driverInvitationData[index]['countOfInvitDriver']) ?.toString() ?? '0') ?? 0; double progressValue = (countOfInvitDriver / 100.0).clamp(0.0, 1.0); return GestureDetector( onTap: () { controller.onSelectDriverInvitation(index); }, child: Container( margin: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( (controller.driverInvitationData[index]['invitorName']), style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, color: CupertinoColors.label, ), ), const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: progressValue, backgroundColor: CupertinoColors.systemGrey4, valueColor: const AlwaysStoppedAnimation(AppColor.blueColor), minHeight: 6, ), ), const SizedBox(height: 4), Text( '$countOfInvitDriver / 100 ${'Trip'.tr}', style: const TextStyle( fontSize: 13, color: CupertinoColors.secondaryLabel, ), ), ], ), ), ); } Widget _buildInvitationItemPassengers(BuildContext context, int index) { // Extracting the data from the sample JSON-like structure var invitation = controller.driverInvitationDataToPassengers[index]; int countOfInvitDriver = int.tryParse((invitation['countOfInvitDriver'])?.toString() ?? '0') ?? 0; double progressValue = (countOfInvitDriver / 10.0).clamp(0.0, 1.0); return GestureDetector( onTap: () { controller.onSelectPassengerInvitation(index); }, child: Container( margin: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( (invitation['passengerName']) .toString(), // Handle null or missing data style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, color: CupertinoColors.label, ), ), const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: progressValue, backgroundColor: CupertinoColors.systemGrey4, valueColor: const AlwaysStoppedAnimation(AppColor.blueColor), minHeight: 6, ), ), const SizedBox(height: 4), Text( '$countOfInvitDriver / 3 ${'Trip'.tr}', // Show trips completed style: const TextStyle( fontSize: 13, color: CupertinoColors.secondaryLabel, ), ), ], ), ), ); } Widget _buildPassengerStats(BuildContext context) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: CupertinoColors.systemGrey6, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Your Rewards".tr, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, color: CupertinoColors.label, ), ), const SizedBox(height: 16), _buildStatItem( context, "Total Invites".tr, (controller.driverInvitationDataToPassengers[0] ['countOfInvitDriver'] .toString()), ), _buildStatItem( context, "Active Users".tr, (controller.driverInvitationDataToPassengers[0]['passengerName']) .toString(), ), ], ), ); } Widget _buildStatItem(BuildContext context, String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: const TextStyle( color: CupertinoColors.label, fontSize: 15, ), ), Text( value, style: const TextStyle( fontWeight: FontWeight.w600, color: AppColor.blueColor, fontSize: 15, ), ), ], ), ); } void _showContactsDialog(BuildContext context) { showCupertinoModalPopup( context: context, builder: (BuildContext context) => Container( height: 400, color: CupertinoColors.systemBackground, child: Column( children: [ Container( padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: CupertinoColors.separator.withOpacity(0.5)), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CupertinoButton( padding: EdgeInsets.zero, child: Text('Cancel'.tr), onPressed: () => Navigator.pop(context), ), Text( 'Choose from contact'.tr, style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, ), ), const SizedBox(width: 60), // For balance ], ), ), Expanded( child: ListView.builder( itemCount: controller.contactMaps.length, itemBuilder: (context, index) { final contact = controller.contactMaps[index]; return Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( color: CupertinoColors.separator.withOpacity(0.5), ), ), ), child: CupertinoButton( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( contact['name'], style: const TextStyle( color: CupertinoColors.label, fontSize: 17, ), ), Text( (contact['phones'][0].toString()), style: const TextStyle( color: CupertinoColors.secondaryLabel, fontSize: 15, ), ), ], ), ), const Icon( CupertinoIcons.chevron_right, color: CupertinoColors.secondaryLabel, ), ], ), onPressed: () { controller.selectPhone(contact['phones'].toString()); // Navigator.pop(context); }, ), ); }, ), ), ], ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/otp_page.dart ================================================== import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; // --- Placeholder Imports --- // Assuming these files exist in your project structure. import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../controller/auth/captin/phone_helper_controller.dart'; import '../../../controller/local/phone_intel/intl_phone_field.dart'; import '../../../main.dart'; import '../../../print.dart'; // Assuming you have an AppColor class defined in your project. // import 'path/to/your/app_color.dart'; /// A visually revamped authentication screen with a light, glassy effect, /// themed for the driver application using a green primary color. class AuthScreen extends StatelessWidget { final String title; final String subtitle; final Widget form; const AuthScreen({ super.key, required this.title, required this.subtitle, required this.form, }); /// Shows a dialog for testers to log in using email and password. void _showTesterLoginDialog( BuildContext context, LoginDriverController controller) { final testerEmailController = TextEditingController(); final testerPasswordController = TextEditingController(); final testerFormKey = GlobalKey(); showDialog( context: context, barrierDismissible: true, builder: (BuildContext dialogContext) { return BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: AlertDialog( backgroundColor: Colors.white.withOpacity(0.85), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), title: const Text( 'App Tester Login', textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.black87), ), content: Form( key: testerFormKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ TextFormField( controller: testerEmailController, keyboardType: TextInputType.emailAddress, style: const TextStyle(color: Colors.black), decoration: InputDecoration( labelText: 'Email', prefixIcon: const Icon(Icons.email_outlined), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: AppColor.greenColor, width: 2), ), ), validator: (value) => value == null || !value.contains('@') ? 'Enter a valid email'.tr : null, ), const SizedBox(height: 16), TextFormField( controller: testerPasswordController, obscureText: true, style: const TextStyle(color: Colors.black), decoration: InputDecoration( labelText: 'Password', prefixIcon: const Icon(Icons.lock_outline), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: AppColor.greenColor, width: 2), ), ), validator: (value) => value == null || value.isEmpty ? 'Enter a password' : null, ), ], ), ), actions: [ TextButton( child: const Text('Cancel'), onPressed: () => Navigator.of(dialogContext).pop(), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text('Login', style: TextStyle(color: Colors.white)), onPressed: () { if (testerFormKey.currentState!.validate()) { controller.logintest( testerPasswordController.text.trim(), testerEmailController.text.trim(), ); Navigator.of(dialogContext).pop(); } }, ), ], ), ); }, ); } @override Widget build(BuildContext context) { // Controller for the driver's login logic final loginController = Get.put(LoginDriverController()); return Scaffold( body: Container( // NEW: Light and airy gradient with green accents decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.white, Colors.green.shade50, ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: Stack( children: [ // Subtle background shapes with the new primary color Positioned( top: -80, left: -100, child: Container( width: 250, height: 250, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.greenColor.withOpacity(0.1), ), ), ), Positioned( bottom: -120, right: -150, child: Container( width: 350, height: 350, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.greenColor.withOpacity(0.15), ), ), ), Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // GestureDetector for tester login GestureDetector( onLongPress: () { _showTesterLoginDialog(context, loginController); }, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.5), border: Border.all( color: Colors.white.withOpacity(0.8), width: 2), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, spreadRadius: 5) ]), child: ClipRRect( borderRadius: BorderRadius.circular(50), child: Image.asset('assets/images/logo.gif', height: 100)), ), ), const SizedBox(height: 20), Text( title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.black87), ), const SizedBox(height: 10), Text( subtitle, textAlign: TextAlign.center, style: const TextStyle( fontSize: 16, color: Colors.black54, ), ), const SizedBox(height: 30), // Glassmorphism Container for the form with a whiter look ClipRRect( borderRadius: BorderRadius.circular(25.0), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: Container( padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( color: Colors.white.withOpacity(0.6), borderRadius: BorderRadius.circular(25.0), border: Border.all( color: Colors.white.withOpacity(0.8), width: 1.5, ), ), child: form, ), ), ), const SizedBox(height: 20), // Button for app testers, adapted to the light theme Material( color: Colors.black.withOpacity(0.05), borderRadius: BorderRadius.circular(12), child: InkWell( onTap: () => _showTesterLoginDialog(context, loginController), borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric( vertical: 10, horizontal: 16), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.admin_panel_settings_outlined, color: Colors.black.withOpacity(0.6)), const SizedBox(width: 8), Text( 'For App Reviewers / Testers', style: TextStyle( color: Colors.black.withOpacity(0.6), fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ], ), ), ), ], ), ), ); } } // --- UI Screens --- class PhoneNumberScreen extends StatefulWidget { const PhoneNumberScreen({super.key}); @override State createState() => _PhoneNumberScreenState(); } class _PhoneNumberScreenState extends State { final _phoneController = TextEditingController(); final _formKey = GlobalKey(); bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); final rawPhone = _phoneController.text.trim().replaceFirst('+', ''); final success = await PhoneAuthHelper.sendOtp(rawPhone); if (success && mounted) { // Get.to(() => OtpVerificationScreen(phoneNumber: rawPhone)); await PhoneAuthHelper.verifyOtp(rawPhone); } if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'welcome to intaleq'.tr, subtitle: 'login or register subtitle'.tr, form: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'Enter your phone number'.tr, style: TextStyle(color: Colors.black87, fontSize: 16), textAlign: TextAlign.center, ), const SizedBox(height: 20), IntlPhoneField( showCountryFlag: false, searchText: 'Search country'.tr, languageCode: 'ar', style: const TextStyle(color: Colors.black), dropdownTextStyle: const TextStyle(color: Colors.black87), decoration: InputDecoration( labelText: 'Phone Number'.tr, hintText: 'witout zero'.tr, labelStyle: const TextStyle(color: Colors.black54), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.black.withOpacity(0.1)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColor.greenColor, width: 2), ), ), initialCountryCode: 'SY', onChanged: (phone) { _phoneController.text = phone.completeNumber; }, validator: (phone) { if (phone == null || phone.number.isEmpty) { return 'Please enter your phone number'.tr; } // Check if the number is a Syrian number if (phone.countryISOCode != 'SY') { return 'Only Syrian phone numbers are allowed'.tr; } // Check if the national number part starts with '0' if (phone.completeNumber.startsWith('96309') || phone.completeNumber.startsWith('+9630') || phone.completeNumber.startsWith('09')) { return 'Please enter the number without the leading 0'.tr; } if (phone.completeNumber.length < 10) { return 'Phone number seems too short'.tr; } return null; }, ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator(color: AppColor.greenColor) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'send otp button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ], ), ), ); } } class OtpVerificationScreen extends StatefulWidget { final String phoneNumber; const OtpVerificationScreen({super.key, required this.phoneNumber}); @override State createState() => _OtpVerificationScreenState(); } class _OtpVerificationScreenState extends State { final _formKey = GlobalKey(); final _otpController = TextEditingController(); bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); await PhoneAuthHelper.verifyOtp(widget.phoneNumber); if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'verify your number title'.tr, subtitle: 'otp sent subtitle'.trParams({'phoneNumber': widget.phoneNumber}), form: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( 'Enter the 5-digit code', style: TextStyle(color: Colors.black87, fontSize: 16), textAlign: TextAlign.center, ), const SizedBox(height: 20), Form( key: _formKey, child: TextFormField( controller: _otpController, textAlign: TextAlign.center, keyboardType: TextInputType.number, maxLength: 5, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.black87, letterSpacing: 18, ), decoration: InputDecoration( counterText: "", hintText: '-----', hintStyle: TextStyle( color: Colors.black.withOpacity(0.2), letterSpacing: 18, fontSize: 28), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(vertical: 10), ), validator: (v) => v == null || v.length < 5 ? '' : null, ), ), const SizedBox(height: 30), _isLoading ? const CircularProgressIndicator(color: AppColor.greenColor) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'verify and continue button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ], ), ); } } class RegistrationScreen extends StatefulWidget { final String phoneNumber; const RegistrationScreen({super.key, required this.phoneNumber}); @override State createState() => _RegistrationScreenState(); } class _RegistrationScreenState extends State { final _formKey = GlobalKey(); final _firstNameController = TextEditingController(); final _lastNameController = TextEditingController(); final _emailController = TextEditingController(); bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); await PhoneAuthHelper.registerUser( phoneNumber: widget.phoneNumber, firstName: _firstNameController.text.trim(), lastName: _lastNameController.text.trim(), email: _emailController.text.trim(), ); if (mounted) setState(() => _isLoading = false); } } Widget _buildTextFormField({ required TextEditingController controller, required String label, TextInputType keyboardType = TextInputType.text, String? Function(String?)? validator, }) { return TextFormField( controller: controller, style: const TextStyle(color: Colors.black87), decoration: InputDecoration( labelText: label, labelStyle: const TextStyle(color: Colors.black54), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.black.withOpacity(0.1)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColor.greenColor, width: 2), ), ), keyboardType: keyboardType, validator: validator, ); } @override Widget build(BuildContext context) { return AuthScreen( title: 'one last step title'.tr, subtitle: 'complete profile subtitle'.tr, form: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTextFormField( controller: _firstNameController, label: 'first name label'.tr, validator: (v) => v!.isEmpty ? 'first name required'.tr : null, ), const SizedBox(height: 16), _buildTextFormField( controller: _lastNameController, label: 'last name label'.tr, validator: (v) => v!.isEmpty ? 'last name required'.tr : null, ), const SizedBox(height: 16), _buildTextFormField( controller: _emailController, label: 'email optional label'.tr, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator(color: AppColor.greenColor) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'complete registration button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ], ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/ai_page.dart ================================================== import 'package:sefer_driver/controller/functions/crud.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/constant/table_names.dart'; import 'package:sefer_driver/controller/auth/captin/register_captin_controller.dart'; import 'package:sefer_driver/controller/functions/ocr_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../constant/links.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../controller/functions/gemeni.dart'; class AiPage extends StatelessWidget { ScanDocumentsByApi scanDocumentsByApi = Get.put(ScanDocumentsByApi()); RegisterCaptainController registerCaptainController = Get.put(RegisterCaptainController()); @override Widget build(BuildContext context) { Get.put(AI()); String text = ''; return MyScafolld( title: 'Documents check'.tr, body: [ GetBuilder(builder: (controller) { return controller.isLoading ? const MyCircularProgressIndicator() : Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ // egyptDriverLicense(), // egyptCarLicenceFront(), // egyptCarLicenceBack(), // egyptDriverIDFront(), // egyptDriverIDBack(), ], ), ); }), ], isleading: true); } GetBuilder egyptDriverLicenseWidget() { return GetBuilder( builder: (contentController) => contentController.responseMap.isNotEmpty ? contentController.isloading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : SizedBox( height: Get.height * .7, child: ListView( children: [ Container( decoration: AppStyle.boxDecoration1, // height: Get.height * .4, child: Padding( padding: const EdgeInsets.all(5), child: contentController.responseMap.isEmpty ? Center( child: Text( 'Capture an Image of Your Driver’s License' .tr, style: AppStyle.title, ), ) : Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '${'Name'.tr} :${(contentController.responseMap['first_name'])}', style: AppStyle.subtitle, ), Text( ' ${(contentController.responseMap['last_name'])}', style: AppStyle.subtitle, ), ], ), Text( '${'Name in arabic'.tr}: ${(contentController.responseMap['name_in_arabic'])}', style: AppStyle.title, ), Text( '${'Drivers License Class'.tr}: ${contentController.responseMap['class']}', style: AppStyle.title, ), ], ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'National Number'.tr}: ${(contentController.responseMap['id'])}', style: AppStyle.title, ), // Image.memory( // scanDocumentsByApi // .imagePortrait, // width: 60, // ), ]), Text( '${'Address'.tr}: ${(contentController.responseMap['address'])}', style: AppStyle.title, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Date of Birth'.tr}: ${contentController.responseMap['dob']}', style: AppStyle.title, ), Text( '${'Age'.tr} : ${contentController.responseMap['age_in_years']}', style: AppStyle.title, ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Expiry Date'.tr}: ${contentController.responseMap['expiration_date']}', style: DateTime.parse( contentController .responseMap[ 'expiration_date'] .toString()) .isBefore( contentController.now) ? AppStyle.title.copyWith( color: AppColor.redColor) : AppStyle.title.copyWith( color: AppColor.greenColor), ), ], ), ], ), ), ), const SizedBox( height: 10, ), DateTime.parse(contentController .responseMap['expiration_date'] .toString()) .isBefore(contentController.now) ? Text( 'You can\'t continue with us .\nYou should renew Driver license' .tr, style: AppStyle.title .copyWith(color: AppColor.redColor), ) : MyElevatedButton( kolor: AppColor.greenColor, title: 'Lets check Car license '.tr, onPressed: () => contentController .getCarLicenseJordanContent()), const SizedBox( height: 10, ), contentController.responseCarLicenseMapJordan.isNotEmpty ? Container( decoration: AppStyle.boxDecoration, // height: Get.height * .3, width: Get.width * .9, child: Column( children: [ Text( '${'Name'.tr} ${contentController.responseCarLicenseMapJordan['name']}', style: AppStyle.title, ), Text( '${'Address'.tr} ${contentController.responseCarLicenseMapJordan['address']}', style: AppStyle.title, ), Text( '${'Car Kind'.tr} ${contentController.responseCarLicenseMapJordan['car_kind']}', style: AppStyle.title, ), Text( '${'Color'.tr} ${contentController.responseCarLicenseMapJordan['car_color']}', style: AppStyle.title, ), Text( '${'Year'.tr} ${contentController.responseCarLicenseMapJordan['car_year']}', style: AppStyle.title, ), Text( '${'Car Plate'.tr} ${contentController.responseCarLicenseMapJordan['car_plate']}', style: AppStyle.title, ), Text( '${'Car Expire'.tr} ${contentController.responseCarLicenseMapJordan['expire_date_of_license']}', style: contentController .responseCarLicenseMapJordan .isNotEmpty ? DateTime.parse(contentController .responseCarLicenseMapJordan[ 'expire_date_of_license'] .toString()) .isBefore(contentController.now) ? AppStyle.title.copyWith( color: AppColor.redColor) : AppStyle.title.copyWith( color: AppColor.greenColor) : null, ), ], ), ) : const SizedBox(), const SizedBox( height: 10, ), // DateTime.parse(contentController // .responseCarLicenseMap[ // 'expire_date_of_license'] // .toString()) // .isBefore(contentController.now) // ? Text( // 'You can\'t continue with us .\nYou should renew Car license' // .tr, // style: AppStyle.title.copyWith( // color: AppColor.redColor), // ) // : MyElevatedButton( kolor: AppColor.greenColor, title: 'Lets check License Back Face'.tr, onPressed: () => contentController .generateBackCarLicenseJordanContent()), const SizedBox( height: 10, ), contentController.responseBackCarLicenseMap.isNotEmpty ? Container( decoration: AppStyle.boxDecoration, // height: 300, child: Column(children: [ Text( 'VIN ${contentController.responseBackCarLicenseMap['vin']}', style: AppStyle.title, ), Text( 'Fuel Type ${contentController.responseBackCarLicenseMap['fuelType']}', style: AppStyle.title, ), Text( 'Insurance Company ${contentController.responseBackCarLicenseMap['insuranceCompany']}', style: AppStyle.title, ), Text( 'Policy Number ${contentController.responseBackCarLicenseMap['policyNumber']}', style: AppStyle.title, ), Text( 'Insurance Type ${contentController.responseBackCarLicenseMap['insuranceType']}', style: AppStyle.title, ) ])) : const SizedBox() ], ), ) : Positioned( top: Get.height * .06, left: Get.width * .051, right: Get.width * .051, child: scanDocumentsByApi.isLoading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : Column( children: [ Container( decoration: AppStyle.boxDecoration1, height: Get.height * .35, child: Padding( padding: const EdgeInsets.all(5), child: Center( child: InkWell( onTap: () async { await CRUD().allMethodForAI( 'name,address,dob,nationalNo,', AppLink.uploadEgypt, 'idFront'); //egypt }, child: Text( 'Take Picture Of ID Card'.tr, style: AppStyle.title, ), ), )), ), ], ), ), ); } GetBuilder jordanDriverLicenseWidget() { return GetBuilder( builder: (contentController) => contentController.responseMap.isNotEmpty ? Positioned( top: Get.height * .09, left: Get.width * .051, right: Get.width * .051, child: contentController.isloading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : SizedBox( height: Get.height * .7, child: ListView( children: [ Container( decoration: AppStyle.boxDecoration, // height: Get.height * .4, child: Padding( padding: const EdgeInsets.all(5), child: contentController.responseMap.isEmpty ? Center( child: Text( 'There is no data yet.'.tr, style: AppStyle.title, ), ) : Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '${'Name'.tr} :${contentController.responseMap['first_name']}', style: AppStyle.subtitle, ), Text( ' ${contentController.responseMap['last_name']}', style: AppStyle.subtitle, ), ], ), Text( '${'Name in arabic'.tr}: ${contentController.responseMap['name_in_arabic']}', style: AppStyle.title, ), Text( '${'Drivers License Class'.tr}: ${contentController.responseMap['class']}', style: AppStyle.title, ), ], ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'National Number'.tr}: ${contentController.responseMap['id']}', style: AppStyle.title, ), // Image.memory( // scanDocumentsByApi // .imagePortrait, // width: 60, // ), ]), Text( '${'Address'.tr}: ${contentController.responseMap['address']}', style: AppStyle.title, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Date of Birth'.tr}: ${contentController.responseMap['dob']}', style: AppStyle.title, ), Text( '${'Age'.tr} : ${contentController.responseMap['age_in_years']}', style: AppStyle.title, ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Expiry Date'.tr}: ${contentController.responseMap['expiration_date']}', style: DateTime.parse( contentController .responseMap[ 'expiration_date'] .toString()) .isBefore( contentController.now) ? AppStyle.title.copyWith( color: AppColor.redColor) : AppStyle.title.copyWith( color: AppColor.greenColor), ), ], ), ], ), ), ), const SizedBox( height: 10, ), DateTime.parse(contentController .responseMap['expiration_date'] .toString()) .isBefore(contentController.now) ? Text( 'You can\'t continue with us .\nYou should renew Driver license' .tr, style: AppStyle.title .copyWith(color: AppColor.redColor), ) : MyElevatedButton( kolor: AppColor.greenColor, title: 'Lets check Car license '.tr, onPressed: () => contentController .getTextFromCard( '''Extract the following information from the front face of the car license card in Jordan: * name * Address * Vehicle type * car_kind * car_color * Vehicle category * car_year * car_plate * Registration type * Usage type * expire_date_of_license Output the extracted information in the following JSON formate and make date format like YYYY-MM-DD''')), const SizedBox( height: 10, ), contentController .responseCarLicenseMapJordan.isNotEmpty ? Container( decoration: AppStyle.boxDecoration, // height: Get.height * .3, width: Get.width * .9, child: Column( children: [ Text( '${'Name'.tr} ${contentController.responseCarLicenseMapJordan['name']}', style: AppStyle.title, ), Text( '${'Address'.tr} ${contentController.responseCarLicenseMapJordan['address']}', style: AppStyle.title, ), Text( '${'Car Kind'.tr} ${contentController.responseCarLicenseMapJordan['car_kind']}', style: AppStyle.title, ), Text( '${'Color'.tr} ${contentController.responseCarLicenseMapJordan['car_color']}', style: AppStyle.title, ), Text( '${'Year'.tr} ${contentController.responseCarLicenseMapJordan['car_year']}', style: AppStyle.title, ), Text( '${'Car Plate'.tr} ${contentController.responseCarLicenseMapJordan['car_plate']}', style: AppStyle.title, ), Text( '${'ُExpire Date'.tr} ${contentController.responseCarLicenseMapJordan['expire_date_of_license']}', style: contentController .responseCarLicenseMapJordan .isNotEmpty ? DateTime.parse(contentController .responseCarLicenseMapJordan[ 'expire_date_of_license'] .toString()) .isBefore( contentController.now) ? AppStyle.title.copyWith( color: AppColor.redColor) : AppStyle.title.copyWith( color: AppColor.greenColor) : null, ), ], ), ) : const SizedBox(), const SizedBox( height: 10, ), //todo temporary // DateTime.parse(contentController // .responseCarLicenseMap[ // 'expire_date_of_license'] // .toString()) // .isBefore(contentController.now) // ? Text( // 'You can\'t continue with us .\nYou should renew Car license' // .tr, // style: AppStyle.title.copyWith( // color: AppColor.redColor), // ) // : MyElevatedButton( kolor: AppColor.greenColor, title: 'Lets check License Back Face'.tr, onPressed: () => contentController.getTextFromCard( 'write json output from extracting car license back face for these key ,vin,fuelType,passengerType,curbWeight,insuranceCompany,policyNumber,notes,insuranceType and output it json .dont add data else this image', )), const SizedBox( height: 10, ), contentController.responseBackCarLicenseMap.isNotEmpty ? Container( decoration: AppStyle.boxDecoration, // height: 300, child: Column(children: [ Text( 'VIN ${contentController.responseBackCarLicenseMap['vin']}', style: AppStyle.title, ), Text( 'Fuel Type ${contentController.responseBackCarLicenseMap['fuelType']}', style: AppStyle.title, ), Text( 'Insurance Company ${contentController.responseBackCarLicenseMap['insuranceCompany']}', style: AppStyle.title, ), Text( 'Policy Number ${contentController.responseBackCarLicenseMap['policyNumber']}', style: AppStyle.title, ), Text( 'Insurance Type ${contentController.responseBackCarLicenseMap['insuranceType']}', style: AppStyle.title, ) ])) : const SizedBox() // MyElevatedButton( // title: 'Detect Your Face '.tr, // onPressed: () => scanDocumentsByApi // .checkMatchFaceApi(), // ), // scanDocumentsByApi.res.isEmpty // ? const SizedBox() // : scanDocumentsByApi.res['data'] // ['result'] // .toString() == // 'Same' // ? MyElevatedButton( // onPressed: () async { // await registerCaptainController // .register(); // await registerCaptainController // .addLisence(); // // await scanDocumentsByApi // // .uploadImagePortrate(); // }, // title: // 'Go to next step\nscan Car License.' // .tr, // kolor: AppColor.greenColor, // ) // : const SizedBox(), // MyElevatedButton( // title: 'get sql data', // kolor: AppColor.yellowColor, // onPressed: () { // sql.deleteAllData( // TableName.faceDetectTimes); // sql // .getAllData( // TableName.faceDetectTimes) // value[0]['faceDetectTimes'])); // }, // ), ], ), ), ) : Positioned( top: Get.height * .06, left: Get.width * .051, right: Get.width * .051, child: scanDocumentsByApi.isLoading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : Column( children: [ Container( decoration: AppStyle.boxDecoration, height: Get.height * .35, child: Padding( padding: const EdgeInsets.all(5), child: Center( child: Text( 'There is no data yet.'.tr, style: AppStyle.title, ), )), ), ], ), ), ); } GetBuilder usaDriverLicensWidget() { return GetBuilder( builder: (scanDocumentsByApi) => scanDocumentsByApi.responseMap.isNotEmpty ? Positioned( top: Get.height * .06, left: Get.width * .051, right: Get.width * .051, child: scanDocumentsByApi.isLoading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : Column( children: [ Container( decoration: AppStyle.boxDecoration, height: Get.height * .4, child: Padding( padding: const EdgeInsets.all(5), child: scanDocumentsByApi.responseMap.isEmpty ? Center( child: Text( 'There is no data yet.'.tr, style: AppStyle.title, ), ) : Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${'Name :'.tr}${scanDocumentsByApi.name}', style: AppStyle.subtitle, ), Row( mainAxisAlignment: MainAxisAlignment .spaceBetween, children: [ Text( '${'Drivers License Class: '.tr}${scanDocumentsByApi.licenseClass}', style: AppStyle.title, ), Image.memory( scanDocumentsByApi .imageSignature, width: 100, height: 30, ), ], ), ], ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Document Number: '.tr}${scanDocumentsByApi.documentNo}', style: AppStyle.title, ), Image.memory( scanDocumentsByApi.imagePortrait, width: 60, ), ]), Text( '${'Address: '.tr}${scanDocumentsByApi.address}', style: AppStyle.title, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Height: '.tr}${scanDocumentsByApi.height}', style: AppStyle.subtitle, ), Text( 'Postal Code: ${scanDocumentsByApi.postalCode}', style: AppStyle.subtitle, ), Text( 'Sex: ${scanDocumentsByApi.sex}', style: AppStyle.subtitle, ), ], ), Text( 'Territorial Code: ${scanDocumentsByApi.stateCode}', style: AppStyle.subtitle, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'Expiry Date: '.tr}${scanDocumentsByApi.expireDate}', style: DateTime.parse( scanDocumentsByApi .responseMap['data'] ['ocr'] ['dateOfExpiry'] .toString()) .isBefore( scanDocumentsByApi.now) ? AppStyle.title.copyWith( color: AppColor.redColor) : AppStyle.title.copyWith( color: AppColor.greenColor), ), Text( '${'Date of Birth: '.tr}${scanDocumentsByApi.dob}', style: AppStyle.title, ), ], ), ], ), ), ), DateTime.parse(scanDocumentsByApi.responseMap['data'] ['ocr']['dateOfExpiry'] .toString()) .isBefore(scanDocumentsByApi.now) ? Text( 'You can\'t continue with us .\nYou should renew Driver license', style: AppStyle.title .copyWith(color: AppColor.redColor), ) : MyElevatedButton( title: 'Detect Your Face '.tr, onPressed: () => scanDocumentsByApi.checkMatchFaceApi(), ), scanDocumentsByApi.res.isEmpty ? const SizedBox() : scanDocumentsByApi.res['data']['result'] .toString() == 'Same' ? MyElevatedButton( onPressed: () async { await registerCaptainController .register(); await registerCaptainController .addLisence(); // await scanDocumentsByApi // .uploadImagePortrate(); }, title: 'Go to next step\nscan Car License.'.tr, kolor: AppColor.greenColor, ) : const SizedBox(), MyElevatedButton( title: 'get sql data', kolor: AppColor.yellowColor, onPressed: () { sql.deleteAllData(TableName.faceDetectTimes); sql.getAllData(TableName.faceDetectTimes); }, ) ], ), ) : Positioned( top: Get.height * .06, left: Get.width * .051, right: Get.width * .051, child: scanDocumentsByApi.isLoading ? Column( children: [ const MyCircularProgressIndicator(), Text( 'We are process picture please wait '.tr, style: AppStyle.title, ) ], ) : Column( children: [ Container( decoration: AppStyle.boxDecoration, height: Get.height * .35, child: Padding( padding: const EdgeInsets.all(5), child: Center( child: Text( 'There is no data yet.'.tr, style: AppStyle.title, ), )), ), ], ), ), ); } } class EgyptDocuments extends StatelessWidget { const EgyptDocuments({ super.key, required this.contentController, }); final AI contentController; @override Widget build(BuildContext context) { return Positioned( top: 3, left: Get.width * .1, right: Get.width * .1, child: MyElevatedButton( title: 'Take Picture Of ID Card'.tr, //egypt onPressed: () async { await CRUD().allMethodForAI('name,address,dob,nationalNo,', AppLink.uploadEgypt, 'idFront'); //egypt }, )); } } class JordanDocumants extends StatelessWidget { const JordanDocumants({ super.key, required this.contentController, }); final AI contentController; @override Widget build(BuildContext context) { return Positioned( top: 3, left: Get.width * .1, right: Get.width * .1, child: MyElevatedButton( title: 'Take Picture Of Driver License Card'.tr, onPressed: () { contentController.getDriverLicenseJordanContent(); }, )); } } class UsaAiDocuments extends StatelessWidget { const UsaAiDocuments({ super.key, required this.scanDocumentsByApi, }); final ScanDocumentsByApi scanDocumentsByApi; @override Widget build(BuildContext context) { return Positioned( top: 3, left: Get.width * .2, right: Get.width * .2, child: MyElevatedButton( title: 'Take Picture Of ID Card'.tr, onPressed: () { scanDocumentsByApi.scanDocumentsByApi(); }, )); } } ================================================== FILE PATH: ./lib/views/auth/captin/login_captin.dart ================================================== import 'dart:io'; import 'package:sefer_driver/views/auth/captin/contact_us_page.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/info.dart'; import '../../../constant/links.dart'; import '../../../constant/style.dart'; import '../../../controller/auth/apple_sigin.dart'; import '../../../controller/auth/captin/login_captin_controller.dart'; import '../../../controller/auth/google_sign.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../controller/functions/overlay_permisssion.dart'; import '../../../main.dart'; import '../../../print.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/mycircular.dart'; import '../country_widget.dart'; import 'otp_page.dart'; class LoginCaptin extends StatelessWidget { final AuthController authController = Get.put(AuthController()); final LoginDriverController controller = Get.put(LoginDriverController()); LoginCaptin({super.key}); @override Widget build(BuildContext context) { return GetBuilder( builder: (controller) { return Scaffold( backgroundColor: AppColor.secondaryColor, body: SafeArea( child: Center( child: _buildBodyContent(context, controller), ), ), ); }, ); } /// Determines which UI to show based on the driver's progress (agreement, permissions, login). Widget _buildBodyContent( BuildContext context, LoginDriverController controller) { if (box.read(BoxName.agreeTerms) != 'agreed') { return _buildAgreementPage(context, controller); } // if (box.read(BoxName.countryCode) == null) { // return CountryPicker(); // Assumed to be a full-screen widget // } if (box.read(BoxName.locationPermission) != 'true') { return _buildLocationPermissionPage(context, controller); } // Once all permissions are granted, show the main login UI return PhoneNumberScreen(); } /// Redesigned UI for the main login screen. Widget _buildLoginUI(BuildContext context, LoginDriverController controller) { return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 32.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Image.asset('assets/images/logo.gif', height: 120, width: 120), const SizedBox(height: 20), Text( 'Driver Portal'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2.copyWith(fontSize: 28), ), const SizedBox(height: 8), Text( 'Sign in to start your journey'.tr, textAlign: TextAlign.center, style: AppStyle.subtitle, ), const SizedBox(height: 40), // Conditional UI based on the controller state if (controller.isGoogleDashOpen) _buildManualLoginForm(context, controller, isRegistration: true) else if (Platform.isIOS && controller.isTest == 0) _buildManualLoginForm(context, controller, isRegistration: false) else _buildSocialLoginOptions(context, controller), const SizedBox(height: 32), Center( child: GestureDetector( onTap: () => Get.to(() => ContactUsPage()), child: Text( 'Need help? Contact Us'.tr, style: AppStyle.subtitle.copyWith( color: AppColor.blueColor, decoration: TextDecoration.underline, ), ), ), ), ], ), ); } /// Builds the social login buttons (Google, Apple, and manual option). Widget _buildSocialLoginOptions( BuildContext context, LoginDriverController controller) { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Sign in with a provider for easy access'.tr, textAlign: TextAlign.center, style: AppStyle.title, ), const SizedBox(height: 24), _buildSocialButton( text: 'Sign In with Google'.tr, icon: FontAwesome.google, backgroundColor: AppColor.redColor, onPressed: () async { GoogleSignInHelper().signInFromLogin(); }, ), if (Platform.isIOS) ...[ const SizedBox(height: 16), _buildSocialButton( text: 'Sign in with Apple'.tr, icon: Icons.apple, backgroundColor: Colors.black, onPressed: () async { User? user = await authController.signInWithApple(); if (user != null) { box.write(BoxName.emailDriver, user.email.toString()); box.write(BoxName.driverID, user.uid); controller.loginWithGoogleCredential( user.uid, user.email.toString(), ); } }, ), ], const SizedBox(height: 24), Row( children: [ const Expanded(child: Divider()), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text('Or'.tr, style: AppStyle.subtitle), ), const Expanded(child: Divider()), ], ), const SizedBox(height: 24), MyElevatedButton( title: 'Create Account with Email'.tr, onPressed: () => controller.changeGoogleDashOpen(), kolor: AppColor.blueColor, // Using 'kolor' as in your widget ), ], ); } /// Builds the form for manual email/password login or registration. Widget _buildManualLoginForm( BuildContext context, LoginDriverController controller, {required bool isRegistration}) { return Card( elevation: 8, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(20.0), child: Form( key: controller.formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( isRegistration ? 'Create Driver Account'.tr : 'Driver Login'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2, ), const SizedBox(height: 24), _buildTextFormField( controller: controller.emailController, labelText: 'Email'.tr, hintText: 'Enter your email'.tr, prefixIcon: Icons.email_outlined, keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || !GetUtils.isEmail(value)) { return 'Please enter a valid email'.tr; } return null; }, ), const SizedBox(height: 20), GetBuilder( id: 'passwordVisibility', // ID to only rebuild this widget builder: (_) => _buildTextFormField( controller: controller.passwordController, labelText: 'Password'.tr, hintText: 'Enter your password'.tr, prefixIcon: Icons.lock_outline, obscureText: controller.isPasswordHidden, suffixIcon: IconButton( icon: Icon( controller.isPasswordHidden ? Icons.visibility_off : Icons.visibility, color: AppColor.primaryColor, ), onPressed: () => controller.togglePasswordVisibility(), ), validator: (value) { if (value == null || value.length < 6) { return 'Password must be at least 6 characters'.tr; } return null; }, ), ), const SizedBox(height: 30), controller.isloading ? const Center(child: MyCircularProgressIndicator()) : MyElevatedButton( title: (isRegistration ? 'Create Account'.tr : 'Login'.tr), onPressed: () { if (controller.formKey.currentState!.validate()) { if (isRegistration) { String email = controller.emailController.text; String uniqueId = controller.generateUniqueIdFromEmail(email); box.write(BoxName.driverID, uniqueId); box.write(BoxName.emailDriver, email); controller.loginUsingCredentialsWithoutGoogle( controller.passwordController.text, email, ); } else { // This is the flow for iOS manual login controller.loginWithGoogleCredential( controller.passwordController.text, controller.emailController.text, ); } } }, ), if (isRegistration) // Show back button only on the registration form TextButton( onPressed: () => controller.changeGoogleDashOpen(), child: Text( 'Back to other sign-in options'.tr, style: TextStyle(color: AppColor.primaryColor), ), ), ], ), ), ), ); } /// A helper method to create styled TextFormFields. TextFormField _buildTextFormField({ required TextEditingController controller, required String labelText, required String hintText, required IconData prefixIcon, required String? Function(String?) validator, bool obscureText = false, Widget? suffixIcon, TextInputType keyboardType = TextInputType.text, }) { return TextFormField( controller: controller, validator: validator, obscureText: obscureText, keyboardType: keyboardType, decoration: InputDecoration( labelText: labelText, hintText: hintText, prefixIcon: Icon(prefixIcon, color: AppColor.primaryColor), suffixIcon: suffixIcon, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12.0)), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12.0), borderSide: const BorderSide(color: AppColor.primaryColor, width: 2.0), ), ), ); } /// A helper for creating consistent social login buttons. Widget _buildSocialButton({ required String text, required IconData icon, required Color backgroundColor, required VoidCallback onPressed, }) { return ElevatedButton.icon( icon: Icon(icon, color: Colors.white), label: Text(text, style: const TextStyle(color: Colors.white, fontSize: 16)), onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: backgroundColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(vertical: 14), ), ); } /// Redesigned UI for the Terms and Conditions agreement page. Widget _buildAgreementPage( BuildContext context, LoginDriverController controller) { // This UI can be identical to the one in LoginPage for consistency. // I am reusing the improved design from the previous request. return Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.policy_outlined, size: 80, color: AppColor.primaryColor), const SizedBox(height: 20), Text('Driver Agreement'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2), const SizedBox(height: 30), RichText( textAlign: TextAlign.center, text: TextSpan( style: AppStyle.title.copyWith(height: 1.5), children: [ TextSpan( text: "To become a driver, you must review and agree to the " .tr), TextSpan( text: 'Terms of Use'.tr, style: const TextStyle( decoration: TextDecoration.underline, color: AppColor.blueColor, fontWeight: FontWeight.bold), recognizer: TapGestureRecognizer() ..onTap = () { launchUrl( Uri.parse('${AppLink.server}/privacy_policy.php'), mode: LaunchMode.externalApplication); }), TextSpan(text: " and acknowledge our Privacy Policy.".tr), ], ), ), Expanded( child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: SingleChildScrollView( padding: const EdgeInsets.all(12), child: HtmlWidget(box.read(BoxName.lang).toString() == 'ar' ? AppInformation.privacyPolicyArabic : AppInformation.privacyPolicy), ), ), ), CheckboxListTile( title: Text('I Agree'.tr, style: AppStyle.title), value: controller.isAgreeTerms, onChanged: (value) => controller.changeAgreeTerm(), activeColor: AppColor.primaryColor, controlAffinity: ListTileControlAffinity.leading, ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: MyElevatedButton( title: 'Continue'.tr, onPressed: controller.isAgreeTerms ? () => controller.saveAgreementTerms() : () {}, ), ), ], ), ); } /// Redesigned UI for the Location Permission request page. Widget _buildLocationPermissionPage( BuildContext context, LoginDriverController controller) { return Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Icon(Icons.location_on_outlined, size: 80, color: AppColor.primaryColor), const SizedBox(height: 20), Text( 'Location Access Required'.tr, textAlign: TextAlign.center, style: AppStyle.headTitle2, ), const SizedBox(height: 16), Text( 'We need access to your location to match you with nearby passengers and provide accurate navigation.' .tr, textAlign: TextAlign.center, style: AppStyle.title, ), const SizedBox(height: 24), Text( 'Please allow location access "all the time" to receive ride requests even when the app is in the background.' .tr, textAlign: TextAlign.center, style: AppStyle.title.copyWith( color: AppColor.greenColor, fontWeight: FontWeight.bold), ), const SizedBox(height: 40), MyElevatedButton( title: "Allow Location Access".tr, onPressed: () async { Get.put(LoginDriverController()); await getLocationPermission(); // Assumes this function handles the request logic if (await Permission.location.isGranted) { box.write(BoxName.locationPermission, 'true'); controller.update(); // Re-check conditions } }, kolor: AppColor.greenColor, ), const SizedBox(height: 16), TextButton( onPressed: () => openAppSettings(), child: Text("Open Settings".tr, style: const TextStyle(color: AppColor.blueColor)), ), ], ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/otp_token_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../controller/auth/captin/opt_token_controller.dart'; class OtpVerificationPage extends StatefulWidget { final String phone; final String deviceToken; final String token; final String ptoken; const OtpVerificationPage({ super.key, required this.phone, required this.deviceToken, required this.token, required this.ptoken, }); @override State createState() => _OtpVerificationPageState(); } class _OtpVerificationPageState extends State { late final OtpVerificationController controller; final List _focusNodes = List.generate(6, (index) => FocusNode()); final List _textControllers = List.generate(6, (index) => TextEditingController()); @override void initState() { super.initState(); controller = Get.put(OtpVerificationController( phone: widget.phone, deviceToken: widget.deviceToken, token: widget.token, )); } @override void dispose() { for (var node in _focusNodes) { node.dispose(); } for (var controller in _textControllers) { controller.dispose(); } super.dispose(); } void _onOtpChanged(String value, int index) { if (value.isNotEmpty) { if (index < 5) { _focusNodes[index + 1].requestFocus(); } else { _focusNodes[index].unfocus(); // إلغاء التركيز بعد آخر حقل } } else if (index > 0) { _focusNodes[index - 1].requestFocus(); } // تجميع نصوص كل الحقول لتكوين الرمز النهائي controller.otpCode.value = _textControllers.map((c) => c.text).join(); } Widget _buildOtpInputFields() { return Directionality( textDirection: TextDirection.ltr, // لضمان ترتيب الحقول من اليسار لليمين child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(5, (index) { return SizedBox( width: 45, height: 55, child: TextFormField( controller: _textControllers[index], focusNode: _focusNodes[index], textAlign: TextAlign.center, keyboardType: TextInputType.number, maxLength: 1, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold), decoration: InputDecoration( counterText: "", border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: Theme.of(context).primaryColor, width: 2), ), ), onChanged: (value) => _onOtpChanged(value, index), ), ); }), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Verify OTP'.tr), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, ), backgroundColor: Colors.grey[50], body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 20), Icon(Icons.phonelink_lock_rounded, size: 80, color: Theme.of(context).primaryColor), const SizedBox(height: 24), Text( 'Verification Code'.tr, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Text( '${'We have sent a verification code to your mobile number:'.tr} ${widget.phone}', textAlign: TextAlign.center, style: TextStyle( color: Colors.grey.shade600, fontSize: 16, height: 1.5), ), ), const SizedBox(height: 40), _buildOtpInputFields(), const SizedBox(height: 40), Obx(() => SizedBox( width: double.infinity, height: 50, child: controller.isVerifying.value ? const Center(child: CircularProgressIndicator()) : ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12))), onPressed: () => controller.verifyOtp(widget.ptoken), child: Text('Verify'.tr, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600)), ), )), const SizedBox(height: 24), Obx( () => controller.canResend.value ? TextButton( onPressed: controller.sendOtp, child: Text('Resend Code'.tr), ) : Text( '${'You can resend in'.tr} ${controller.countdown.value} ${'seconds'.tr}', style: const TextStyle(color: Colors.grey), ), ) ], ), ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/driver_car_controller.dart ================================================== import 'dart:convert'; import 'package:get/get.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../controller/functions/crud.dart'; import '../../../main.dart'; import '../../widgets/error_snakbar.dart'; class DriverCarController extends GetxController { bool isLoading = false; List cars = []; // int? carId; fetchCatrsForDrivers() async { isLoading = true; update(); var res = await CRUD().get(link: AppLink.getNewCarsDrivers, payload: { "driverID": box.read(BoxName.driverID).toString(), }); if (res != 'failure') { var d = jsonDecode(res)['message']; cars = d; // carId = cars.isEmpty ? 1 : cars.length + 1; } isLoading = false; update(); } addCarsForDrivers( String vin, String carPlate, String make, String model, String year, String expirationDate, String color, String colorHex, String address, String owner, String registrationDate, String displacement, String fuel) async { var res = await CRUD().post( link: AppLink.addRegisrationCar, payload: { "driverID": box.read(BoxName.driverID).toString(), "vin": vin ?? 'unknown', "car_plate": carPlate.toString(), "make": make ?? 'unknown', "model": model ?? 'unknown', "year": year ?? 'unknown', "expiration_date": expirationDate ?? 'unknown', "color": color ?? 'unknown', "owner": owner ?? 'unknown', "color_hex": colorHex ?? '#000000', "address": address ?? 'unknown', "displacement": displacement ?? 'unknown', "fuel": fuel ?? 'unknown', "registration_date": registrationDate ?? 'unknown', }, ); if (res != 'failure') { mySnackbarSuccess(''); fetchCatrsForDrivers(); } else { mySnackeBarError(''); } } // update carRegistration only and insert on it without tow column Future updateCarRegistration(String id, String driverID) async { final body = { 'id': id, 'driverID': driverID, }; // remove default before update var response = await CRUD().post( link: AppLink.makeDefaultCar, payload: body, ); if (response != 'failure') { mySnackbarSuccess('Updated'.tr); } else { mySnackeBarError('Not updated'.tr); } } //todo need review removeCar(String carId) async { isLoading = true; update(); var res = await CRUD().post(link: AppLink.deleteNewCarsDrivers, payload: { "id": carId.toString(), }); if (res != 'failure') { mySnackbarSuccess('deleted'.tr); } isLoading = false; update(); } @override void onInit() { fetchCatrsForDrivers(); super.onInit(); } } ================================================== FILE PATH: ./lib/views/auth/captin/verify_email_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/auth/captin/register_captin_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; class VerifyEmailCaptainPage extends StatelessWidget { VerifyEmailCaptainPage({super.key}); RegisterCaptainController registerCaptinController = Get.put(RegisterCaptainController()); @override Widget build(BuildContext context) { return MyScafolld( title: 'Verify Email For Driver'.tr, body: [ Positioned( top: 10, left: 20, child: Text( 'We sent 5 digit to your Email provided'.tr, style: AppStyle.title.copyWith(fontSize: 20), )), GetBuilder( builder: (controller) => Positioned( top: 100, left: 80, right: 80, child: Padding( padding: const EdgeInsets.all(10), child: Column( children: [ SizedBox( width: 100, child: TextField( controller: registerCaptinController.verifyCode, decoration: InputDecoration( labelStyle: AppStyle.title, border: const OutlineInputBorder(), hintText: '5 digit'.tr, counterStyle: AppStyle.number, hintStyle: AppStyle.subtitle .copyWith(color: AppColor.accentColor), ), maxLength: 5, keyboardType: TextInputType.number, ), ), const SizedBox( height: 30, ), MyElevatedButton( title: 'Send Verfication Code'.tr, onPressed: () { registerCaptinController.sendVerifications(); }) ], ), ), )), ], isleading: true, ); } Padding verifyEmail() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Container( decoration: BoxDecoration( border: Border.all( color: AppColor.accentColor, width: 2, ), borderRadius: BorderRadius.circular(8), ), child: const Padding( padding: EdgeInsets.all(10), child: SizedBox( width: 20, child: TextField( maxLength: 1, keyboardType: TextInputType.number, ), ), ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/criminal_documents_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/links.dart'; import '../../../constant/style.dart'; import '../../../controller/functions/encrypt_decrypt.dart'; import '../../../controller/functions/gemeni.dart'; import '../../../controller/functions/tts.dart'; import '../../../main.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/my_scafold.dart'; class CriminalDocumemtPage extends StatelessWidget { const CriminalDocumemtPage({super.key}); @override Widget build(BuildContext context) { Get.put(AI()); return MyScafolld( title: "Criminal Document".tr, isleading: false, body: [ GetBuilder(builder: (controller) { return Column( children: [ Container( decoration: AppStyle.boxDecoration, child: Padding( padding: const EdgeInsets.all(8.0), child: Text('You have upload Criminal documents'.tr), )), egyptCriminalRecord(), controller.responseCriminalRecordEgypt.isNotEmpty ? MyElevatedButton( title: 'Next'.tr, onPressed: () async { if ((controller .responseCriminalRecordEgypt['FullName']) != box.read(BoxName.nameArabic)) //todo get from server { Get.defaultDialog( barrierDismissible: false, title: 'Criminal Record Mismatch', content: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.warning, size: 48, color: Colors.red), const SizedBox(height: 16), Text( 'The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.' .tr, textAlign: TextAlign.center, style: AppStyle.title, ), const SizedBox(height: 16), IconButton( onPressed: () async { await Get.find() .speakText( 'The full name on your criminal record does not match the one on your driver’s license. Please verify and provide the correct documents.' .tr, ); }, icon: const Icon(Icons.volume_up), ), ], ), actions: [ TextButton( onPressed: () { Get.back(); }, child: const Text('OK'), ), ], ); } else { await controller.addCriminalDocuments(); } }) : const SizedBox(), ], ); }) ], ); } GetBuilder egyptCriminalRecord() { return GetBuilder( builder: (ai) { if (ai.responseCriminalRecordEgypt.isNotEmpty) { return Card( elevation: 4.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Criminal Record'.tr, style: AppStyle.headTitle2), IconButton( onPressed: () async { await ai.allMethodForAI( """ Write a JSON object from the following information extracted from the provided Arabic text: { "InspectionResult": "", "NationalID": "", "FullName": "", "IssueDate": "" // Format: YYYY-MM-DD } Important notes: 1. For the IssueDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9). 2. Add appropriate spaces in all text fields to ensure readability. 3. If any information is missing, leave the corresponding field as an empty string. 4. Ensure all text is properly formatted and spaces are used correctly. 5. Convert any Arabic numerals to Latin numerals (0-9) where applicable. Please fill in the JSON object with the extracted information, following these guidelines. """, AppLink.uploadEgypt, 'criminalRecord', ); }, icon: const Icon(Icons.refresh), ), ], ), const SizedBox(height: 8.0), const Divider(color: AppColor.accentColor), const SizedBox(height: 8.0), Text( '${'InspectionResult'.tr}: ${(ai.responseCriminalRecordEgypt['InspectionResult'])}'), const SizedBox(height: 8.0), Text( '${'FullName'.tr}: ${(ai.responseCriminalRecordEgypt['FullName'])}', style: AppStyle.title.copyWith( color: (ai.responseCriminalRecordEgypt['FullName']) == (ai.responseIdEgyptDriverLicense['name_arabic']) ? AppColor.greenColor : AppColor.redColor), ), const SizedBox(height: 8.0), Text( '${'NationalID'.tr}: ${(ai.responseCriminalRecordEgypt['NationalID'])}'), const SizedBox(height: 8.0), Text( '${'IssueDate'.tr}: ${ai.responseCriminalRecordEgypt['IssueDate']}'), ], ), ), ); } return Card( child: InkWell( onTap: () async { await ai.allMethodForAI( """ Write a JSON object from the following information extracted from the provided Arabic text: { "InspectionResult": "", "NationalID": "", "FullName": "", "IssueDate": "" // Format: YYYY-MM-DD } Important notes: 1. For the IssueDate, ensure the date is in YYYY-MM-DD format using Latin numerals (0-9). 2. Add appropriate spaces in all text fields to ensure readability. 3. If any information is missing, leave the corresponding field as an empty string. 4. Ensure all text is properly formatted and spaces are used correctly. 5. Convert any Arabic numerals to Latin numerals (0-9) where applicable. Please fill in the JSON object with the extracted information, following these guidelines. """, AppLink.uploadEgypt, 'criminalRecord', ); }, child: Column( children: [ Image.asset( 'assets/images/6.png', height: Get.height * .25, width: double.maxFinite, fit: BoxFit.fitHeight, ), Text( 'Capture an Image of Your Criminal Record'.tr, style: AppStyle.title, ), ], ), ), ); }, ); } } ================================================== FILE PATH: ./lib/views/auth/captin/car_license_page.dart ================================================== import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/functions/ocr_controller.dart'; import '../../../constant/style.dart'; import '../../../controller/auth/captin/ml_google_doc.dart'; import '../../../controller/auth/captin/register_captin_controller.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/my_scafold.dart'; // class CarLicensePage extends StatelessWidget { // CarLicensePage({super.key}); // // CarRegistrationRecognizerController carRegistrationRecognizerController = // // Get.put(CarRegistrationRecognizerController()); // RegisterCaptainController registerCaptainController = // Get.put(RegisterCaptainController()); // @override // Widget build(BuildContext context) { // Get.find().uploadImagePortrate(); // return MyScafolld( // title: 'Car License Card'.tr, // body: [ // Positioned( // top: 3, // left: Get.width * .2, // right: Get.width * .2, // child: MyElevatedButton( // title: 'Take Picture Of ID Card'.tr, // onPressed: () async { // //0vQRyaYYDWpsv73A5CZOknseK7S2sgwE // //3vQRyaYYSWpmv69A58ZOkxmeK6M1mgwEDlXrXlBl // //0pALdqDDYHvzp73Q59SIgbzjG7Z2zkhJXr // // String? visionApi = AK.serverPHP; // await carRegistrationRecognizerController.scanText(); // }, // )), // Positioned( // top: 50, // child: SizedBox( // height: Get.height * .6, // width: Get.width, // child: buildImageWithBoundingBoxes(), // ), // ), // Positioned( // bottom: Get.height * .2, // left: Get.width * .2, // right: Get.width * .2, // child: MyElevatedButton( // title: 'Register'.tr, // onPressed: () async { // // registerCaptainController.addLisence(); // // registerCaptainController.register(); // registerCaptainController.addRegisrationCarForDriver( // carRegistrationRecognizerController.extracted['vin'], // carRegistrationRecognizerController.extracted['make'], // carRegistrationRecognizerController.extracted['model'], // carRegistrationRecognizerController.extracted['year'], // carRegistrationRecognizerController.extracted['color'], // carRegistrationRecognizerController.extracted['owner'], // carRegistrationRecognizerController // .extracted['expiration_date'], // carRegistrationRecognizerController // .extracted['registration_date'], // ); // }, // )), // ], // isleading: true); // } // } // Widget buildImageWithBoundingBoxes() { // Get.put(CarRegistrationRecognizerController()); // return GetBuilder( // builder: (carRegistrationRecognizerController) => // carRegistrationRecognizerController.image == null || // carRegistrationRecognizerController.extracted.isEmpty // ? Center( // child: Text( // 'No image selected yet'.tr, // style: AppStyle.headTitle2, // )) // : Column( // children: [ // SizedBox( // width: Get.width * .8, // height: Get.width * .5, // child: Image.file( // File(carRegistrationRecognizerController // .croppedFile!.path), // // fit: BoxFit.fill, // )), // const SizedBox( // height: 20, // ), // Container( // decoration: AppStyle.boxDecoration, // height: Get.width * .5, // width: Get.width * .9, // child: Column( // crossAxisAlignment: CrossAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // Text( // '${'Made :'.tr}${carRegistrationRecognizerController.extracted['make']}', // style: AppStyle.title, // ), // Text( // '${'model :'.tr}${carRegistrationRecognizerController.extracted['model']}', // style: AppStyle.title, // ), // ], // ), // Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // Text( // '${'VIN :'.tr}${carRegistrationRecognizerController.extracted['vin']}', // style: AppStyle.title, // ), // Text( // '${'year :'.tr}${carRegistrationRecognizerController.extracted['year']}', // style: AppStyle.title, // ), // ], // ), // Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // Column( // children: [ // Text( // 'expiration date :${carRegistrationRecognizerController.extracted['expiration_date']}', // style: AppStyle.title, // ), // Text( // 'registration date :${carRegistrationRecognizerController.extracted['registration_date']}', // style: AppStyle.title, // ), // ], // ), // Text( // 'color :${carRegistrationRecognizerController.extracted['color']}', // style: AppStyle.title, // ), // ], // ), // Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // Text( // 'owner :${carRegistrationRecognizerController.extracted['owner']}', // style: AppStyle.title, // ), // ], // ), // ], // ), // ) // ], // )); // } ================================================== FILE PATH: ./lib/views/auth/captin/cards/syrian_card_a_i.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/functions/audio_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/links.dart'; import '../../../../constant/style.dart'; import '../../../../controller/functions/gemeni.dart'; import '../../../../controller/functions/package_info.dart'; import '../../../../controller/functions/tts.dart'; import '../../../../print.dart'; import '../../../widgets/elevated_btn.dart'; import '../../../widgets/my_circular_indicator_timer.dart'; import '../../../widgets/my_scafold.dart'; import '../../../widgets/mydialoug.dart'; // --- اقتراحات الألوان الجديدة --- // يمكنك تعريف هذه الألوان في ملف AppColor.dart الخاص بك class NewAppColor { static const Color primaryColor = Color(0xFF0D47A1); // أزرق داكن static const Color accentColor = Color(0xFF1976D2); // أزرق أفتح static const Color backgroundColor = Color(0xFFF5F7FA); // رمادي فاتح للخلفية static const Color cardColor = Colors.white; static const Color textColor = Color(0xFF333333); // أسود ناعم للنصوص static const Color subTextColor = Color(0xFF757575); // رمادي للنصوص الفرعية static const Color successColor = Color(0xFF2E7D32); // أخضر للنجاح static const Color errorColor = Color(0xFFC62828); // أحمر للخطأ static const Color borderColor = Color(0xFFE0E0E0); // لون الحدود } // --- اقتراحات للخطوط --- // يمكنك استخدام حزمة google_fonts وتعيين الخط 'Cairo' أو 'Tajawal' للتطبيق class NewAppStyle { static TextStyle get headlineStyle { return const TextStyle( fontFamily: 'Cairo', // اسم الخط المقترح fontSize: 18, fontWeight: FontWeight.bold, color: NewAppColor.primaryColor, ); } static TextStyle get titleStyle { return const TextStyle( fontFamily: 'Cairo', fontSize: 16, fontWeight: FontWeight.bold, color: NewAppColor.textColor, ); } static TextStyle get bodyStyle { return const TextStyle( fontFamily: 'Cairo', fontSize: 14, color: NewAppColor.subTextColor, height: 1.5, ); } static TextStyle get valueStyle { return const TextStyle( fontFamily: 'Cairo', fontSize: 15, fontWeight: FontWeight.w600, color: NewAppColor.textColor, ); } } class SyrianCardAI extends StatelessWidget { SyrianCardAI({super.key}); final TextToSpeechController textToSpeechController = Get.put(TextToSpeechController()); @override Widget build(BuildContext context) { Get.put(AI()); WidgetsBinding.instance.addPostFrameCallback((_) { checkForUpdate(context); }); return MyScafolld( // تم تغيير لون الخلفية للتصميم الجديد // backgroundColor: NewAppColor.backgroundColor, title: "Approve Driver Documents".tr, action: GetBuilder(builder: (cont) { return IconButton( onPressed: () { cont.isLoading = false; cont.update(); }, icon: const Icon(Icons.refresh, color: NewAppColor.primaryColor), ); }), body: [ GetBuilder(builder: (controller) { return controller.isLoading ? MyCircularProgressIndicatorWithTimer( isLoading: controller.isLoading, ) : Padding( padding: const EdgeInsets.symmetric( horizontal: 12.0, vertical: 8.0), child: Column( children: [ // --- زر "التالي" بتصميم جديد --- if (controller.licenceFrontSy.isNotEmpty && controller.licenceBackSy.isNotEmpty && (controller.idFrontSy.isNotEmpty) && (controller.idBackSy.isNotEmpty) && controller.vehicleFrontSy.isNotEmpty && controller.vehicleBackSy.isNotEmpty) Padding( padding: const EdgeInsets.only(bottom: 16.0), child: MyElevatedButton( title: 'التالي'.tr, // استخدام اللون الجديد للنجاح kolor: NewAppColor.successColor, onPressed: () { controller.addDriverAndCarEgypt(); }, ), ), Expanded( child: ListView( children: [ // --- فيديو الشرح بتصميم جديد --- VideoButton(), const SizedBox(height: 16), egyptDriverLicense(), const SizedBox(height: 16), syriaDriverLicenseBack(), const SizedBox(height: 16), syriaVehicleCardFront(), const SizedBox(height: 16), syriaVehicleCardBack(), const SizedBox(height: 16), syriaIdCardFront(), const SizedBox(height: 16), syriaDriverIDBack(), const SizedBox(height: 16), // egyptCriminalRecord(), // const SizedBox(height: 24), ], ), ), ], ), ); }), // --- شاشة الموافقة بتصميم جديد --- Positioned( top: 0, bottom: 0, right: 0, left: 0, child: GetBuilder(builder: (controller) { return controller.approved == false // --- إضافة خلفية معتمة --- ? Container( color: Colors.black.withOpacity(0.6), child: Center( child: Container( margin: const EdgeInsets.all(24), padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 15, spreadRadius: 5, ) ], ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "Approve Driver Documents".tr, style: NewAppStyle.headlineStyle, ), const SizedBox(height: 16), Text( "To become a ride-sharing driver on the Intaleq app, you need to upload your driver's license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Intaleq app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences." .tr, style: NewAppStyle.bodyStyle, textAlign: TextAlign.center, ), const SizedBox(height: 24), // --- زر الاستماع بتصميم جديد --- TextButton.icon( style: TextButton.styleFrom( foregroundColor: NewAppColor.accentColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 10), ), onPressed: () async { controller.startTimer(); if (box.read(BoxName.lang) == 'ar') { await Get.put(AudioController()) .playAudio1('assets/aggrement.wav'); } else { await textToSpeechController.speakText( 'To become a ride-sharing driver on the Intaleq app...' .tr); } }, icon: const Icon(Icons.volume_up_outlined, size: 30), label: Text('اضغط للاستماع'.tr, style: AppStyle.title.copyWith( color: NewAppColor.accentColor)), ), const SizedBox(height: 24), // --- أزرار الموافقة والرفض بتصميم جديد --- controller.isTimerComplete ? Row( children: [ Expanded( child: MyElevatedButton( title: 'إلغاء'.tr, kolor: NewAppColor.errorColor, onPressed: () { MyDialog().getDialog( 'سيتم إلغاء التسجيل'.tr, '', () async { Get.back(); Get.back(); }); }), ), const SizedBox(width: 16), Expanded( child: MyElevatedButton( title: 'أوافق'.tr, kolor: NewAppColor.successColor, onPressed: () { controller.setApproved(); }), ), ], ) : Column( children: [ CircularProgressIndicator( value: controller.progressValue, color: NewAppColor.primaryColor, ), const SizedBox(height: 8), Text( '${'الوقت المتبقي'.tr}: ${controller.remainingSeconds} ${"ثانية".tr}', style: NewAppStyle.bodyStyle, ), ], ), ], ), ), ), ) : const SizedBox(); }), ) ], isleading: true, ); } // --- واجهة عرض بيانات الوثيقة --- Widget _buildDocumentDataCard({ required String title, required VoidCallback onRefresh, required List children, }) { return Card( elevation: 4.0, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), side: BorderSide(color: NewAppColor.borderColor, width: 1), ), shadowColor: NewAppColor.primaryColor.withOpacity(0.1), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: NewAppStyle.headlineStyle), IconButton( onPressed: onRefresh, icon: const Icon(Icons.refresh, color: NewAppColor.accentColor), ), ], ), const Divider( height: 24, thickness: 1, color: NewAppColor.borderColor), ...children, ], ), ), ); } // --- واجهة التقاط صورة الوثيقة --- Widget _buildCaptureCard({ required String title, required String imagePath, required VoidCallback onTap, }) { return GestureDetector( onTap: onTap, child: Card( clipBehavior: Clip.antiAlias, elevation: 2.0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Image.asset( imagePath, height: Get.height * .20, fit: BoxFit.cover, // --- في حال لم يتم العثور على الصورة --- errorBuilder: (context, error, stackTrace) { return Container( height: Get.height * .20, color: NewAppColor.borderColor, child: const Icon( Icons.camera_alt_outlined, size: 50, color: NewAppColor.subTextColor, ), ); }, ), Container( padding: const EdgeInsets.all(16.0), color: NewAppColor.cardColor, child: Text( title, style: AppStyle.title, textAlign: TextAlign.center, ), ), ], ), ), ); } // --- ويدجت لعرض معلومة (سطر) --- Widget _infoRow(String label, String? value, {Color? valueColor}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('$label: ', style: NewAppStyle.bodyStyle), Expanded( child: Text( value ?? 'غير متوفر', style: NewAppStyle.valueStyle.copyWith(color: valueColor), ), ), ], ), ); } GetBuilder egyptDriverLicense() { return GetBuilder( builder: (ai) { if (ai.licenceFrontSy.isNotEmpty) { final data = ai.licenceFrontSy; DateTime? expiryDateTime; bool isExpired = false; if (data['expiry_date'] != null) { expiryDateTime = DateTime.tryParse(data['expiry_date']); isExpired = expiryDateTime != null && expiryDateTime.isBefore(DateTime.now()); } // بطاقة «رخصة القيادة – الوجه الأمامي» بتنسيق مضغوط وأيقونات return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // العنوان + زر التحديث Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('رخصة القيادة – الوجه الأمامي'.tr, style: NewAppStyle.headlineStyle), IconButton( icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), splashRadius: 18, onPressed: () async => await ai .pickAndSendImage('driving_license_sy_front'), ), ], ), const SizedBox(height: 8), // سطر الاسم الكامل Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['name_arabic'] != null) _iconInfo(Icons.person, data['name_arabic']!), if (data['birth_place'] != null) _iconInfo(Icons.location_city, data['birth_place']!), ], ), const SizedBox(height: 8), // بقية الحقول داخل Wrap لتقليل الطول Wrap( spacing: 12, runSpacing: 8, children: [ if (data['national_number'] != null) _iconInfo(Icons.badge, data['national_number']!), if (data['civil_registry'] != null) _iconInfo(Icons.location_on, data['civil_registry']!), if (data['blood_type'] != null) _iconInfo(Icons.water_drop, data['blood_type']!), if (data['birth_year'] != null) _iconInfo(Icons.calendar_today, data['birth_year']!), ], ), ], ), ), ); } return _buildCaptureCard( title: 'التقط صورة لرخصة القيادة'.tr, imagePath: 'assets/images/1.png', onTap: () async { await ai.pickAndSendImage('driving_license_sy_front'); }, ); }, ); } GetBuilder syriaDriverLicenseBack() { return GetBuilder( builder: (ai) { if (ai.licenceBackSy.isNotEmpty) { final data = ai.licenceBackSy; // صلاحية الرخصة final DateTime? expDate = DateTime.tryParse(data['expiry_date'] ?? ''); final bool expired = expDate != null && expDate.isBefore(DateTime.now()); final Color expColor = expired ? NewAppColor.errorColor // أحمر إن انتهت : NewAppColor.successColor; // أخضر إن صالحة return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // عنوان البطاقة + زر الإنعاش Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('رخصة القيادة – الوجه الخلفي'.tr, style: NewAppStyle.headlineStyle), IconButton( splashRadius: 18, icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), onPressed: () async => await ai .pickAndSendImage('driving_license_sy_back'), ), ], ), const SizedBox(height: 8), // صفّ أول (الفئة + الرقم) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['license_category'] != null) _iconInfo( Icons.star, data['license_category']!), // D1 / D2… if (data['license_number'] != null) _iconInfo( Icons.confirmation_number, data['license_number']!), ], ), const SizedBox(height: 8), // صفّ ثانٍ (التواريخ) مع تلوين تاريخ الصلاحية Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['issue_date'] != null) _iconInfo(Icons.event, data['issue_date']!), if (data['expiry_date'] != null) _iconInfo(Icons.event_busy, data['expiry_date']!, valueColor: expColor), ], ), ], ), ), ); } // بطاقة الالتقاط الافتراضية return _buildCaptureCard( title: 'التقط صورة الوجه الخلفي للرخصة'.tr, imagePath: 'assets/images/5.png', onTap: () async => await ai.pickAndSendImage('driving_license_sy_back'), ); }, ); } GetBuilder syriaDriverIDBack() { return GetBuilder( builder: (ai) { // استلمنا الحقول الأربعة فقط (governorate-address-gender-issue_date) if (ai.idBackSy.isNotEmpty) { final data = ai.idBackSy; return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // العنوان + زر التحديث Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('بطاقة الهوية – الوجه الخلفي'.tr, style: NewAppStyle.headlineStyle), IconButton( splashRadius: 18, icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), onPressed: () async => await ai.pickAndSendImage('id_back_sy'), ), ], ), const SizedBox(height: 8), // المحافظة + العنوان Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['governorate'] != null) _iconInfo(Icons.location_city, data['governorate']!), if (data['address'] != null) _iconInfo(Icons.home, data['address']!), ], ), const SizedBox(height: 8), // الجنس + تاريخ الإصدار Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['gender'] != null) _iconInfo(Icons.person, data['gender']!), if (data['issue_date'] != null) _iconInfo(Icons.event, data['issue_date']!), ], ), ], ), ), ); } // البطاقة الافتراضية لالتقاط الصورة return _buildCaptureCard( title: 'التقط صورة للوجه الخلفي للهوية'.tr, imagePath: 'assets/images/4.png', onTap: () async => await ai.pickAndSendImage('id_back_sy'), ); }, ); } /// عنصر (أيقونة + قيمة) مع لون نص مخصّص عند الحاجة Widget _iconInfo(IconData icon, String value, {Color? valueColor}) { return Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 18, color: NewAppColor.accentColor), const SizedBox(width: 4), Flexible( child: Text( value.tr, style: NewAppStyle.bodyStyle.copyWith(color: valueColor), overflow: TextOverflow.ellipsis, ), ), ], ); } GetBuilder syriaIdCardFront() { // أبقِ الاسم القديم إذا أردت return GetBuilder( builder: (ai) { if (ai.idFrontSy.isNotEmpty) { // غيّر المفتاح حسب متغيرك final data = ai.idFrontSy; return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // العنوان + زر التحديث Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('بطاقة الهوية – الوجه الأمامي'.tr, style: NewAppStyle.headlineStyle), IconButton( splashRadius: 18, icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), onPressed: () async => await ai.pickAndSendImage( 'id_front_sy', // أو id_front حسب تسمية end-point ), ), ], ), const SizedBox(height: 8), // سطر الاسم الكامل if (data['full_name'] != null) _iconInfo(Icons.person, data['full_name']!), const SizedBox(height: 8), // صفّ (الرقم الوطني + تاريخ الميلاد) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['national_number'] != null) _iconInfo(Icons.badge, data['national_number']!), if (data['dob'] != null) _iconInfo(Icons.cake, data['dob']!), ], ), const SizedBox(height: 8), // العنوان كامل بمفرده if (data['address'] != null) _iconInfo(Icons.home, data['address']!), ], ), ), ); } // كارد الالتقاط الافتراضية return _buildCaptureCard( title: 'التقط صورة للوجه الأمامي للهوية'.tr, imagePath: 'assets/images/2.png', onTap: () async => await ai.pickAndSendImage('id_front_sy'), ); }, ); } GetBuilder syriaVehicleCardFront() { // يمكنك إبقاء الاسم القديم إن شئت return GetBuilder( builder: (ai) { if (ai.vehicleFrontSy.isNotEmpty) { final data = ai.vehicleFrontSy; // تاريخ الفحص القادم للفحص الدوري (inspection_date) final DateTime? nextCheck = DateTime.tryParse(data['inspection_date'] ?? ''); final bool overdue = nextCheck != null && nextCheck.isBefore(DateTime.now()); final Color checkColor = overdue ? NewAppColor.errorColor : NewAppColor.successColor; return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // العنوان + تحديث Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('رخصة المركبة – الوجه الأمامي'.tr, style: NewAppStyle.headlineStyle), IconButton( splashRadius: 18, icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), onPressed: () async => await ai.pickAndSendImage( 'vehicle_license_sy_front', ), ), ], ), const SizedBox(height: 8), // الصف الأوّل (لوحة + مالك) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['car_plate'] != null) _iconInfo(Icons.directions_car, data['car_plate']!), if (data['owner'] != null) _iconInfo(Icons.person, data['owner']!), ], ), const SizedBox(height: 8), // الصف الثاني (VIN + اللون) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['vin'] != null) _iconInfo(Icons.confirmation_num, data['vin']!), if (data['color'] != null) _iconInfo(Icons.palette, data['color']!), ], ), const SizedBox(height: 8), // الصف الثالث (تاريخ المنح + الفحص القادم) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['issue_date'] != null) _iconInfo(Icons.event, data['issue_date']!), if (data['inspection_date'] != null) _iconInfo( Icons.event_available, data['inspection_date']!, valueColor: checkColor), ], ), ], ), ), ); } // لو لم تُرفع صورة بعد return _buildCaptureCard( title: 'التقط صورة لوجه رخصة المركبة'.tr, imagePath: 'assets/images/6.png', onTap: () async => await ai.pickAndSendImage('vehicle_license_sy_front'), ); }, ); } GetBuilder syriaVehicleCardBack() { // أبقِ الاسم القديم إن أردت return GetBuilder( builder: (ai) { if (ai.vehicleBackSy.isNotEmpty) { final data = ai.vehicleBackSy; return Card( elevation: 2, color: NewAppColor.cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: NewAppColor.borderColor, width: .8), ), child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // العنوان + زر تحديث Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('رخصة المركبة – الوجه الخلفي'.tr, style: NewAppStyle.headlineStyle), IconButton( splashRadius: 18, icon: const Icon(Icons.refresh, size: 20, color: NewAppColor.accentColor), onPressed: () async => await ai.pickAndSendImage( 'vehicle_license_sy_back', ), ), ], ), const SizedBox(height: 8), // صفّ (الشركة + الطراز) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['make'] != null) _iconInfo(Icons.factory, data['make']!), if (data['model'] != null) _iconInfo(Icons.directions_car_filled, data['model']!), ], ), const SizedBox(height: 8), // صفّ (سنة الصنع + اللون) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (data['year'] != null) _iconInfo(Icons.calendar_today, data['year']!), if (data['fuel'] != null) _iconInfo(Icons.local_gas_station, data['fuel']!), ], ), const SizedBox(height: 8), // رقم الهيكل بمفرده (قد يكون طويلًا) if (data['chassis'] != null) _iconInfo(Icons.confirmation_num, data['chassis']!), ], ), ), ); } // بطاقة الالتقاط الافتراضية return _buildCaptureCard( title: 'التقط صورة لخلفية رخصة المركبة'.tr, imagePath: 'assets/images/3.png', onTap: () async => await ai.pickAndSendImage('vehicle_license_sy_back'), ); }, ); } GetBuilder egyptCriminalRecord() { return GetBuilder( builder: (ai) { if (ai.responseCriminalRecordEgypt.isNotEmpty) { return _buildDocumentDataCard( title: 'صحيفة الحالة الجنائية'.tr, onRefresh: () async { await ai.allMethodForAI( (ai.prompts[5]['prompt'].toString()), AppLink.uploadEgypt, 'criminalRecord', ); }, children: [ _infoRow('نتيجة الفحص'.tr, ai.responseCriminalRecordEgypt['InspectionResult']), _infoRow( 'الاسم الكامل'.tr, ai.responseCriminalRecordEgypt['FullName'], valueColor: (ai.responseCriminalRecordEgypt['FullName']) == (ai.responseIdEgyptDriverLicense['name_arabic']) ? NewAppColor.successColor : NewAppColor.errorColor, ), _infoRow('الرقم القومي'.tr, ai.responseCriminalRecordEgypt['NationalID']), ], ); } return _buildCaptureCard( title: 'التقط صورة لصحيفة الحالة الجنائية'.tr, imagePath: 'assets/images/6.png', onTap: () async { await ai.allMethodForAI( (ai.prompts[5]['prompt'].toString()), AppLink.uploadEgypt, 'criminalRecord', ); }, ); }, ); } } // --- واجهة عرض الأقسام غير المصرية (بدون تغيير) --- // --- زر الفيديو بتصميم جديد --- class VideoButton extends StatelessWidget { final String videoUrl = "https://youtube.com/shorts/fC0RmYH5B_0?feature=share"; @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: InkWell( onTap: () async { if (await canLaunchUrl(Uri.parse(videoUrl))) { await launchUrl(Uri.parse(videoUrl)); } else { Get.snackbar('خطأ', 'لا يمكن فتح الفيديو'); } }, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.play_circle_outline, color: NewAppColor.accentColor, size: 28), const SizedBox(width: 12), Text( "شاهد فيديو الشرح".tr, style: AppStyle.title.copyWith(color: NewAppColor.accentColor), ), ], ), ), ), ); } } ================================================== FILE PATH: ./lib/views/auth/captin/cards/sms_signup.dart ================================================== import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/auth/captin/register_captin_controller.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import 'package:sefer_driver/views/widgets/my_scafold.dart'; import 'package:sefer_driver/views/widgets/my_textField.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../Rate/rate_app_page.dart'; class SmsSignupEgypt extends StatelessWidget { SmsSignupEgypt({super.key}); @override Widget build(BuildContext context) { Get.put(RegisterCaptainController()); return MyScafolld( title: 'Phone Check'.tr, body: [ GetBuilder( builder: (registerCaptainController) { return ListView( // mainAxisAlignment: MainAxisAlignment.center, children: [ // Logo at the top Padding( padding: const EdgeInsets.only(bottom: 20.0), child: Image.asset( 'assets/images/logo.gif', // Make sure you have a logo image in your assets folder height: 100, ), ), // Message to the driver Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Text( 'We need your phone number to contact you and to help you receive orders.' .tr, textAlign: TextAlign.center, style: AppStyle.title, ), ), // Enter phone number text Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Text( 'Enter your phone number'.tr, textAlign: TextAlign.center, style: AppStyle.title, ), ), // Phone number input field Padding( padding: const EdgeInsets.all(16.0), child: !registerCaptainController.isSent ? Form( key: registerCaptainController.formKey3, child: MyTextForm( controller: registerCaptainController.phoneController, label: 'Enter your phone number'.tr, hint: 'Enter your phone number'.tr, type: TextInputType.phone), ) : Container( decoration: AppStyle.boxDecoration1, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( registerCaptainController.phoneController.text, style: AppStyle.title, ), ), )), const SizedBox( height: 10, ), Padding( padding: const EdgeInsets.all(16.0), child: registerCaptainController.isSent ? Form( key: registerCaptainController.formKey3, child: MyTextForm( controller: registerCaptainController.verifyCode, label: '5 digit'.tr, hint: '5 digit'.tr, type: TextInputType.number), ) : const SizedBox()), // Submit button registerCaptainController.isLoading ? const MyCircularProgressIndicator() : Padding( padding: const EdgeInsets.all(16.0), child: MyElevatedButton( onPressed: () async { !registerCaptainController.isSent ? await registerCaptainController.sendOtpMessage() : await registerCaptainController.verifySMSCode(); }, title: 'Submit'.tr, ), ), Padding( padding: const EdgeInsets.all(16.0), child: MyElevatedButton( kolor: AppColor.yellowColor, title: "Rate Our App".tr, onPressed: () { Get.to(RatingScreen()); }), ), // IconButton( // onPressed: () async { // // final plainText = // // 'https://server.sefer.live/sefer.click/sefer'; // // debugPrint('Plain Text: $plainText'); // // Encrypt the data // // final encryptedData = encryptionHelper.encryptData(plainText); // // debugPrint('Encrypted: $encryptedData'); // // Decrypt the data // // final decryptedData = encryptionHelper.decryptData( // // '2unGmj8jSMFBfxqH8+GN'); // Use the encryptedData variable // // debugPrint('Decrypted: $decryptedData'); // // box.remove('DriversSecure'); // var drivers0 = await CRUD().get( // link: // 'https://server.sefer.live/sefer.click/sefer/auth/captin/getAllDriverSecure.php', // payload: {}); // var decodedDriver; // if (drivers0 != 'failure') { // decodedDriver = jsonDecode(drivers0); // // // // box.write('DriversSecure', decodedDriver['message']); // } // var drivers = decodedDriver['message']; // Log.print('drivers.length: ${drivers.length}'); // for (var i = 0; i < drivers.length; i++) { // Log.print('id: ${drivers[i]['id']}'); // var payload = { // "phone": encryptionHelper // .encryptData(drivers[i]['phone'].toString()), // "email": encryptionHelper // .encryptData(drivers[i]['email'].toString()), // "gender": encryptionHelper // .encryptData(drivers[i]['gender'] ?? 'unknown'), // "birthdate": encryptionHelper // .encryptData(drivers[i]['birthdate'].toString()), // "first_name": encryptionHelper // .encryptData(drivers[i]['first_name'].toString()), // "last_name": encryptionHelper // .encryptData(drivers[i]['last_name'].toString()), // "sosPhone": encryptionHelper // .encryptData(drivers[i]['sosPhone'].toString()), // // "name_english": encryptionHelper // // .encryptData(drivers[i]['name_english'].toString()), // // "last_name": encryptionHelper // // .encryptData(drivers[i]['last_name'].toString()), // // "sosPhone": encryptionHelper // // .encryptData(drivers[i]['sosPhone'].toString()), // // "address": encryptionHelper // // .encryptData(drivers[i]['address'].toString()), // // "card_id": encryptionHelper // // .encryptData(drivers[i]['card_id'].toString()), // // "occupation": encryptionHelper // // .encryptData(drivers[i]['occupation'].toString()), // // "religion": encryptionHelper // // .encryptData(drivers[i]['religion'].toString()), // // "site": encryptionHelper // // .encryptData(drivers[i]['site'].toString()), // // "education": encryptionHelper // // .encryptData(drivers[i]['education'].toString()), // // "accountBank": encryptionHelper // // .encryptData(drivers[i]['accountBank'].toString()), // // "employmentType": encryptionHelper // // .encryptData(drivers[i]['employmentType'].toString()), // // "maritalStatus": (drivers[i]['maritalStatus'].toString()), // // "fullNameMaritial": encryptionHelper.encryptData( // // drivers[i]['fullNameMaritial'].toString()), // 'id': drivers[i]['id'].toString() // }; // // print(drivers[i]['idn']); // // if (drivers[i]['id'].toString() != // // '01002165502a9sHC1tbrUrUw') { // var result = await CRUD().post( // link: // 'https://server.sefer.live/sefer.click/sefer/auth/captin/updateDriverSecure.php', // payload: payload); // if (result != 'failure') { // print(result); // } else { // print('failure'); // } // // Future.delayed(Duration(microseconds: 200)); // // } // } // MyDialog().getDialog('title', 'midTitle', () { // Get.back(); // }); // }, // icon: const Icon( // FontAwesome5.grin_tears, // size: 29, // color: AppColor.blueColor, // ), // ), ], ); }), ], isleading: false, ); } } ================================================== FILE PATH: ./lib/views/auth/captin/cards/gemini_egypt.dart ================================================== import 'dart:convert'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; class GeminiEgypt extends GetxController { Map responseIdCardDriverEgypt = {}; String? responseIdCardDriverEgypt1; Future geminiAiExtraction(String prompt, payload) async { var requestBody = jsonEncode({ 'contents': [ { 'parts': [ // { // 'inlineData': { // 'mimeType': 'image/jpeg', // 'data': imageData, // }, // }, { 'text': """ $payload $prompt ,and make dates format like year-month-day""" }, ], }, ], 'generationConfig': { 'temperature': 0.4, 'topK': 32, 'topP': 1, 'maxOutputTokens': 4096, 'stopSequences': [], }, 'safety_settings': [ {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE" }, ] }); final response = await http.post( Uri.parse( // 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=AIzaSyCyoLcSkDzK5_SMe00nhut56SSXWPR074w'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // Process the responseData as needed var result = responseData['candidates'][0]['content']['parts'][0]['text']; RegExp regex = RegExp(r"```json([^`]*)```"); String? jsonString = regex.firstMatch(responseData.toString())?.group(1)?.trim(); if (jsonString != null) { // Convert the JSON object to a String jsonString = jsonEncode(json.decode(jsonString)); responseIdCardDriverEgypt1 = jsonString; responseIdCardDriverEgypt = jsonDecode(responseIdCardDriverEgypt1!); update(); return responseIdCardDriverEgypt; } else {} // Rest of your code... } else {} } } ================================================== FILE PATH: ./lib/views/auth/captin/camera_widgets/camera_lisence_page.dart ================================================== import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/widgets/elevated_btn.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/style.dart'; import '../../../../controller/functions/camer_controller.dart'; import '../../../../controller/functions/ocr_controller.dart'; import '../../../widgets/my_scafold.dart'; class CameraLisencePage extends StatelessWidget { CameraLisencePage.CameraLicensePage({super.key}); final CameraClassController cameraClassController = Get.put(CameraClassController()); @override Widget build(BuildContext context) { return MyScafolld( title: 'Scan Driver License'.tr, body: [ Column(children: [ Text( 'Please put your licence in these border'.tr, style: AppStyle.title.copyWith(color: AppColor.greenColor), ), Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: GetBuilder( builder: (cameraClassController) => cameraClassController.isCameraInitialized ? Stack( children: [ Container( decoration: AppStyle.boxDecoration, child: CameraPreview( cameraClassController.cameraController, ), ), Positioned( top: Get.height * .1, right: 5, left: 5, child: Container( height: Get.width * 3 / 4, width: Get.width * .9, decoration: BoxDecoration( // color: AppColor.blueColor, border: Border.all( color: AppColor.yellowColor, width: 2), ), ), ), ], ) : Container( decoration: AppStyle.boxDecoration, height: Get.width * 3 / 4, width: Get.width, child: Center( child: Text( 'Camera not initialized yet', style: AppStyle.title, ), ), ), ), ), const SizedBox( height: 20, ), MyElevatedButton( title: 'Take Image'.tr, onPressed: () { ScanDocumentsByApi().scanDocumentsByApi(); }, ) ]), ], isleading: true, ); } } ================================================== FILE PATH: ./lib/views/notification/available_rides_page.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'dart:math'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/links.dart'; import '../../constant/style.dart'; import '../../controller/firebase/firbase_messge.dart'; import '../../controller/firebase/notification_service.dart'; import '../../controller/functions/crud.dart'; import '../../controller/home/captin/home_captain_controller.dart'; import '../../controller/notification/ride_available_controller.dart'; import '../../main.dart'; import '../home/Captin/driver_map_page.dart'; import '../widgets/my_scafold.dart'; import '../widgets/mycircular.dart'; import '../widgets/mydialoug.dart'; // --- Placeholder Classes and Variables (for demonstration) --- // These are dummy implementations to make the code runnable. // You should use your actual project files. // --- End of Placeholder Classes --- class AvailableRidesPage extends StatelessWidget { const AvailableRidesPage({super.key}); @override Widget build(BuildContext context) { // Use findOrPut to avoid re-creating the controller on rebuilds Get.lazyPut(() => RideAvailableController()); Get.lazyPut(() => HomeCaptainController()); return GetBuilder( builder: (rideAvailableController) { // rideAvailableController.sortRidesByDistance(); // Original logic return MyScafolld( title: 'Available for rides'.tr, body: [ rideAvailableController.isLoading ? const MyCircularProgressIndicator() : Builder( builder: (context) { // Filtering logic remains the same final filteredRides = rideAvailableController .rideAvailableMap['message'] .where((rideInfo) { var driverType = box.read(BoxName.carTypeOfDriver).toString(); switch (driverType) { case 'Comfort': return ['Speed', 'Comfort'] .contains(rideInfo['carType']); case 'Speed': case 'Scooter': case 'Awfar Car': return rideInfo['carType'] == driverType; case 'Lady': return ['Comfort', 'Speed', 'Lady'] .contains(rideInfo['carType']); default: return false; } }).toList(); if (filteredRides.isEmpty) { return Center( child: Text( "No rides available for your vehicle type.".tr, style: AppStyle.subtitle, ), ); } return ListView.builder( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 16), itemCount: filteredRides.length, itemBuilder: (context, index) { return RideAvailableCard( rideInfo: filteredRides[index], ); }, ); }, ) ], isleading: true); }); } } class RideAvailableCard extends StatelessWidget { final Map rideInfo; const RideAvailableCard({Key? key, required this.rideInfo}) : super(key: key); @override Widget build(BuildContext context) { // The main card with improved styling return Card( margin: const EdgeInsets.only(bottom: 16.0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), elevation: 5, shadowColor: Colors.black.withOpacity(0.1), child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () { // You can add an action here, e.g., show ride details on a map }, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(), const SizedBox(height: 16), _buildRouteInfo(), const Divider(height: 32), _buildRideDetails(), const SizedBox(height: 20), _buildAcceptButton(), ], ), ), ), ); } // Header section with Price and Car Type Widget _buildHeader() { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Fare'.tr, style: AppStyle.subtitle.copyWith(fontSize: 12)), const SizedBox(height: 4), Text('${rideInfo['price']} \$', style: AppStyle.title .copyWith(fontSize: 24, color: AppColor.primaryColor)), ], ), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: AppColor.greenColor.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Text( rideInfo['carType'], style: AppStyle.title .copyWith(color: AppColor.greenColor, fontSize: 12), ), ), ], ); } // Visual representation of the pickup and dropoff route Widget _buildRouteInfo() { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Dotted line and icons column Column( children: [ const Icon(CupertinoIcons.circle_fill, color: AppColor.greenColor, size: 20), ...List.generate( 4, (index) => Container( height: 4, width: 2, color: AppColor.writeColor, margin: const EdgeInsets.symmetric(vertical: 2), )), const Icon(CupertinoIcons.location_solid, color: Colors.red, size: 20), ], ), const SizedBox(width: 16), // Location text column Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildLocationText(rideInfo['startName'], 'Pickup'.tr), const SizedBox(height: 20), _buildLocationText(rideInfo['endName'], 'Dropoff'.tr), ], ), ) ], ); } // Helper for location text Widget _buildLocationText(String location, String label) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)), const SizedBox(height: 2), Text( location, style: AppStyle.title.copyWith(fontWeight: FontWeight.normal), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ); } // Ride details section with Distance and Passenger Rating Widget _buildRideDetails() { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildInfoChip( icon: CupertinoIcons.map_pin_ellipse, value: '${rideInfo['distance']} ${'KM'.tr}', label: 'Distance'.tr, color: AppColor.primaryColor, ), _buildInfoChip( icon: CupertinoIcons.star_fill, value: '${rideInfo['passengerRate']}', label: 'Rating'.tr, color: Colors.amber, ), ], ); } // A reusable chip for displaying info with an icon Widget _buildInfoChip( {required IconData icon, required String value, required String label, required Color color}) { return Column( children: [ Row( children: [ Icon(icon, color: color, size: 16), const SizedBox(width: 8), Text(value, style: AppStyle.title), ], ), const SizedBox(height: 4), Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)), ], ); } // The accept button with improved styling Widget _buildAcceptButton() { return SizedBox( width: double.infinity, child: ElevatedButton.icon( icon: const Icon(Icons.check_circle_outline, color: Colors.white), label: Text('Accept'.tr, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold)), onPressed: _acceptRide, style: ElevatedButton.styleFrom( backgroundColor: AppColor.greenColor, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), elevation: 2, ), ), ); } // --- Ride Acceptance Logic --- // This logic is copied exactly from your original code. void _acceptRide() async { var res = await CRUD().post( link: '${AppLink.endPoint}rides/updateStausFromSpeed.php', payload: { 'id': rideInfo['id'], 'rideTimeStart': DateTime.now().toString(), 'status': 'Apply', 'driver_id': box.read(BoxName.driverID), }); if (res != "failure") { List bodyToPassenger = [ box.read(BoxName.driverID).toString(), box.read(BoxName.nameDriver).toString(), box.read(BoxName.tokenDriver).toString(), ]; box.write(BoxName.statusDriverLocation, 'on'); await CRUD().postFromDialogue(link: AppLink.addDriverOrder, payload: { 'driver_id': box.read(BoxName.driverID), 'order_id': rideInfo['id'], 'status': 'Apply' }); // await CRUD().post(link: AppLink.updateRides, payload: { // 'id': rideInfo['id'], // 'DriverIsGoingToPassenger': DateTime.now().toString(), // 'status': 'Applied' // }); await CRUD().post( link: AppLink.updateWaitingRide, payload: {'id': rideInfo['id'], 'status': 'Applied'}); // if (AppLink.endPoint.toString() != AppLink.seferCairoServer) { NotificationService.sendNotification( target: rideInfo['passengerToken'].toString(), title: 'Accepted Ride'.tr, body: 'your ride is Accepted'.tr, isTopic: false, // Important: this is a token tone: 'start', driverList: bodyToPassenger, category: 'Accepted Ride', ); Get.back(); Get.to(() => PassengerLocationMapPage(), arguments: { 'passengerLocation': rideInfo['start_location'].toString(), 'passengerDestination': rideInfo['end_location'].toString(), 'Duration': rideInfo['duration'].toString(), 'totalCost': rideInfo['price'].toString(), 'Distance': rideInfo['distance'].toString(), 'name': rideInfo['first_name'].toString(), 'phone': rideInfo['phone'].toString(), 'email': rideInfo['email'].toString(), 'WalletChecked': rideInfo['payment_method'].toString(), 'tokenPassenger': rideInfo['passengerToken'].toString(), 'direction': 'https://www.google.com/maps/dir/${rideInfo['start_location']}/${rideInfo['end_location']}/', 'DurationToPassenger': rideInfo['duration'].toString(), 'rideId': rideInfo['id'].toString(), 'passengerId': rideInfo['passenger_id'].toString(), 'driverId': box.read(BoxName.driverID).toString(), 'durationOfRideValue': rideInfo['duration'].toString(), 'paymentAmount': rideInfo['price'].toString(), 'paymentMethod': 'cash'.toString() == 'true' ? 'visa' : 'cash', 'isHaveSteps': 'startEnd'.toString(), 'step0': ''.toString(), 'step1': ''.toString(), 'step2': ''.toString(), 'step3': ''.toString(), 'step4': ''.toString(), 'passengerWalletBurc': rideInfo['bruc'].toString(), 'timeOfOrder': DateTime.now().toString(), 'totalPassenger': rideInfo['price'].toString(), 'carType': rideInfo['carType'].toString(), 'kazan': Get.find().kazan.toString(), 'startNameLocation': rideInfo['startName'].toString(), 'endNameLocation': rideInfo['endName'].toString(), }); } else { MyDialog().getDialog( "This ride is already taken by another driver.".tr, '', () { CRUD().post( link: AppLink.deleteAvailableRide, payload: {'id': rideInfo['id']}); Get.back(); }); } } } ================================================== FILE PATH: ./lib/views/notification/notification_page.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import '../../controller/notification/passenger_notification_controller.dart'; import '../widgets/elevated_btn.dart'; import '../widgets/my_scafold.dart'; import '../widgets/mycircular.dart'; class NotificationPage extends StatelessWidget { const NotificationPage({super.key}); @override Widget build(BuildContext context) { Get.put(PassengerNotificationController()); return MyScafolld( isleading: true, title: 'Notifications', body: [ GetBuilder( builder: (notificationCaptainController) => notificationCaptainController.isloading ? const MyCircularProgressIndicator() : SafeArea( child: ListView.builder( itemCount: notificationCaptainController .notificationData['message'].length, itemBuilder: (BuildContext context, int index) { if (notificationCaptainController .notificationData['message'] == "No notification data found") { Get.defaultDialog(); } var res = notificationCaptainController .notificationData['message'][index]; return Card( elevation: 4, color: res['isShown'] == 'true' ? AppColor.secondaryColor.withOpacity(.5) : AppColor.secondaryColor.withOpacity(.9), child: ListTile( onTap: () { Get.defaultDialog( title: res['title'], titleStyle: AppStyle.title, content: SizedBox( width: Get.width * .8, // height: Get.height * .4, child: Text( res['body'], style: AppStyle.title, ), ), confirm: MyElevatedButton( title: 'Ok', onPressed: () { notificationCaptainController .updateNotification( res['id'].toString()); })); }, leading: res['isShown'] == 'true' ? const Icon( Icons.notifications_off_outlined) : const Icon(Icons.notifications_active), title: Text( res['title'], style: AppStyle.title, ), subtitle: Text( res['body'], style: AppStyle.subtitle, ), ), ); }, ), )) ], ); } } ================================================== FILE PATH: ./lib/views/notification/notification_captain.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/controller/notification/notification_captain_controller.dart'; import 'package:flutter/cupertino.dart'; class NotificationCaptain extends StatelessWidget { const NotificationCaptain({Key? key}) : super(key: key); @override Widget build(BuildContext context) { Get.put(NotificationCaptainController()); return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('Notifications'.tr), leading: CupertinoNavigationBarBackButton( onPressed: () => Get.back(), ), ), child: SafeArea( child: GetBuilder( builder: (notificationCaptainController) => notificationCaptainController.isLoading ? const Center(child: CupertinoActivityIndicator()) : ListView.builder( itemCount: notificationCaptainController .notificationData['message'].length, itemBuilder: (BuildContext context, int index) { if (notificationCaptainController .notificationData['message'] == "No notification data found") { _showCupertinoDialog(context, 'No Notifications', 'There are no notifications at this time.'); return const SizedBox.shrink(); } var res = notificationCaptainController .notificationData['message'][index]; return CupertinoListTile( leading: const Icon(CupertinoIcons.bell_fill), title: Text( res['title'], style: CupertinoTheme.of(context).textTheme.textStyle, ), subtitle: Text( res['body'], style: CupertinoTheme.of(context) .textTheme .tabLabelTextStyle, ), onTap: () { _showCupertinoDialog( context, res['title'], res['body'], onConfirm: () { notificationCaptainController .updateNotification(res['id'].toString()); Navigator.of(context).pop(); }, ); }, ); }, ), ), ), ); } void _showCupertinoDialog(BuildContext context, String title, String content, {VoidCallback? onConfirm}) { showCupertinoDialog( context: context, builder: (BuildContext context) => CupertinoAlertDialog( title: Text(title), content: Text(content), actions: [ CupertinoDialogAction( child: const Text('OK'), onPressed: onConfirm ?? () => Navigator.of(context).pop(), ), ], ), ); } } ================================================== FILE PATH: ./lib/views/lang/languages.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart'; import '../../controller/local/local_controller.dart'; class Language extends StatelessWidget { const Language({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('Choose Language'.tr), border: null, ), child: Material( // Wrap SafeArea with Material widget child: SafeArea( child: GetBuilder( builder: (controller) => Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(), const SizedBox(height: 20), Expanded( child: ListView( physics: const BouncingScrollPhysics(), children: [ _buildLanguageButton( 'العربية', 'ar', controller, context, '🇪🇬'), _buildLanguageButton('العربية (الخليج)', 'ar-gulf', controller, context, '🇸🇦'), _buildLanguageButton('العربية (المغرب)', 'ar-ma', controller, context, '🇲🇦'), _buildLanguageButton( 'English', 'en', controller, context, '🇺🇸'), _buildLanguageButton( 'Türkçe', 'tr', controller, context, '🇹🇷'), _buildLanguageButton( 'Français', 'fr', controller, context, '🇫🇷'), _buildLanguageButton( 'Italiano', 'it', controller, context, '🇮🇹'), _buildLanguageButton( 'Deutsch', 'de', controller, context, '🇩🇪'), _buildLanguageButton( 'Ελληνικά', 'el', controller, context, '🇬🇷'), _buildLanguageButton( 'Español', 'es', controller, context, '🇪🇸'), _buildLanguageButton( 'فارسی', 'fa', controller, context, '🇮🇷'), _buildLanguageButton( '中文', 'zh', controller, context, '🇨🇳'), _buildLanguageButton( 'Русский', 'ru', controller, context, '🇷🇺'), _buildLanguageButton( 'हिन्दी', 'hi', controller, context, '🇮🇳'), ], ), ), ], ), ), ), ), ), ), ); } Widget _buildHeader() { return Padding( padding: const EdgeInsets.only(top: 20, bottom: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Language Options'.tr, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: CupertinoColors.black, // Or your theme primary color ), textAlign: TextAlign.start, ), const SizedBox(height: 8), Text( 'Select your preferred language for the app interface.', style: TextStyle( fontSize: 16, color: CupertinoColors.secondaryLabel, ), textAlign: TextAlign.start, ), ], ), ); } Widget _buildLanguageButton(String title, String langCode, LocaleController controller, BuildContext context, String flagIcon) { return Container( decoration: BoxDecoration( color: CupertinoColors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: CupertinoColors.systemGrey5.withOpacity(0.5), spreadRadius: 1, blurRadius: 3, offset: const Offset(0, 2), ), ], ), child: ListTile( leading: Text(flagIcon, style: const TextStyle(fontSize: 28)), // Using flag icon as leading title: Text( title, style: const TextStyle( fontWeight: FontWeight.w500, ), ), trailing: const Icon(CupertinoIcons.chevron_forward, color: CupertinoColors.inactiveGray), onTap: () async { controller.changeLang(langCode); showCupertinoDialog( context: context, builder: (context) => CupertinoAlertDialog( title: Text('You should restart app to change language'.tr), actions: [ CupertinoDialogAction( child: Text('Ok'.tr), onPressed: () { Get.offAll(() => HomeCaptain()); }, ), ], ), ); }, ), ); } } ================================================== FILE PATH: ./lib/views/widgets/elevated_btn.dart ================================================== import 'dart:io'; import 'package:flutter/material.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:flutter/services.dart'; import 'package:vibration/vibration.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.dart'; class MyElevatedButton extends StatelessWidget { final String title; final VoidCallback onPressed; final Color kolor; final int vibrateDuration; const MyElevatedButton({ Key? key, required this.title, required this.onPressed, this.kolor = AppColor.primaryColor, this.vibrateDuration = 100, }) : super(key: key); @override Widget build(BuildContext context) { bool vibrate = box.read(BoxName.isvibrate) ?? true; return ElevatedButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.all(kolor), shadowColor: WidgetStateProperty.all(Colors.transparent), shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), onPressed: () async { // Handle haptic feedback for both iOS and Android if (vibrate == true) { if (Platform.isIOS) { HapticFeedback.selectionClick(); } else if (Platform.isAndroid) { await Vibration.vibrate(duration: vibrateDuration); } else {} } // Ensure the onPressed callback is called after haptic feedback onPressed(); }, child: Text( title, textAlign: TextAlign.center, style: AppStyle.title.copyWith(color: AppColor.secondaryColor), ), ); } } ================================================== FILE PATH: ./lib/views/widgets/my_textField.dart ================================================== import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:sefer_driver/constant/box_name.dart'; class MyTextForm extends StatelessWidget { const MyTextForm({ Key? key, required this.controller, required this.label, required this.hint, required this.type, }) : super(key: key); final TextEditingController controller; final String label, hint; final TextInputType type; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 10), child: SizedBox( width: Get.width * .8, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label.tr, style: TextStyle( color: CupertinoColors.label, fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), CupertinoTextField( controller: controller, keyboardType: type, placeholder: hint.tr, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: CupertinoColors.systemBackground, border: Border.all(color: CupertinoColors.systemGrey4), borderRadius: BorderRadius.circular(8), ), style: const TextStyle(color: CupertinoColors.label), placeholderStyle: const TextStyle(color: CupertinoColors.placeholderText), ), const SizedBox(height: 4), ValueListenableBuilder( valueListenable: controller, builder: (context, value, child) { String? errorText = _getErrorText(value.text); return errorText != null ? Text( errorText, style: const TextStyle( color: CupertinoColors.destructiveRed, fontSize: 12), ) : const SizedBox.shrink(); }, ), ], ), ), ); } String? _getErrorText(String value) { if (value.isEmpty) { return '${'Please enter'.tr} $label'.tr; } if (type == TextInputType.emailAddress) { if (!value.contains('@')) { return 'Please enter a valid email.'.tr; } } else if (type == TextInputType.phone) { final box = GetStorage(); if (box.read(BoxName.countryCode) == 'Egypt') { if (value.length != 11) { return 'Please enter a valid phone number.'.tr; } } else if (value.length != 10) { return 'Please enter a valid phone number.'.tr; } } return null; } } ================================================== FILE PATH: ./lib/views/widgets/my_circular_indicator_timer.dart ================================================== import 'package:sefer_driver/constant/style.dart'; import 'package:flutter/material.dart'; import 'dart:async'; class MyCircularProgressIndicatorWithTimer extends StatelessWidget { final Color backgroundColor; final bool isLoading; MyCircularProgressIndicatorWithTimer({ Key? key, this.backgroundColor = Colors.transparent, required this.isLoading, }) : super(key: key); final StreamController _streamController = StreamController(); void startTimer() { int _timeLeft = 60; Timer.periodic(const Duration(seconds: 1), (timer) { if (_timeLeft > 0 && isLoading) { _streamController.add(_timeLeft); _timeLeft--; } else { timer.cancel(); _streamController.close(); } }); } @override Widget build(BuildContext context) { if (isLoading) { startTimer(); } return Center( child: Container( width: 200, height: 200, decoration: BoxDecoration( color: backgroundColor, shape: BoxShape.circle, ), child: Stack( children: [ const Center(child: CircularProgressIndicator()), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Align( alignment: Alignment.center, child: Image.asset( 'assets/images/logo.gif', width: 140, height: 140, ), ), const SizedBox(height: 10), StreamBuilder( stream: _streamController.stream, initialData: 60, builder: (context, snapshot) { return Text('${snapshot.data}', style: AppStyle.title); }, ), ], ), ], ), ), ); } } ================================================== FILE PATH: ./lib/views/widgets/circle_container.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'mydialoug.dart'; class MyCircleContainer extends StatelessWidget { final Widget child; final Color backgroundColor; final Color borderColor; MyCircleContainer({ Key? key, required this.child, this.backgroundColor = AppColor.secondaryColor, this.borderColor = AppColor.accentColor, }) : super(key: key); final controller = Get.put(CircleController()); @override Widget build(BuildContext context) { return GetBuilder( builder: ((controller) => GestureDetector( onTap: () { controller.changeColor(); MyDialog().getDialog( 'Rejected Orders Count'.tr, 'This is the total number of rejected orders per day after accepting the orders' .tr, () { Get.back(); }); }, child: AnimatedContainer( onEnd: () { controller.onEnd(); }, duration: const Duration(milliseconds: 300), width: controller.size, height: controller.size, decoration: BoxDecoration( shape: BoxShape.circle, color: controller.backgroundColor, border: Border.all( color: borderColor, width: 1, ), ), child: Center(child: child), ), ))); } } class CircleController extends GetxController { Color backgroundColor = AppColor.secondaryColor; double size = 40; void changeColor() { backgroundColor = backgroundColor == AppColor.secondaryColor ? AppColor.accentColor : AppColor.secondaryColor; size = 60; update(); } void onEnd() { size = 40; update(); } } ================================================== FILE PATH: ./lib/views/widgets/error_snakbar.dart ================================================== import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../../constant/colors.dart'; class SnackbarConfig { static const duration = Duration(seconds: 3); static const animationDuration = Duration(milliseconds: 300); static const margin = EdgeInsets.symmetric(horizontal: 16, vertical: 10); static const borderRadius = 12.0; static const elevation = 6.0; static final BoxShadow shadow = BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2), ); } SnackbarController mySnackeBarError(String message) { // Trigger error haptic feedback HapticFeedback.mediumImpact(); return Get.snackbar( 'Error'.tr, message, backgroundColor: AppColor.redColor.withOpacity(0.95), colorText: AppColor.secondaryColor, icon: const Icon( Icons.error_outline_rounded, color: AppColor.secondaryColor, size: 28, ), shouldIconPulse: true, snackPosition: SnackPosition.TOP, margin: SnackbarConfig.margin, borderRadius: SnackbarConfig.borderRadius, duration: SnackbarConfig.duration, animationDuration: SnackbarConfig.animationDuration, forwardAnimationCurve: Curves.easeOutCirc, reverseAnimationCurve: Curves.easeInCirc, boxShadows: [SnackbarConfig.shadow], padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), titleText: Text( 'Error'.tr, style: const TextStyle( fontWeight: FontWeight.w700, color: Colors.white, fontSize: 16, letterSpacing: 0.2, ), ), messageText: Text( message, style: TextStyle( color: Colors.white.withOpacity(0.95), fontSize: 14, height: 1.3, ), ), onTap: (_) { HapticFeedback.lightImpact(); Get.closeCurrentSnackbar(); }, isDismissible: true, dismissDirection: DismissDirection.horizontal, overlayBlur: 0.8, overlayColor: Colors.black12, ); } SnackbarController mySnackbarSuccess(String message) { // Trigger success haptic feedback HapticFeedback.lightImpact(); return Get.snackbar( 'Success'.tr, message, backgroundColor: AppColor.greenColor.withOpacity(0.95), colorText: AppColor.secondaryColor, icon: const Icon( Icons.check_circle_outline_rounded, color: AppColor.secondaryColor, size: 28, ), shouldIconPulse: true, snackPosition: SnackPosition.TOP, margin: SnackbarConfig.margin, borderRadius: SnackbarConfig.borderRadius, duration: SnackbarConfig.duration, animationDuration: SnackbarConfig.animationDuration, forwardAnimationCurve: Curves.easeOutCirc, reverseAnimationCurve: Curves.easeInCirc, boxShadows: [SnackbarConfig.shadow], padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), titleText: Text( 'Success'.tr, style: const TextStyle( fontWeight: FontWeight.w700, color: Colors.white, fontSize: 16, letterSpacing: 0.2, ), ), messageText: Text( message, style: TextStyle( color: Colors.white.withOpacity(0.95), fontSize: 14, height: 1.3, ), ), onTap: (_) { HapticFeedback.lightImpact(); Get.closeCurrentSnackbar(); }, isDismissible: true, dismissDirection: DismissDirection.horizontal, overlayBlur: 0.8, overlayColor: Colors.black12, ); } ================================================== FILE PATH: ./lib/views/widgets/mydialoug.dart ================================================== import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/functions/tts.dart'; class DialogConfig { static const Duration animationDuration = Duration(milliseconds: 200); static const double blurStrength = 8.0; static const double cornerRadius = 14.0; static final BoxDecoration decoration = BoxDecoration( borderRadius: BorderRadius.circular(cornerRadius), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(38), // 0.15 opacity blurRadius: 16, offset: const Offset(0, 8), ), ], ); } class MyDialog extends GetxController { void getDialog(String title, String? midTitle, VoidCallback onPressed) { final textToSpeechController = Get.put(TextToSpeechController()); HapticFeedback.mediumImpact(); Get.dialog( TweenAnimationBuilder( duration: DialogConfig.animationDuration, tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.scale( scale: 0.95 + (0.05 * value), child: Opacity(opacity: value, child: child), ); }, child: BackdropFilter( filter: ImageFilter.blur( sigmaX: DialogConfig.blurStrength, sigmaY: DialogConfig.blurStrength, ), child: Theme( data: ThemeData.light().copyWith( dialogBackgroundColor: CupertinoColors.systemBackground, ), child: CupertinoAlertDialog( title: Column( children: [ Text( title.tr, style: AppStyle.title.copyWith( fontSize: 20, fontWeight: FontWeight.w700, letterSpacing: -0.5, color: AppColor.primaryColor, ), ), const SizedBox(height: 8), ], ), content: Column( children: [ CupertinoButton( padding: const EdgeInsets.all(8), onPressed: () async { HapticFeedback.selectionClick(); await textToSpeechController.speakText(title); await textToSpeechController.speakText(midTitle!); }, child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColor.primaryColor.withAlpha(26), // 0.1 opacity borderRadius: BorderRadius.circular(8), ), child: Icon( CupertinoIcons.speaker_2_fill, color: AppColor.primaryColor, size: 24, ), ), ), const SizedBox(height: 8), Text( midTitle!, style: AppStyle.title.copyWith( fontSize: 16, height: 1.3, color: Colors.black87, ), textAlign: TextAlign.center, ), ], ), actions: [ CupertinoDialogAction( onPressed: () { HapticFeedback.lightImpact(); Get.back(); }, child: Text( 'Cancel'.tr, style: TextStyle( color: AppColor.redColor, fontWeight: FontWeight.w600, fontSize: 17, ), ), ), CupertinoDialogAction( onPressed: () { HapticFeedback.mediumImpact(); onPressed(); }, child: Text( 'OK'.tr, style: TextStyle( color: AppColor.greenColor, fontWeight: FontWeight.w600, fontSize: 17, ), ), ), ], ), ), ), ), barrierDismissible: true, barrierColor: Colors.black.withAlpha(102), // 0.4 opacity ); } } class MyDialogContent extends GetxController { void getDialog(String title, Widget? content, VoidCallback onPressed) { final textToSpeechController = Get.put(TextToSpeechController()); HapticFeedback.mediumImpact(); Get.dialog( TweenAnimationBuilder( duration: DialogConfig.animationDuration, tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Transform.scale( scale: 0.95 + (0.05 * value), child: Opacity(opacity: value, child: child), ); }, child: BackdropFilter( filter: ImageFilter.blur( sigmaX: DialogConfig.blurStrength, sigmaY: DialogConfig.blurStrength, ), child: Theme( data: ThemeData.light().copyWith( dialogBackgroundColor: CupertinoColors.systemBackground, ), child: CupertinoAlertDialog( title: Column( children: [ Text( title, style: AppStyle.title.copyWith( fontSize: 20, fontWeight: FontWeight.w700, letterSpacing: -0.5, color: AppColor.primaryColor, ), ), const SizedBox(height: 8), ], ), content: Column( children: [ CupertinoButton( padding: const EdgeInsets.all(8), onPressed: () async { HapticFeedback.selectionClick(); await textToSpeechController.speakText(title); }, child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColor.primaryColor.withAlpha(26), // 0.1 opacity borderRadius: BorderRadius.circular(8), ), child: Icon( CupertinoIcons.headphones, color: AppColor.primaryColor, size: 24, ), ), ), const SizedBox(height: 12), content!, ], ), actions: [ CupertinoDialogAction( onPressed: () { HapticFeedback.lightImpact(); Get.back(); }, child: Text( 'Cancel', style: TextStyle( color: AppColor.redColor, fontWeight: FontWeight.w600, fontSize: 17, ), ), ), CupertinoDialogAction( onPressed: () { HapticFeedback.mediumImpact(); onPressed(); }, child: Text( 'OK'.tr, style: TextStyle( color: AppColor.greenColor, fontWeight: FontWeight.w600, fontSize: 17, ), ), ), ], ), ), ), ), barrierDismissible: true, barrierColor: Colors.black.withAlpha(102), // 0.4 opacity ); } } ================================================== FILE PATH: ./lib/views/widgets/icon_widget_menu.dart ================================================== import 'package:flutter/material.dart'; import 'package:sefer_driver/constant/style.dart'; import '../../constant/colors.dart'; class IconWidgetMenu extends StatelessWidget { const IconWidgetMenu({ Key? key, required this.onpressed, required this.icon, required this.title, }) : super(key: key); final VoidCallback onpressed; final IconData icon; final String title; @override Widget build(BuildContext context) { return InkWell( onTap: onpressed, child: Padding( padding: const EdgeInsets.only(top: 25), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 50, decoration: const BoxDecoration( color: AppColor.secondaryColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: AppColor.secondaryColor, offset: Offset(-2, -2), blurRadius: 0, spreadRadius: 0, blurStyle: BlurStyle.outer, ), BoxShadow( color: AppColor.accentColor, offset: Offset(3, 3), blurRadius: 0, spreadRadius: 0, blurStyle: BlurStyle.outer, ), ], ), child: Center( child: Icon( icon, size: 30, color: AppColor.primaryColor, ), ), ), Text( title, style: AppStyle.subtitle, ) ], ), ), ); } } ================================================== FILE PATH: ./lib/views/widgets/my_scafold.dart ================================================== import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; class MyScafolld extends StatelessWidget { const MyScafolld({ super.key, required this.title, required this.body, this.action = const Icon( Icons.clear, color: AppColor.secondaryColor, ), required this.isleading, }); final String title; final List body; final Widget action; final bool isleading; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.secondaryColor, appBar: AppBar( backgroundColor: AppColor.secondaryColor, elevation: 0, leading: isleading ? IconButton( onPressed: () { Get.back(); }, icon: const Icon( Icons.arrow_back_ios_new, color: AppColor.primaryColor, ), ) : const SizedBox(), actions: [action], title: Text( title, style: AppStyle.title.copyWith(fontSize: 30), ), ), body: SafeArea(child: Stack(children: body))); } } ================================================== FILE PATH: ./lib/views/widgets/mycircular.dart ================================================== import 'package:flutter/material.dart'; class MyCircularProgressIndicator extends StatefulWidget { final Color backgroundColor; final double size; final Color progressColor; final double strokeWidth; const MyCircularProgressIndicator({ super.key, this.backgroundColor = Colors.transparent, this.size = 110, this.progressColor = Colors.blue, this.strokeWidth = 3.0, }); @override State createState() => _MyCircularProgressIndicatorState(); } class _MyCircularProgressIndicatorState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; late Animation _rotationAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, )..repeat(reverse: true); _scaleAnimation = Tween( begin: 0.95, end: 1.05, ).animate(CurvedAnimation( parent: _controller, curve: Curves.easeInOut, )); _rotationAnimation = Tween( begin: 0, end: 2, ).animate(CurvedAnimation( parent: _controller, curve: Curves.linear, )); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Center( child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.scale( scale: _scaleAnimation.value, child: Container( width: widget.size, height: widget.size, decoration: BoxDecoration( color: widget.backgroundColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: widget.progressColor.withAlpha(30), blurRadius: 12, spreadRadius: 2, ), ], ), child: Stack( alignment: Alignment.center, children: [ // Outer rotating progress indicator Transform.rotate( angle: _rotationAnimation.value * 3.14, child: CircularProgressIndicator( strokeWidth: widget.strokeWidth, valueColor: AlwaysStoppedAnimation( widget.progressColor, ), ), ), // Inner static progress indicator CircularProgressIndicator( strokeWidth: widget.strokeWidth * 0.7, valueColor: AlwaysStoppedAnimation( widget.progressColor.withAlpha(150), ), ), // Logo container with scale animation ScaleTransition( scale: Tween( begin: 0.9, end: 1.0, ).animate(CurvedAnimation( parent: _controller, curve: Curves.easeInOut, )), child: Container( width: widget.size * 0.7, height: widget.size * 0.7, decoration: BoxDecoration( shape: BoxShape.circle, color: widget.backgroundColor, ), child: Image.asset( 'assets/images/logo.gif', fit: BoxFit.contain, ), ), ), ], ), ), ); }, ), ); } }