From 630d0c4afb621a273c42eb53414cbfdde5969795 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 21 Nov 2024 16:48:54 +0200 Subject: [PATCH] 11/21/1 --- android/app/build.gradle | 4 +- ios/Runner/Info.plist | 4 +- .../home/map_passenger_controller.dart | 233 +++++++-- lib/controller/home/vip_waitting_page.dart | 441 ++++++++++++------ lib/controller/local/translations.dart | 6 +- lib/views/home/map_page_passenger.dart | 2 + .../map_widget.dart/left_main_menu_icons.dart | 24 +- lib/views/home/map_widget.dart/vip_begin.dart | 319 +++++++++++++ 8 files changed, 839 insertions(+), 194 deletions(-) create mode 100644 lib/views/home/map_widget.dart/vip_begin.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index c61fdff..2d432ec 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -148,8 +148,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 98 - versionName = '1.5.98' + versionCode = 99 + versionName = '1.5.99' multiDexEnabled =true // manifestPlaceholders can be specified here if needed diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 44be063..3513e88 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -41,11 +41,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 70 + 71 CFBundleSignature ???? CFBundleVersion - 4.3.70 + 4.3.71 NSHumanReadableCopyright FirebaseAppDelegateProxyEnabled diff --git a/lib/controller/home/map_passenger_controller.dart b/lib/controller/home/map_passenger_controller.dart index 1a79e5b..f786103 100644 --- a/lib/controller/home/map_passenger_controller.dart +++ b/lib/controller/home/map_passenger_controller.dart @@ -146,6 +146,7 @@ class MapPassengerController extends GetxController { double naturePrice = 0; bool heightMenuBool = false; String statusRide = 'wait'; + String statusRideVip = 'wait'; bool statusRideFromStart = false; bool isPickerShown = false; bool isPointsPageForRider = false; @@ -747,9 +748,91 @@ class MapPassengerController extends GetxController { // update(); } + int progressTimerRideBeginVip = 0; + int elapsedTimeInSeconds = 0; // Timer starts from 0 + String stringElapsedTimeRideBegin = '0:00'; + String stringElapsedTimeRideBeginVip = '0:00'; + bool rideInProgress = true; // To control when to stop the timer + + void rideIsBeginPassengerTimerVIP() async { + rideInProgress = true; // Start the ride timer + bool sendSOS = false; + while (rideInProgress) { + await Future.delayed(const Duration(seconds: 1)); + + // Increment elapsed time + elapsedTimeInSeconds++; + + // Update the time display + int minutes = (elapsedTimeInSeconds / 60).floor(); + int seconds = elapsedTimeInSeconds % 60; + stringElapsedTimeRideBeginVip = + '$minutes:${seconds.toString().padLeft(2, '0')}'; + + // Check for speed and SOS conditions + if (speed > 100 && !sendSOS) { + Get.defaultDialog( + barrierDismissible: false, + title: "Warning: Speeding detected!".tr, + titleStyle: AppStyle.title, + content: Text( + "We noticed the speed 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." + .tr, + style: AppStyle.title, + ), + confirm: MyElevatedButton( + title: "Share Trip Details".tr, + onPressed: () { + Get.back(); + // Implement sharing trip details logic here + String message = "**Emergency SOS from Passenger:**\n"; + + // Get trip details from GetX or relevant provider + String origin = passengerLocation.toString(); + String destination = myDestination.toString(); + String driverName = firstName; + String driverCarPlate = licensePlate; + + // Add trip details to the message + message += "* ${'Origin'.tr}: $origin\n"; + message += "* ${'Destination'.tr}: $destination\n"; + message += "* ${'Driver Name'.tr}: $driverName\n"; + message += "* ${'Driver Car Plate'.tr}: $driverCarPlate\n\n"; + message += "* ${'Driver Phone'.tr}: $driverPhone\n\n"; + + // Add current location + message += + "${'Current Location'.tr}:https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude} \n"; + + // Append a call to action + message += "Please help! Contact me as soon as possible.".tr; + + // Launch WhatsApp communication + launchCommunication( + 'whatsapp', box.read(BoxName.sosPhonePassenger), message); + sendSOS = true; + }, + kolor: AppColor.redColor, + ), + cancel: MyElevatedButton( + title: "Cancel".tr, + onPressed: () { + Get.back(); + }, + kolor: AppColor.greenColor, + ), + ); + } + + // Update the UI + update(); + } + } + void tripFinishedFromDriver() async { isRideFinished = true; rideTimerBegin = false; + statusRideVip = 'Finished'; box.write(BoxName.arrivalTime, ''); remainingTimeTimerRideBegin = 0; box.write(BoxName.passengerWalletTotal, '0'); @@ -795,6 +878,22 @@ class MapPassengerController extends GetxController { } } + begiVIPTripFromPassenger() async { + timeToPassengerFromDriverAfterApplied = 0; + remainingTime = 0; + isBottomSheetShown = false; + remainingTimeToPassengerFromDriverAfterApplied = 0; + remainingTimeDriverWaitPassenger5Minute = 0; + rideTimerBegin = true; + statusRideVip = 'Begin'; + isDriverInPassengerWay = false; + isDriverArrivePassenger = false; + update(); + // isCancelRidePageShown = true; + rideIsBeginPassengerTimerVIP(); + runWhenRideIsBegin(); + } + Map rideStatusFromStartApp = {}; getRideStatusFromStartApp() async { try { @@ -1053,6 +1152,7 @@ class MapPassengerController extends GetxController { late String driverRate = ''; late String firstName = ''; late String carColor = ''; + late String colorHex = ''; late String carYear = ''; late String model = ''; late String make = ''; @@ -1099,6 +1199,8 @@ class MapPassengerController extends GetxController { .toString(); carColor = dataCarsLocationByPassenger['data'][carsOrder]['color'].toString(); + colorHex = dataCarsLocationByPassenger['data'][carsOrder]['color_hex'] ?? + '#A52A2A'; driverRate = dataCarsLocationByPassenger['data'][carsOrder] ['ratingDriver'] .toString(); @@ -1971,7 +2073,10 @@ class MapPassengerController extends GetxController { return jsonDecode(response)['data']; } - late String driverCarModel, driverCarMake, driverLicensePlate, driverName; + late String driverCarModel, + driverCarMake, + driverLicensePlate, + driverName = ''; getUpdatedRideForDriverApply(String rideId) async { // if (isDriversTokensSend) { final res = await CRUD().get( @@ -4597,12 +4702,13 @@ class MapPassengerController extends GetxController { } Future mishwariOption() async { - // isBottomSheetShown = false; + isLoading = true; update(); // add dialoug for select driver and car await selectDriverAndCarForMishwariTrip(); Future.delayed(Duration.zero); - + isLoading = false; + update(); Get.to(() => CupertinoDriverListWidget()); // changeCashConfirmPageShown(); @@ -4651,13 +4757,62 @@ class MapPassengerController extends GetxController { if (response != 'failure') { // Trip saved successfully // Get.snackbar('Success'.tr, 'Trip booked successfully'.tr); - var id = response['message'].toString(); + var id = response['message']['id'].toString(); + await CRUD().post( + link: '${AppLink.seferCairoServer}/ride/rides/add.php', + payload: { + "start_location": + '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', + "end_location": + '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', + "date": DateTime.now().toString(), + "time": DateTime.now().toString(), + "endtime": + DateTime.now().add(const Duration(hours: 2)).toString(), + "price": '50', + "passenger_id": box.read(BoxName.passengerID).toString(), + "driver_id": driver['driver_id'].toString(), + "status": "waiting", + 'carType': 'vip', + "price_for_driver": '50', + "price_for_passenger": '50', + "distance": '20', + "paymentMethod": 'cash', + }).then((value) { + if (value is String) { + final parsedValue = jsonDecode(value); + rideId = parsedValue['message']; + } else if (value is Map) { + rideId = value['message']; + } else { + Log.print('Unexpected response type: ${value.runtimeType}'); + } + }); if (AppLink.endPoint != AppLink.seferCairoServer) { await CRUD().post( link: "${AppLink.endPoint}/ride/mishwari/add.php", payload: tripData); + CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: { + "start_location": + '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', + "end_location": + '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', + "date": DateTime.now().toString(), + "time": DateTime.now().toString(), + "endtime": DateTime.now().add(const Duration(hours: 2)).toString(), + "price": '50', + "passenger_id": box.read(BoxName.passengerID).toString(), + "driver_id": driver['driver_id'].toString(), + "status": "waiting", + 'carType': 'vip', + "price_for_driver": '50', + "price_for_passenger": '50', + "distance": '20', + "paymentMethod": 'cash', + }); } - driverIdVip = driver['driver_id']; + driverIdVip = driver['driver_id'].toString(); + driverId = driver['driver_id'].toString(); DateTime timeSelected = DateTime.parse(tripDateTime.toIso8601String()); Get.find().scheduleNotificationsForTimeSelected( @@ -4667,35 +4822,41 @@ class MapPassengerController extends GetxController { timeSelected); // Optionally, set up local notification or send a push notification - // await FirebaseMessagesController().sendNotificationToDriverMAP( - // 'OrderVIP', - // rideId.toString(), - // driver['token'].toString(), - // [ - // id, - // driver['id'], - // passengerLocation.latitude.toString(), - // passengerLocation.longitude.toString(), - // box.read(BoxName.name).toString(), - // box.read(BoxName.passengerID).toString(), - // box.read(BoxName.phone).toString(), - // box.read(BoxName.email).toString(), - // box.read(BoxName.passengerPhotoUrl).toString(), - // box.read(BoxName.tokenFCM).toString(), - // driver['token'].toString(), - // ], - // 'order.wav'); + await FirebaseMessagesController().sendNotificationToDriverMAP( + 'OrderVIP', + rideId.toString(), + driver['token'].toString(), + [ + id, + driver['id'], + passengerLocation.latitude.toString(), + passengerLocation.longitude.toString(), + box.read(BoxName.name).toString(), + box.read(BoxName.passengerID).toString(), + box.read(BoxName.phone).toString(), + box.read(BoxName.email).toString(), + box.read(BoxName.passengerPhotoUrl).toString(), + box.read(BoxName.tokenFCM).toString(), + driver['token'].toString(), + ], + 'order.wav'); if (response['message'] == "Trip updated successfully") { mySnackbarSuccess("Trip updated successfully".tr); - // FirebaseMessagesController().sendNotificationToDriverMAP( - // 'Order VIP Canceld'.tr, - // 'Passenger cancel order'.tr, - // token, - // [], - // 'cancel.wav', - // ); + Log.print( + 'previous_driver_token: ${response['previous_driver_token']}'); + + FirebaseMessagesController().sendNotificationToDriverMAP( + 'Order VIP Canceld'.tr, + 'Passenger cancel order'.tr, + response['previous_driver_token'].toString(), + [], + 'cancel.wav', + ); } - Get.to(() => const VipWaittingPage()); + // data = []; + isBottomSheetShown = false; + update(); + Get.to(() => VipWaittingPage()); } else { throw Exception('Failed to save trip'); } @@ -4723,6 +4884,16 @@ class MapPassengerController extends GetxController { } } + sendToDriverAgain(String token) { + FirebaseMessagesController().sendNotificationToDriverMAP( + 'Order VIP Canceld'.tr, + 'Passenger cancel order'.tr, + token, + [], + 'cancel.wav', + ); + } + initilizeGetStorage() async { if (box.read(BoxName.addWork) == null) { box.write(BoxName.addWork, 'addWork'); diff --git a/lib/controller/home/vip_waitting_page.dart b/lib/controller/home/vip_waitting_page.dart index 3f5a096..9cc1287 100644 --- a/lib/controller/home/vip_waitting_page.dart +++ b/lib/controller/home/vip_waitting_page.dart @@ -1,190 +1,323 @@ +import 'dart:async'; import 'dart:convert'; +import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/constant/colors.dart'; +import 'package:SEFER/constant/links.dart'; import 'package:SEFER/constant/style.dart'; import 'package:SEFER/controller/home/map_passenger_controller.dart'; +import 'package:SEFER/main.dart'; import 'package:SEFER/views/widgets/elevated_btn.dart'; +import 'package:SEFER/views/widgets/my_scafold.dart'; import 'package:SEFER/views/widgets/mycircular.dart'; +import 'package:SEFER/views/widgets/mysnakbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; -import '../../constant/links.dart'; import '../functions/crud.dart'; +class VipOrderController extends GetxController { + RxBool isLoading = false.obs; + final arguments = Get.arguments; + RxList tripData = [].obs; + RxBool isButtonVisible = false.obs; + RxInt countdown = 60.obs; + Timer? _countdownTimer; + + @override + void onInit() { + super.onInit(); + fetchOrder(); + startCountdown(); + } + + @override + void onClose() { + _countdownTimer?.cancel(); + super.onClose(); + } + + Future fetchOrder() async { + try { + isLoading.value = true; + var mapPassengerController = Get.find(); + + var res = await CRUD().get( + link: AppLink.getMishwari, + payload: { + // 'driverId': mapPassengerController.driverIdVip.toString(), + 'driverId': box.read(BoxName.passengerID).toString(), + }, + ); + + if (res != 'failure') { + var decodedResponse = jsonDecode(res); + if (decodedResponse['message'] is List) { + tripData.value = decodedResponse['message']; + } else { + tripData.clear(); // Ensure empty list if no data + mySnackeBarError('No trip data found'); + } + } else { + tripData.clear(); + mySnackeBarError('Failed to fetch trip data'); + } + } catch (e) { + tripData.clear(); + mySnackeBarError('An error occurred: $e'); + } finally { + isLoading.value = false; + } + } + + void startCountdown() { + _countdownTimer?.cancel(); // Cancel any existing timer + countdown.value = 60; + + _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + if (countdown.value > 0) { + countdown.value--; + } else { + timer.cancel(); + isButtonVisible.value = true; + } + }); + } + + void sendToDriverAgain() { + // Reset states + isButtonVisible.value = false; + fetchOrder(); // Refresh order + startCountdown(); // Restart countdown + } +} + class VipWaittingPage extends StatelessWidget { - const VipWaittingPage({super.key}); + VipWaittingPage({super.key}); + final VipOrderController vipOrderController = Get.put(VipOrderController()); @override Widget build(BuildContext context) { - Get.put(VipOrderController()); - return Scaffold( - appBar: AppBar( - title: Text("Waiting VIP".tr), - ), - body: GetBuilder(builder: (vipOrderController) { - var data = vipOrderController.tripData[0]; - - // Function to get the localized status string - String getLocalizedStatus(String status) { - switch (status) { - case 'pending': - return 'pending'.tr; - case 'accepted': - return 'accepted'.tr; - case 'rejected': - return 'rejected'.tr; - default: - return 'unknown'.tr; // Fallback for unexpected statuses + return MyScafolld( + title: "Waiting VIP".tr, + body: [ + Obx(() { + // Loading state + if (vipOrderController.isLoading.value) { + return const Center(child: MyCircularProgressIndicator()); } - } -// Function to get the appropriate status color - Color getStatusColor(String status) { - switch (status) { - case 'pending': - return Colors.yellow; - case 'accepted': - return Colors.green; - case 'rejected': - return Colors.red; - default: - return Colors.grey; // Default color for unknown statuses + // No data state + if (vipOrderController.tripData.isEmpty) { + return Center( + child: Text( + 'No trip data available'.tr, + style: AppStyle.title, + ), + ); } - } - return vipOrderController.isLoading - ? const MyCircularProgressIndicator() - : Card( - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + // Data available + var data = vipOrderController.tripData[0]; + + // Function to get the localized status string + String getLocalizedStatus(String status) { + switch (status) { + case 'pending': + return 'pending'.tr; + case 'accepted': + return 'accepted'.tr; + case 'begin': + return 'begin'.tr; + case 'rejected': + return 'rejected'.tr; + case 'cancelled': + return 'cancelled'.tr; + default: + return 'unknown'.tr; + } + } + + // Function to get the appropriate status color + Color getStatusColor(String status) { + switch (status) { + case 'pending': + return Colors.yellow; + case 'accepted': + return Colors.green; + case 'begin': + return Colors.green; + case 'rejected': + return Colors.red; + case 'cancelled': + return Colors.red; + default: + return Colors.grey; + } + } + + return Card( + elevation: 4, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + margin: const EdgeInsets.all(16), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${'Driver Name:'.tr} ${data['name']}", + style: AppStyle.title, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "${'Driver Name:'.tr} ${data['name']}", - style: AppStyle.title, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${'Car Plate:'.tr} ${data['car_plate']}", - style: AppStyle.title, - ), - Text( - "${'Car Make:'.tr} ${data['make']}", - style: AppStyle.title, - ), - Text( - "${'Car Model:'.tr} ${data['model']}", - style: AppStyle.title, - ), - Text( - "${"Car Color:".tr} ${data['color']}", - style: AppStyle.title, - ), - ], + Text( + "${'Car Plate:'.tr} ${data['car_plate']}", + style: AppStyle.title, + ), + Text( + "${'Car Make:'.tr} ${data['make']}", + style: AppStyle.title, + ), + Text( + "${'Car Model:'.tr} ${data['model']}", + style: AppStyle.title, + ), + Text( + "${"Car Color:".tr} ${data['color']}", + style: AppStyle.title, ), - SizedBox( - width: 100, - height: 100, - child: Icon(Fontisto.car, - size: 80, - color: Color(int.parse(data['color_hex'] - .replaceFirst('#', '0xff'))))), ], ), - // Text( - // "${'Driver Phone:'.tr} ${data['phone']}", - // style: AppStyle.title, - // ), - const SizedBox(height: 12), - const Divider(), - const SizedBox(height: 12), - - Container( - color: getStatusColor( - data['status']), // Correctly assigns a Color - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - "${'Trip Status:'.tr} ${getLocalizedStatus(data['status'])}", // Uses the String function - style: const TextStyle( - fontSize: 16, + SizedBox( + width: 100, + height: 100, + child: Icon( + Fontisto.car, + size: 80, + color: Color( + int.parse( + data['color_hex'].replaceFirst('#', '0xff'), ), ), ), ), - Text( - "${'Scheduled Time:'.tr} ${DateFormat('yyyy-MM-dd hh:mm a').format(DateTime.parse(data['timeSelected']))}", - style: const TextStyle(fontSize: 16), - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - MyElevatedButton( - title: "Cancel Trip".tr, - kolor: AppColor.redColor, - onPressed: () { - Get.find().cancelVip( - data['token'].toString(), - data['id'].toString(), - ); - }, - ), - // MyElevatedButton( - // title: "Accept Trip".tr, - // kolor: AppColor.greenColor, - // onPressed: () { - // // Add your cancel trip logic here - // }, - // ), - ], - ), ], ), - ), - ); - }), + const SizedBox(height: 12), + const Divider(), + const SizedBox(height: 12), + Container( + color: getStatusColor(data['status']), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "${'Trip Status:'.tr} ${getLocalizedStatus(data['status'])}", + style: const TextStyle(fontSize: 16), + ), + ), + ), + Text( + "${'Scheduled Time:'.tr} ${DateFormat('yyyy-MM-dd hh:mm a').format(DateTime.parse(data['timeSelected']))}", + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + data['status'].toString() != 'begin' + ? MyElevatedButton( + title: "Cancel Trip".tr, + kolor: AppColor.redColor, + onPressed: () { + Get.find().cancelVip( + data['token'].toString(), + data['id'].toString(), + ); + }, + ) + : const SizedBox(), + Obx(() { + // If countdown is still running, show countdown + if (!vipOrderController.isButtonVisible.value) { + return Column( + children: [ + CircularProgressIndicator( + value: 1 - + (vipOrderController.countdown.value / 60), + strokeWidth: 6.0, + color: AppColor.greenColor, + backgroundColor: AppColor.accentColor, + ), + const SizedBox(height: 10), + Text( + "${vipOrderController.countdown.value}s ${'remaining'.tr}", + style: const TextStyle(fontSize: 16), + ), + ], + ); + } + + // Once countdown is complete, show "Send to Driver Again" button + return MyElevatedButton( + title: "Send to Driver Again".tr, + kolor: AppColor.greenColor, + onPressed: () { + Get.find() + .sendToDriverAgain(data['token']); + vipOrderController.fetchOrder(); + }, + ); + }), + ], + ), + const SizedBox( + height: 30, + ), + data['status'].toString() == 'begin' + ? MyElevatedButton( + title: "Click here to begin your trip\n\nGood luck, " + .tr + + box.read(BoxName.name).toString(), + kolor: AppColor.greenColor, + onPressed: () { + final mapPassengerController = + Get.find(); + mapPassengerController.make = data['make']; + mapPassengerController.licensePlate = + data['car_plate']; + mapPassengerController.model = data['model']; + mapPassengerController.driverId = data['driverId']; + mapPassengerController.carColor = data['color']; + mapPassengerController.driverRate = data['rating']; + mapPassengerController.colorHex = data['color_hex']; + mapPassengerController.driverPhone = data['phone']; + mapPassengerController.driverToken = data['token']; + mapPassengerController.driverName = + data['name'].toString().split(' ')[0]; + + Get.back(); + + mapPassengerController.begiVIPTripFromPassenger(); + }, + ) + : const SizedBox() + ], + ), + ), + ); + }), + ], + isleading: true, ); } } - -class VipOrderController extends GetxController { - bool isLoading = false; - final arguments = Get.arguments; - late String body; - List tripData = []; - - fetchOrder() async { - isLoading = true; - update(); - var res = await CRUD().get(link: AppLink.getMishwari, payload: { - 'driverId': Get.find().driverIdVip.toString(), - }); - isLoading = false; - update(); - if (res != 'failure') { - tripData = jsonDecode(res)['message']; - update(); - } - } - - @override - void onInit() async { - fetchOrder(); - super.onInit(); - } -} diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 3d96535..ba8998e 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -4,8 +4,10 @@ class MyTranslation extends Translations { @override Map> get keys => { "ar": { + "Send to Driver Again": "إرسال إلى السائق مرة أخرى", "Driver Name:": "اسم السائق:", - "Car Plate:": "رقم اللوحة:", + 'No trip data available': "لا توجد بيانات رحلة متاحة", + "Car Plate:": "رقم اللوحة:", "remaining": "متبقي", "Order Cancelled": "تم إلغاء الطلب", 'You canceled VIP trip': "ألغيت الرحلة", "Passenger cancelled order": "الراكب قام بإلغاء الطلب", @@ -797,7 +799,7 @@ iOS [https://getapp.cc/app/6458734951] 'Selected Date and Time': "التاريخ والوقت المحددان", "Lets check Car license ": "دَعْنَا نَتَحَقَّق مِن رُخْصَة السَّيَّارَة ", - 'Driver List': 'قائمة السائقين', + // 'Driver List': 'قائمة السائقين', 'Car': 'السيارة', 'Plate': 'لوحة السيارة', 'N/A': 'غير متوفر', diff --git a/lib/views/home/map_page_passenger.dart b/lib/views/home/map_page_passenger.dart index b30a0f2..3c251df 100644 --- a/lib/views/home/map_page_passenger.dart +++ b/lib/views/home/map_page_passenger.dart @@ -23,6 +23,7 @@ import 'map_widget.dart/payment_method.page.dart'; import 'map_widget.dart/points_page_for_rider.dart'; import 'map_widget.dart/ride_from_start_app.dart'; import 'map_widget.dart/searching_captain_window.dart'; +import 'map_widget.dart/vip_begin.dart'; class MapPagePassenger extends StatelessWidget { const MapPagePassenger({super.key}); @@ -63,6 +64,7 @@ class MapPagePassenger extends StatelessWidget { // const TimerToPassengerFromDriver(), const PassengerRideLocationWidget(), const RideBeginPassenger(), + const VipRideBeginPassenger(), const RideFromStartApp(), cancelRidePage(), const MenuIconMapPageWidget(), diff --git a/lib/views/home/map_widget.dart/left_main_menu_icons.dart b/lib/views/home/map_widget.dart/left_main_menu_icons.dart index bb77e2d..ff26bb6 100644 --- a/lib/views/home/map_widget.dart/left_main_menu_icons.dart +++ b/lib/views/home/map_widget.dart/left_main_menu_icons.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../../../constant/colors.dart'; -import '../../../controller/functions/crud.dart'; import '../../../controller/functions/tts.dart'; import '../../../controller/home/map_passenger_controller.dart'; import '../../../controller/home/vip_waitting_page.dart'; @@ -91,14 +91,32 @@ GetBuilder leftMainMenuIcons() { borderRadius: BorderRadius.circular(15)), child: IconButton( onPressed: () async { - Get.to(() => const VipWaittingPage()); + Get.to(() => VipWaittingPage()); }, icon: const Icon( - Icons.voice_chat, + Octicons.watch, // Replace this with your desired VIP icon size: 29, ), ), ), + // AnimatedContainer( + // duration: const Duration(microseconds: 200), + // width: controller.widthMapTypeAndTraffic, + // decoration: BoxDecoration( + // color: AppColor.secondaryColor, + // border: Border.all(), + // borderRadius: BorderRadius.circular(15)), + // child: IconButton( + // onPressed: () async { + // print(Get.put(MapPassengerController()).data); + // }, + // icon: const Icon( + // Octicons + // .telescope, // Replace this with your desired VIP icon + // size: 29, + // ), + // ), + // ), ], ); })), diff --git a/lib/views/home/map_widget.dart/vip_begin.dart b/lib/views/home/map_widget.dart/vip_begin.dart new file mode 100644 index 0000000..b124710 --- /dev/null +++ b/lib/views/home/map_widget.dart/vip_begin.dart @@ -0,0 +1,319 @@ +import 'package:SEFER/constant/links.dart'; +import 'package:SEFER/views/home/profile/complaint_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_font_icons/flutter_font_icons.dart'; +import 'package:get/get.dart'; +import 'package:SEFER/constant/box_name.dart'; +import 'package:SEFER/controller/profile/profile_controller.dart'; +import 'package:SEFER/main.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/functions/audio_record1.dart'; +import '../../../controller/functions/launch.dart'; +import '../../../controller/functions/toast.dart'; +import '../../../controller/home/map_passenger_controller.dart'; + +class VipRideBeginPassenger extends StatelessWidget { + const VipRideBeginPassenger({ + super.key, + }); + + @override + Widget build(BuildContext context) { + ProfileController profileController = Get.put(ProfileController()); + AudioRecorderController audioController = + Get.put(AudioRecorderController()); + // Get.put(MapPassengerController()); + return GetBuilder(builder: (controller) { + if (controller.statusRideVip == 'Begin' || + !controller.statusRideFromStart) { + return Positioned( + left: 10, + right: 10, + bottom: 10, + child: Container( + decoration: AppStyle.boxDecoration, + height: controller.statusRideVip == 'Begin' ? Get.height * .33 : 0, + // width: 100, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CircleAvatar( + radius: 30, + backgroundImage: NetworkImage( + '${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg', + ), + onBackgroundImageError: (_, __) { + // Handle error here + }, + backgroundColor: Colors.grey, + child: const Icon( + Icons.person, // Default icon or placeholder + size: 30, + color: Colors.white, + ), // Placeholder background color + ), + Column( + children: [ + Container( + decoration: AppStyle.boxDecoration, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + child: Text( + controller.driverName, + style: AppStyle.title, + ), + ), + ), + const SizedBox( + height: 10, + ), + Container( + decoration: AppStyle.boxDecoration, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Text( + controller.make, + style: AppStyle.title, + ), + const SizedBox( + width: 10, + ), + Text( + controller.model, + style: AppStyle.title, + ), + ], + ), + ), + ), + ], + ), + Column( + children: [ + Container( + decoration: AppStyle.boxDecoration, + child: Padding( + padding: const EdgeInsets.all(3), + child: Text( + 'vip', + style: AppStyle.title, + ), + ), + ), + Text( + '${controller.driverRate} 📈', + style: AppStyle.title, + ), + ], + ), + ], + ), + // SizedBox( + // height: 5, + // ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + width: Get.width * .15, + decoration: AppStyle.boxDecoration, + child: IconButton( + onPressed: () => Get.to( + () => ComplaintPage(), + transition: Transition.downToUp, + ), + icon: const Icon( + Icons.note_add, + color: AppColor.redColor, + ), + tooltip: ' Add Note', // Optional tooltip for clarity + ), + ), + Container( + width: Get.width * .15, + decoration: AppStyle.boxDecoration, + child: audioController.isRecording == false + ? IconButton( + onPressed: () async { + await audioController.startRecording(); + Toast.show(context, 'Start Record'.tr, + AppColor.greenColor); + }, + icon: const Icon( + Icons.play_circle_fill_outlined, + color: AppColor.greenColor, + ), + tooltip: + ' Add Note', // Optional tooltip for clarity + ) + : IconButton( + onPressed: () async { + await audioController.stopRecording(); + Toast.show(context, 'Record saved'.tr, + AppColor.greenColor); + }, + icon: const Icon( + Icons.stop_circle, + color: AppColor.greenColor, + ), + tooltip: + ' Add Note', // Optional tooltip for clarity + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + decoration: AppStyle.boxDecoration, + width: Get.width * .15, + child: IconButton( + onPressed: () async { + if (box.read(BoxName.sosPhonePassenger) == null) { + { + await profileController.updatField( + 'sosPhone', TextInputType.phone); + box.write(BoxName.sosPhonePassenger, + profileController.prfoileData['sosPhone']); + } + } else { + makePhoneCall('122'); + // box.read(BoxName.sosPhonePassenger)); + } + }, + icon: const Icon( + Icons.sos_rounded, + color: AppColor.redColor, + ), + ), + ), + Container( + decoration: AppStyle.boxDecoration, + width: Get.width * .15, + child: IconButton( + onPressed: () async { + if (box.read(BoxName.sosPhonePassenger) == null || + box.read(BoxName.sosPhonePassenger) == 'sos') { + { + await profileController.updatField( + 'sosPhone', TextInputType.phone); + box.write(BoxName.sosPhonePassenger, + profileController.prfoileData['sosPhone']); + } + } else { + String phoneNumber = box + .read(BoxName.sosPhonePassenger) + .toString(); + // phoneNumber = phoneNumber.replaceAll('0', ''); + var phone = box.read(BoxName.countryCode) == + 'Egypt' + ? '+2${box.read(BoxName.sosPhonePassenger)}' + : '+962${box.read(BoxName.sosPhonePassenger)}'; + controller.sendWhatsapp(phone); + } + }, + icon: const Icon( + FontAwesome.whatsapp, + color: AppColor.greenColor, + ), + ), + ), + Container( + decoration: AppStyle.boxDecoration, + width: Get.width * .15, + child: IconButton( + onPressed: () async { + await controller.getTokenForParent(); + }, + icon: const Icon( + AntDesign.Safety, + color: AppColor.blueColor, + ), + ), + ), + ], + ), + Stack( + children: [ + // StreamCounter(), + LinearProgressIndicator( + backgroundColor: AppColor.accentColor, + color: + // controller.remainingTimeTimerRideBegin < 60 + // ? AppColor.redColor + // : + AppColor.greenColor, + minHeight: 25, + borderRadius: BorderRadius.circular(15), + value: + 24 //controller.progressTimerRideBegin.toDouble(), + ), + Center( + child: Text( + controller.stringElapsedTimeRideBeginVip, + style: AppStyle.title, + ), + ) + ], + ) + ], + ), + ), + ), + ); + } else { + return const SizedBox(); + } + }); + } +} + +class StreamCounter extends StatelessWidget { + const StreamCounter({Key? key}) : super(key: key); + + @override + // Build the UI based on the timer value + Widget build(BuildContext context) { + Get.put(MapPassengerController()); + return GetBuilder(builder: (controller) { + return StreamBuilder( + initialData: 0, + stream: controller.timerController.stream, + builder: (context, snapshot) { + // Calculate the remaining time based on the current tick + final remainingTime = controller.durationToRide - snapshot.data!; + + // Format the remaining time as a string + final formattedRemainingTime = + '${(remainingTime / 60).floor()}:${(remainingTime % 60).toString().padLeft(2, '0')}'; + + // Return the UI widgets based on the remaining time + return Column( + children: [ + Text(formattedRemainingTime), + // ElevatedButton( + // onPressed: () { + // // Handle button press here + // }, + // ), + ], + ); + }, + ); + }); + } +}