25-6-23/1
This commit is contained in:
@@ -28,7 +28,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Step-by-step instructions on how to request a ride through the Sefer app.'
|
||||
'Step-by-step instructions on how to request a ride through the Tripz app.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
@@ -43,7 +43,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Sefer 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.'
|
||||
'Tripz 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,
|
||||
),
|
||||
@@ -58,7 +58,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
|
||||
'Tripz offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
@@ -73,7 +73,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.'
|
||||
'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Tripz cancellation policy for details.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
@@ -98,7 +98,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
});
|
||||
},
|
||||
child: Text(
|
||||
'Visit our website or contact Sefer support for information on driver registration and requirements.'
|
||||
'Visit our website or contact Tripz support for information on driver registration and requirements.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
@@ -115,22 +115,22 @@ class FrequentlyQuestionsPage extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
|
||||
'Tripz 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 Sefer offer?
|
||||
// Question 8: What safety measures does Tripz offer?
|
||||
ExpansionTile(
|
||||
title: Text(
|
||||
'What safety measures does Sefer offer?'.tr,
|
||||
'What safety measures does Tripz offer?'.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
'Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
|
||||
'Tripz prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
|
||||
@@ -120,7 +120,7 @@ class SettingsCaptain extends StatelessWidget {
|
||||
CupertinoListTile(
|
||||
leading: const Icon(CupertinoIcons.hand_raised_fill),
|
||||
title:
|
||||
Text("How to use SEFER".tr, style: AppStyle.headTitle2),
|
||||
Text("How to use Tripz".tr, style: AppStyle.headTitle2),
|
||||
trailing: const CupertinoListTileChevron(),
|
||||
onTap: () => Get.to(() => const UsingAppPage()),
|
||||
),
|
||||
|
||||
@@ -10,7 +10,7 @@ class UsingAppPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MyScafolld(
|
||||
title: "How to use SEFER".tr,
|
||||
title: "How to use Tripz".tr,
|
||||
body: [
|
||||
SizedBox(
|
||||
child: Padding(
|
||||
@@ -22,12 +22,13 @@ class UsingAppPage extends StatelessWidget {
|
||||
MyDialogContent().getDialog(
|
||||
"What are the order details we provide to you?".tr,
|
||||
Image.network(
|
||||
'https://api.sefer.live/sefer/imageForUsingApp/order_page.jpg',
|
||||
'https://api.tripz-egypt.com/tripz/imageForUsingApp/order_page.jpg',
|
||||
height: 300,
|
||||
width: 300,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
() {});
|
||||
), () {
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration1,
|
||||
@@ -47,16 +48,17 @@ class UsingAppPage extends StatelessWidget {
|
||||
onTap: () {
|
||||
MyDialog().getDialog(
|
||||
"What are the order details we provide to you?".tr,
|
||||
'''Sefer Wallet Features:
|
||||
'''Tripz Wallet Features:
|
||||
|
||||
Transfer money multiple times.
|
||||
Transfer to anyone.
|
||||
Make purchases.
|
||||
Charge your account.
|
||||
Charge a friend's Sefer account.
|
||||
Charge a friend's Tripz account.
|
||||
Store your money with us and receive it in your bank as a monthly salary.'''
|
||||
.tr,
|
||||
() {});
|
||||
.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration1,
|
||||
@@ -75,8 +77,8 @@ Store your money with us and receive it in your bank as a monthly salary.'''
|
||||
InkWell(
|
||||
onTap: () {
|
||||
MyDialog().getDialog(
|
||||
"What are the order details we provide to you?".tr,
|
||||
'''Types of Trips in Sefer:
|
||||
"What is Types of Trips in Tripz?".tr,
|
||||
'''Types of Trips in Tripz:
|
||||
|
||||
Comfort: For cars newer than 2017 with air conditioning.
|
||||
Lady: For girl drivers.
|
||||
@@ -84,15 +86,16 @@ 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,
|
||||
() {});
|
||||
.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"What is Types of Trips in Sefer?".tr,
|
||||
"What is Types of Trips in Tripz?".tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -21,16 +21,20 @@ class PassengerLocationMapPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// if (!mapDriverController.initialized) {
|
||||
// // Call a method to initialize the controller
|
||||
|
||||
// mapDriverController.initialized;
|
||||
// } else {
|
||||
// Get.put(MapDriverController()).argumentLoading();
|
||||
|
||||
// Get.put(MapDriverController())
|
||||
// .startTimerToShowPassengerInfoWindowFromDriver();
|
||||
// }
|
||||
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
|
||||
// نستخدم addPostFrameCallback لضمان أن هذا الكود يعمل بعد اكتمال بناء الإطار الأول
|
||||
// هذا يعطي GetX وقته لتجهيز كل شيء
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// نستدعي دالة التهيئة الجديدة ونمرر لها البيانات
|
||||
mapDriverController.argumentLoading();
|
||||
});
|
||||
} else {
|
||||
// في حال عدم وجود arguments، يجب التعامل مع هذا الخطأ
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Get.snackbar("Error", "No order data found.");
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
mapDriverController.argumentLoading();
|
||||
mapDriverController.startTimerToShowPassengerInfoWindowFromDriver();
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ 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 '../../../../print.dart';
|
||||
import '../../../widgets/circle_container.dart';
|
||||
import '../driver_map_page.dart';
|
||||
import 'widget/connect.dart';
|
||||
@@ -482,6 +483,8 @@ class HomeCaptain extends StatelessWidget {
|
||||
),
|
||||
GetBuilder<HomeCaptainController>(
|
||||
builder: (homeCaptainController) {
|
||||
Log.print(
|
||||
'rideStatus from home 486 : ${box.read(BoxName.rideStatus)}');
|
||||
return box.read(BoxName.rideStatus) == 'Applied' ||
|
||||
box.read(BoxName.rideStatus) == 'Begin'
|
||||
? Positioned(
|
||||
@@ -520,7 +523,7 @@ class HomeCaptain extends StatelessWidget {
|
||||
};
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.rice_bowl,
|
||||
Icons.directions_rounded,
|
||||
size: 29,
|
||||
color: AppColor.blueColor,
|
||||
),
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
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/print.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/error_snakbar.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/functions/crud.dart';
|
||||
import '../../../../../controller/home/captin/order_request_controller.dart';
|
||||
import '../../../../Rate/ride_calculate_driver.dart';
|
||||
|
||||
GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
@@ -17,6 +25,46 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
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();
|
||||
},
|
||||
);
|
||||
// Log.print(
|
||||
// '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,
|
||||
@@ -89,7 +137,10 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
}),
|
||||
)
|
||||
: const SizedBox(),
|
||||
// : const SizedBox(),
|
||||
// const SizedBox(
|
||||
// height: 5,
|
||||
// ),
|
||||
|
||||
// AnimatedContainer(
|
||||
// duration: const Duration(microseconds: 200),
|
||||
// width: controller.widthMapTypeAndTraffic,
|
||||
@@ -100,53 +151,7 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
// child: Builder(builder: (context) {
|
||||
// return IconButton(
|
||||
// onPressed: () async {
|
||||
// final List<dynamic> testList = const [
|
||||
// "32.1117875,36.0669891",
|
||||
// "32.1364001,36.0707479",
|
||||
// "24.84",
|
||||
// "7.56",
|
||||
// "436",
|
||||
// "4.38",
|
||||
// "109270481246447459618",
|
||||
// "113172279072358305645",
|
||||
// "hamza",
|
||||
// "e4QWqe7K607luM7qUMOPCL:APA91bFjX4XBM4I5COJl9fyxCTKJ1ZQpT3vzY7iEbOTuT4uo0-OSCAt5zgVhlhw4aC33s-VhyucDnP1tQGFd9svaazQ8A_SKgolPk3owzug8dCsiXoPeJ0k",
|
||||
// "+201010101010",
|
||||
// "6",
|
||||
// "43",
|
||||
// "true",
|
||||
// "c2tXiuBJQCSg4CU4IfqYOL:APA91bFA0f8R3QMnPQnPEEdNyjY-jcoKt4nLBHxcLLsmDSuJn5yd4jSvwq7qDIZpkkPkjfjdwdKsGL0-G0aHpPyjfiBvbCwFmlRMCUKftNMNT7MJx2Bp16Y",
|
||||
// "6",
|
||||
// "1188",
|
||||
// "false",
|
||||
// "109270481246447459618",
|
||||
// "436",
|
||||
// "startEnd",
|
||||
// "32.12404505187645,36.06566168367863",
|
||||
// "",
|
||||
// "",
|
||||
// "",
|
||||
// "",
|
||||
// "5.42",
|
||||
// "0",
|
||||
// "hamzaayedflutter@gmail.com",
|
||||
// "4368+PPP، السخنة، الأردن",
|
||||
// "43PC+C4G، السخنة، الأردن",
|
||||
// "Speed",
|
||||
// "8",
|
||||
// "5.00"
|
||||
// ];
|
||||
// await FlutterOverlayWindow.shareData(testList);
|
||||
// await FlutterOverlayWindow.showOverlay(
|
||||
// enableDrag: true,
|
||||
// flag: OverlayFlag.focusPointer,
|
||||
// // visibility: NotificationVisibility.visibilityPublic,
|
||||
// positionGravity: PositionGravity.auto,
|
||||
// height: 1300,
|
||||
// width: WindowSize.matchParent,
|
||||
// startPosition: const OverlayPosition(0, -90),
|
||||
// );
|
||||
// debugPrint('Overlay opened: ');
|
||||
// Log.print('phoneDriver: ${box.read(BoxName.phoneDriver)}');
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// FontAwesome5.grin_tears,
|
||||
@@ -165,3 +170,142 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _log(String message) => print(message);
|
||||
|
||||
Future<void> 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},
|
||||
);
|
||||
|
||||
// Assuming the server returns order data if found, or 'failure'/'none' if not
|
||||
if (response != 'failure') {
|
||||
Log.print('response: ${response}');
|
||||
_log("MAIN_APP_LOG: Pending order DETECTED from server!");
|
||||
|
||||
final Map<String, dynamic> orderInfoFromServer = response['message'];
|
||||
final Map<String, dynamic> rideArguments =
|
||||
_transformServerDataToAppArguments(orderInfoFromServer);
|
||||
// 2. Build the new arguments map, matching your Flutter structure
|
||||
|
||||
_log("MAIN_APP_LOG: Constructed rideArguments map successfully.");
|
||||
|
||||
/////////////
|
||||
final customerToken = (response)['message']['token_passenger'];
|
||||
final orderId = (response)['message']['ride_id'].toString();
|
||||
Log.print('orderId: ${orderId}');
|
||||
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);
|
||||
} else {
|
||||
_log("MAIN_APP_LOG: No pending orders found on server.");
|
||||
box.write(BoxName.rideArgumentsFromBackground, 'failure');
|
||||
}
|
||||
} catch (e) {
|
||||
_log("Error while polling server: $e");
|
||||
} finally {
|
||||
_isProcessingOrder = false; // Release lock
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> _transformServerDataToAppArguments(
|
||||
Map<String, dynamic> serverData) {
|
||||
_log("Transforming server data to match app's argument structure.");
|
||||
|
||||
// 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;
|
||||
final FirebaseMessagesController _firebaseMessagesController =
|
||||
Get.put(FirebaseMessagesController());
|
||||
_log("Attempting to send acceptance notification to passenger...");
|
||||
List<String> 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) {
|
||||
_firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
|
||||
'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
|
||||
_log("Acceptance notification task was fired.");
|
||||
} else {
|
||||
_log("Could not send notification: Customer token is missing or empty.");
|
||||
}
|
||||
} catch (e) {
|
||||
_log("Error while firing notification task: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ import 'package:get/get.dart';
|
||||
// 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 SEFER app and be part of our SEFER family."
|
||||
// "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,
|
||||
// ),
|
||||
@@ -186,7 +186,7 @@ class MaintainCenterPage extends StatelessWidget {
|
||||
),
|
||||
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 SEFER app and be part of our SEFER family."
|
||||
"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
|
||||
|
||||
@@ -13,8 +13,11 @@ 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/elevated_btn.dart';
|
||||
|
||||
import '../../../../constant/box_name.dart';
|
||||
import '../../../../constant/style.dart';
|
||||
import '../../../../controller/functions/launch.dart';
|
||||
import '../../../../main.dart';
|
||||
import '../../../../print.dart';
|
||||
|
||||
class PassengerInfoWindow extends StatelessWidget {
|
||||
const PassengerInfoWindow({super.key});
|
||||
@@ -179,7 +182,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
if (await controller
|
||||
.calculateDistanceBetweenDriverAndPassengerLocation() <
|
||||
140) {
|
||||
FirebaseMessagesController()
|
||||
Get.find<FirebaseMessagesController>()
|
||||
.sendNotificationToDriverMAP(
|
||||
'Hi ,I Arrive your site',
|
||||
'I Arrive at your site'.tr,
|
||||
@@ -245,7 +248,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
MyDialog().getDialog(
|
||||
'Are you sure to cancel?'.tr, '',
|
||||
() async {
|
||||
FirebaseMessagesController()
|
||||
Get.find<FirebaseMessagesController>()
|
||||
.sendNotificationToDriverMAP(
|
||||
'Driver Cancelled Your Trip',
|
||||
'You will need to pay the cost to the driver, or it will be deducted from your next trip'
|
||||
@@ -254,6 +257,9 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
[],
|
||||
'cancel.wav',
|
||||
);
|
||||
Log.print(
|
||||
'rideStatus from passenge info 261 : ${box.read(BoxName.rideStatus)}');
|
||||
box.write(BoxName.rideStatus, 'Cancel');
|
||||
await controller
|
||||
.addWaitingTimeCostFromPassengerToDriverWallet();
|
||||
controller.isdriverWaitTimeEnd = false;
|
||||
@@ -296,7 +302,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
_buildMessageTile(
|
||||
text: "Where are you, sir?".tr,
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Where are you, sir?".tr,
|
||||
controller.tokenPassenger,
|
||||
@@ -309,7 +315,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
_buildMessageTile(
|
||||
text: "I've been trying to reach you but your phone is off.".tr,
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"I've been trying to reach you but your phone is off.".tr,
|
||||
controller.tokenPassenger,
|
||||
@@ -324,7 +330,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
"Please don't be late, I'm waiting for you at the specified location."
|
||||
.tr,
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Please don't be late, I'm waiting for you at the specified location."
|
||||
.tr,
|
||||
@@ -338,7 +344,7 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
_buildMessageTile(
|
||||
text: "Please don't be late".tr,
|
||||
onTap: () {
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
"Please don't be late".tr,
|
||||
controller.tokenPassenger,
|
||||
@@ -364,7 +370,8 @@ class PassengerInfoWindow extends StatelessWidget {
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
Get.find<FirebaseMessagesController>()
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From Driver',
|
||||
controller.messageToPassenger.text,
|
||||
controller.tokenPassenger,
|
||||
|
||||
@@ -171,7 +171,7 @@ class SosConnect extends StatelessWidget {
|
||||
} else {
|
||||
throw 'Could not launch google maps';
|
||||
}
|
||||
};
|
||||
}();
|
||||
}
|
||||
|
||||
void _sendWhatsAppMessage(MapDriverController mapDriverController) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sefer_driver/constant/colors.dart';
|
||||
@@ -5,9 +7,13 @@ 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/views/widgets/mydialoug.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import '../../../constant/box_name.dart';
|
||||
import '../../../constant/links.dart';
|
||||
import '../../../controller/functions/crud.dart';
|
||||
import '../../../main.dart';
|
||||
import '../../../print.dart';
|
||||
import '../../widgets/elevated_btn.dart';
|
||||
import '../../widgets/my_textField.dart';
|
||||
|
||||
@@ -44,21 +50,34 @@ class PointsCaptain extends StatelessWidget {
|
||||
title: 'Pay with Credit Card'.tr,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
await paymentController.payWithPayMob(
|
||||
context,
|
||||
pricePoint.toStringAsFixed(2),
|
||||
box.read(BoxName.countryCode) == 'Egypt'
|
||||
? 'EGP'
|
||||
: 'JOD', () async {
|
||||
// await captainWalletController.getPaymentId(
|
||||
// 'visa-in', pricePoint);
|
||||
await captainWalletController.addDriverWallet(
|
||||
'visa-in', countPoint, pricePoint);
|
||||
await captainWalletController.addSeferWallet(
|
||||
'visa-in', pricePoint.toString());
|
||||
await captainWalletController
|
||||
.getCaptainWalletFromBuyPoints();
|
||||
});
|
||||
|
||||
var res = await CRUD().postWallet(
|
||||
// link: AppLink.payWithPayMobWalletPasenger,
|
||||
link: AppLink.payWithPayMobCardDriver,
|
||||
payload: {
|
||||
"amount": pricePoint.toStringAsFixed(2),
|
||||
"email": box.read(BoxName.emailDriver),
|
||||
"first_name": (box
|
||||
.read(BoxName.nameDriver)
|
||||
.toString()
|
||||
.split(' ')[0])
|
||||
.toString(),
|
||||
"last_name": (box
|
||||
.read(BoxName.nameDriver)
|
||||
.toString()
|
||||
.split(' ')[1])
|
||||
.toString(),
|
||||
"phone_number": (box.read(BoxName.phoneDriver)),
|
||||
});
|
||||
// var d = jsonDecode(res);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PaymentScreen(
|
||||
iframeUrl: res['message'],
|
||||
countPrice: countPoint.toString()),
|
||||
),
|
||||
);
|
||||
}, //51524
|
||||
),
|
||||
// Add some spacing between buttons
|
||||
@@ -88,31 +107,45 @@ class PointsCaptain extends StatelessWidget {
|
||||
BoxName.phoneWallet,
|
||||
paymentController
|
||||
.walletphoneController.text);
|
||||
await paymentController.payWithPayMobWallet(
|
||||
context,
|
||||
pricePoint.toStringAsFixed(2),
|
||||
box.read(BoxName.countryCode) == 'Egypt'
|
||||
? 'EGP'
|
||||
: 'JOD', () async {
|
||||
// await captainWalletController
|
||||
// .getPaymentId('visa-in', pricePoint);
|
||||
await captainWalletController
|
||||
.addDriverWallet('visa-in',
|
||||
countPoint, pricePoint);
|
||||
await captainWalletController
|
||||
.addSeferWallet(
|
||||
'visa-in', pricePoint.toString());
|
||||
await captainWalletController
|
||||
.getCaptainWalletFromBuyPoints();
|
||||
});
|
||||
var res = await CRUD().postWallet(
|
||||
// link: AppLink.payWithPayMobWalletPasenger,
|
||||
link: AppLink.payWithWallet,
|
||||
payload: {
|
||||
"amount":
|
||||
pricePoint.toStringAsFixed(2),
|
||||
"email":
|
||||
box.read(BoxName.emailDriver),
|
||||
"first_name": (box
|
||||
.read(BoxName.nameDriver)
|
||||
.toString()
|
||||
.split(' ')[0])
|
||||
.toString(),
|
||||
"last_name": (box
|
||||
.read(BoxName.nameDriver)
|
||||
.toString()
|
||||
.split(' ')[1])
|
||||
.toString(),
|
||||
"phone_number":
|
||||
(box.read(BoxName.phoneWallet)),
|
||||
});
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
PaymentScreenWallet(
|
||||
iframeUrl: res['message'],
|
||||
countPrice:
|
||||
countPoint.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
MyDialog().getDialog(
|
||||
'phone number is wrong'.tr,
|
||||
'',
|
||||
() {
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
// MyDialog().getDialog(
|
||||
// 'phone number is wrong'.tr,
|
||||
// '',
|
||||
// () {
|
||||
// Get.back();
|
||||
// },
|
||||
// );
|
||||
// Get.back();
|
||||
}));
|
||||
},
|
||||
@@ -173,3 +206,311 @@ class PointsCaptain extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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<PaymentScreen> createState() => _PaymentScreenState();
|
||||
}
|
||||
|
||||
class _PaymentScreenState extends State<PaymentScreen> {
|
||||
late final WebViewController _controller;
|
||||
final controller = Get.find<CaptainWalletController>();
|
||||
@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<void> _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<PaymentScreenWallet> createState() => _PaymentScreenWalletState();
|
||||
}
|
||||
|
||||
class _PaymentScreenWalletState extends State<PaymentScreenWallet> {
|
||||
late final WebViewController _controller;
|
||||
final controller = Get.find<CaptainWalletController>();
|
||||
@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<void> _fetchPaymentStatus() async {
|
||||
final String userId = '+2' + 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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user