24-12/26/1

This commit is contained in:
Hamza-Ayed
2024-12-26 00:58:41 +03:00
parent 970e444f4a
commit 186cd3aa54
14 changed files with 2912 additions and 3466 deletions

View File

@@ -575,7 +575,7 @@ class MapPassengerController extends GetxController {
void getDrawerMenu() {
heightMenuBool = !heightMenuBool;
widthMapTypeAndTraffic = heightMenuBool == true ? 0 : 50;
heightMenu = heightMenuBool == true ? 70 : 0;
heightMenu = heightMenuBool == true ? 80 : 0;
widthMenu = heightMenuBool == true ? 110 : 0;
update();
}
@@ -3160,7 +3160,7 @@ class MapPassengerController extends GetxController {
} else {
isMainBottomMenuMap = !isMainBottomMenuMap;
mainBottomMenuMapHeight =
isMainBottomMenuMap == true ? Get.height * .2 : Get.height * .55;
isMainBottomMenuMap == true ? Get.height * .2 : Get.height * .7;
isWayPointSheet = false;
if (heightMenuBool == true) {
getDrawerMenu();
@@ -4074,7 +4074,7 @@ class MapPassengerController extends GetxController {
LatLngBounds(northeast: northeast, southwest: southwest);
// Fit the camera to the bounds
var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 100);
var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 130);
mapController!.animateCamera(cameraUpdate);
// getDistanceFromText(data[0]['distance']['text']);
@@ -4132,117 +4132,51 @@ class MapPassengerController extends GetxController {
}
Future<void> _animatePolyline(List<LatLng> coordinates) async {
// Initial animation
polyLines.clear();
List<LatLng> animatedPoints = [];
const int totalAnimations = 7;
// Draw initial polyline
for (int i = 0; i < coordinates.length; i++) {
animatedPoints.add(coordinates[i]);
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: List<LatLng>.from(animatedPoints),
width: 4,
color: AppColor.primaryColor,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 1));
Color getAnimationColor(int cycle) {
switch (cycle) {
case 0:
return AppColor.primaryColor;
case 1:
return AppColor.writeColor;
case 2:
return AppColor.primaryColor;
default:
return AppColor.primaryColor;
}
}
// Color change animations
for (int cycle = 0; cycle < 6; cycle++) {
// Change to green
for (int cycle = 0; cycle < totalAnimations; cycle++) {
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: coordinates,
width: 4,
color: AppColor.bronze,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 500));
List<LatLng> animatedPoints = [];
// Change back to primary color
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: coordinates,
width: 4,
color: AppColor.writeColor,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 500));
for (int i = 0; i < coordinates.length; i++) {
animatedPoints.add(coordinates[i]);
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: List<LatLng>.from(animatedPoints),
width: 4,
color: getAnimationColor(cycle),
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 10));
}
if (cycle < totalAnimations - 1) {
await Future.delayed(const Duration(milliseconds: 500));
polyLines.clear();
update();
await Future.delayed(const Duration(milliseconds: 200));
}
}
}
// Add this method to your controller class
// Future<void> _animatePolyline(List<LatLng> coordinates) async {
// // Clear existing polylines
// polyLines.clear();
// // Create segments for animation
// List<LatLng> animatedPoints = [];
// // Calculate step size for smoother animation
// int stepSize = (coordinates.length / 20).round();
// stepSize = stepSize < 1 ? 1 : stepSize;
// for (int i = 0; i < coordinates.length; i += stepSize) {
// // Add points gradually
// animatedPoints.add(coordinates[i]);
// if (animatedPoints.length > 1) {
// // Remove previous polyline
// if (polyLines.isNotEmpty) {
// polyLines.clear();
// }
// // Add new polyline segment
// polyLines.add(
// Polyline(
// polylineId: const PolylineId('animated_route'),
// points: List<LatLng>.from(animatedPoints),
// width: 4,
// color: Colors.blue,
// ),
// );
// // Update camera position to follow animation
// if (mapController != null) {
// final bounds = LatLngBounds(
// southwest: animatedPoints.reduce((value, element) => LatLng(
// min(value.latitude, element.latitude),
// min(value.longitude, element.longitude))),
// northeast: animatedPoints.reduce((value, element) => LatLng(
// max(value.latitude, element.latitude),
// max(value.longitude, element.longitude))),
// );
// mapController!.animateCamera(
// CameraUpdate.newLatLngBounds(bounds, 100),
// );
// }
// }
// update();
// await Future.delayed(const Duration(milliseconds: 50));
// }
// }
String shortenAddress(String fullAddress) {
// Split the address into parts

File diff suppressed because it is too large Load Diff

View File

@@ -37,461 +37,297 @@ class LoginPage extends StatelessWidget {
isleading: false,
body: [
if (box.read(BoxName.agreeTerms) != 'agreed')
agreedPage()
_buildAgreementPage(controller)
else if (box.read(BoxName.countryCode) == null)
CountryPicker()
_buildCountryPicker()
else if (box.read(BoxName.locationPermission) != 'true')
locationPermissionDialog()
_buildLocationPermissionDialog(controller)
else
SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
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,
),
Platform.isIOS && controller.isTest == 0
? Container(
decoration: AppStyle.boxDecoration,
child: Column(
children: [
Form(
key: controller.formKey,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
children: [
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:
'Please enter your phone number.'
.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;
},
),
GetBuilder<LoginController>(
builder: (controller) =>
controller.isloading
? const MyCircularProgressIndicator()
: MyElevatedButton(
onPressed: () {
if (controller
.formKey
.currentState!
.validate()) {
controller
.login();
}
},
title:
'Submit'.tr,
),
)
],
),
),
),
),
const SizedBox(
height: 10,
),
],
),
)
: 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.signInFromLogin();
// },
// kolor: AppColor.blueColor,
// ),
InkWell(
onTap: () async {
await GoogleSignInHelper().signInFromLogin();
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: AppColor.redColor,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
FontAwesome.google,
color: AppColor.blueColor,
),
const SizedBox(width: 8),
Text(
'Sign In by Google'.tr,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
],
),
),
),
!Platform.isAndroid
? GestureDetector(
onTap: () async {
User? user =
await authController.signInWithApple();
if (user != null) {
box.write(BoxName.passengerID, user.uid);
box.write(BoxName.email, user.email);
await controller.loginUsingCredentials(
box
.read(BoxName.passengerID)
.toString(),
box.read(BoxName.email).toString(),
);
// Navigate to another screen or perform other actions
} else {
Get.snackbar('user not found'.tr, '',
backgroundColor: AppColor.redColor);
}
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.apple,
color: Colors.white,
size: 24,
),
const SizedBox(width: 8),
Text(
'Sign in with Apple'.tr,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
],
),
),
)
: const SizedBox(),
],
),
)),
SizedBox(
height: Get.height * .1,
),
GestureDetector(
onTap: () => Get.to(() => ContactUsPage()),
child: Text(
'If you need assistance, contact us'
.tr, // Improved wording
style: AppStyle.subtitle,
),
),
// Text(
// 'if you dont have account'.tr,
// style: AppStyle.subtitle,
// ),
// AnimatedTextKit(
// onTap: () => Get.to(() => SmsSignupEgypt()),
// animatedTexts: [
// TypewriterAnimatedText(
// 'Register'.tr,
// textStyle: AppStyle.headTitle2,
// speed: const Duration(milliseconds: 200),
// ),
// ],
// totalRepeatCount: 4,
// pause: const Duration(milliseconds: 200),
// displayFullTextOnTap: true,
// stopPauseOnTap: true,
// ),
// const Spacer(),
const SizedBox(
height: 100,
),
],
),
),
)
_buildLoginContent(controller, authController),
],
),
);
}
Padding agreedPage() {
return Padding(
padding: const EdgeInsets.all(16),
child: SingleChildScrollView(
Widget _buildLoginContent(
LoginController controller, AuthController authController) {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.asset(
'assets/images/notepad.png',
width: Get.width * .2,
),
SizedBox(
width: Get.width * .7,
child: Text(
'Accept Ride\'s Terms & Review Privacy Notice'.tr,
style: AppStyle.headTitle2,
),
),
],
Image.asset(
'assets/images/logo.gif',
height: Get.width * 0.4,
width: Get.width * 0.4,
fit: BoxFit.contain,
),
const SizedBox(
height: 30,
),
RichText(
text: TextSpan(
text:
'By selecting "I Agree" below, I have reviewed and agree to the Terms of Use and acknowledge the '
.tr,
style: AppStyle.title,
children: <TextSpan>[
TextSpan(
text: 'Privacy Notice'.tr,
style: const TextStyle(
decoration: TextDecoration.underline,
color: AppColor.blueColor),
recognizer: TapGestureRecognizer()
..onTap = () {
Get.defaultDialog(
title: ''.tr,
content: const SizedBox(
height: 400,
width: 400,
child: SingleChildScrollView(
child:
HtmlWidget(AppInformation.privacyPolicy),
),
));
}),
TextSpan(
text: '. I am at least 18 years of age.'.tr,
),
],
const SizedBox(height: 32),
if (Platform.isIOS && controller.isTest == 0)
_buildEmailPasswordForm(controller)
else
Padding(
padding: const EdgeInsets.only(bottom: 24.0),
child: Text(
'Sign in for a seamless experience'.tr,
textAlign: TextAlign.center,
style: AppStyle.subtitle,
),
),
InkWell(
onTap: () async => await GoogleSignInHelper().signInFromLogin(),
child: _buildSocialButton(
icon: FontAwesome.google,
text: 'Sign In with Google'.tr,
color: AppColor.redColor,
),
),
const SizedBox(
height: 100,
),
GetBuilder<LoginController>(
builder: (controller) => Column(
children: [
Row(
children: [
Checkbox.adaptive(
autofocus: true,
tristate: true,
splashRadius: 25,
activeColor: AppColor.primaryColor,
value: controller.isAgreeTerms,
onChanged: (value) => controller.changeAgreeTerm(),
),
Text(
'I Agree'.tr,
style: controller.isAgreeTerms
? AppStyle.title
: AppStyle.title
.copyWith(color: AppColor.accentColor),
),
],
),
MyElevatedButton(
title: 'Submit'.tr,
onPressed: () => controller.saveAgreementTerms()),
],
const SizedBox(height: 16),
if (!Platform.isAndroid)
GestureDetector(
onTap: () async {
User? user = await authController.signInWithApple();
if (user != null) {
box.write(BoxName.passengerID, user.uid);
box.write(BoxName.email, user.email);
await controller.loginUsingCredentials(
box.read(BoxName.passengerID).toString(),
box.read(BoxName.email).toString(),
);
} else {
Get.snackbar('User not found'.tr, '',
backgroundColor: AppColor.redColor);
}
},
child: _buildSocialButton(
icon: Icons.apple,
text: 'Sign in with Apple'.tr,
color: Colors.black,
),
),
)
const SizedBox(height: 40),
GestureDetector(
onTap: () => Get.to(() => ContactUsPage()),
child: Text(
'Need assistance? Contact us'.tr,
style: AppStyle.subtitle.copyWith(color: Colors.grey),
),
),
],
),
),
);
}
locationPermissionDialog() {
return GetBuilder<LoginController>(builder: (controller) {
return Padding(
padding: const EdgeInsets.all(16),
child: Container(
height: Get.height * .4,
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
'We use your precise location to find the nearest available driver and provide accurate pickup and dropoff information. You can manage this in Settings.'
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
TextButton(
onPressed: () {
// Optionally, navigate to app settings for manual permission control
openAppSettings();
},
child: Text(
"Open Settings".tr,
style: const TextStyle(color: AppColor.blueColor),
Widget _buildSocialButton({
required IconData icon,
required String text,
required Color color,
}) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: Colors.white),
const SizedBox(width: 12),
Text(
text,
style: const TextStyle(
color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
),
],
),
);
}
Widget _buildEmailPasswordForm(LoginController controller) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
keyboardType: TextInputType.emailAddress,
controller: controller.emailController,
decoration: InputDecoration(
labelText: 'Email'.tr,
hintText: 'Your email address'.tr,
border: const OutlineInputBorder(),
),
validator: (value) => value == null ||
value.isEmpty ||
!value.contains('@') ||
!value.contains('.')
? 'Enter a valid email'.tr
: null,
),
const SizedBox(height: 16),
TextFormField(
obscureText: true,
controller: controller.passwordController,
decoration: InputDecoration(
labelText: 'Password'.tr,
hintText: 'Your password'.tr,
border: const OutlineInputBorder(),
),
validator: (value) => value == null || value.isEmpty
? 'Enter your password'.tr
: null,
),
const SizedBox(height: 24),
GetBuilder<LoginController>(
builder: (controller) => controller.isloading
? const Center(child: CircularProgressIndicator())
: ElevatedButton(
onPressed: () {
if (controller.formKey.currentState!.validate()) {
controller.login();
}
},
child: Text('Submit'.tr),
),
),
MyElevatedButton(
title: 'Next'.tr,
onPressed: () async {
// if (box.read(BoxName.locationPermission) != 'true') {
// Get.put(MyDialog()).getDialog(
// 'Location Permission is requiered for find drivers'
// .tr,
// 'You can just manage your account!'.tr, () {
// Get.back();
// Get.to(() {
// PassengerProfilePage();
// });
// });
// } else {
await controller.getLocationPermission();
// }
),
],
),
),
);
}
Widget _buildAgreementPage(LoginController controller) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: Image.asset('assets/images/notepad.png', width: 40),
title: Text('Terms of Use & Privacy Notice'.tr,
style: AppStyle.headTitle2),
),
const SizedBox(height: 20),
RichText(
textAlign: TextAlign.left,
text: TextSpan(
style: AppStyle.title,
children: <TextSpan>[
TextSpan(
text:
'By selecting "I Agree" below, I confirm that I have read and agree to the '
.tr),
TextSpan(
text: 'Terms of Use'.tr,
style: const TextStyle(
decoration: TextDecoration.underline,
color: AppColor.blueColor),
),
const TextSpan(text: ' and acknowledge the '),
TextSpan(
text: 'Privacy Notice'.tr,
style: const TextStyle(
decoration: TextDecoration.underline,
color: AppColor.blueColor),
recognizer: TapGestureRecognizer()
..onTap = () {
Get.defaultDialog(
title: 'Privacy Notice'.tr,
content: const SizedBox(
height: 400,
width: 400,
child: SingleChildScrollView(
child: HtmlWidget(AppInformation.privacyPolicy),
),
),
);
},
kolor: AppColor.greenColor,
)
],
),
TextSpan(text: '. I am at least 18 years old.'.tr),
],
),
),
const SizedBox(height: 40),
Row(
children: [
Checkbox(
value: controller.isAgreeTerms,
onChanged: (newValue) => controller.changeAgreeTerm(),
activeColor: AppColor.primaryColor,
),
Text('I Agree'.tr, style: AppStyle.title),
],
),
const Spacer(),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: controller.isAgreeTerms
? () => controller.saveAgreementTerms()
: null,
child: Text('Continue'.tr),
),
),
),
),
);
});
],
),
);
}
Widget _buildLocationPermissionDialog(LoginController controller) {
return Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.location_on, size: 60, color: AppColor.primaryColor),
const SizedBox(height: 20),
Text(
'Enable Location Access'.tr,
style: AppStyle.headTitle2,
textAlign: TextAlign.center,
),
const SizedBox(height: 10),
Text(
'We need your location to find nearby drivers for pickups and drop-offs.'
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async => await controller.getLocationPermission(),
child: Text('Allow Location Access'.tr),
),
TextButton(
onPressed: () => openAppSettings(),
child: Text('Open Settings'.tr),
),
],
),
);
}
Widget _buildCountryPicker() {
return CountryPicker();
}
}

View File

@@ -33,7 +33,7 @@ class MapPagePassenger extends StatelessWidget {
Get.put(MapPassengerController());
Get.put(MyMenuController());
WidgetsBinding.instance.addPostFrameCallback((_) {
checkForUpdate(context);
// checkForUpdate(context);
});
return Scaffold(
@@ -53,7 +53,8 @@ class MapPagePassenger extends StatelessWidget {
// const HeaderDestination(),
const BurcMoney(),
const PromoCode(),
const ApplyOrderWidget(), const MapMenuWidget(),
const ApplyOrderWidget(),
const MapMenuWidget(),
// hexagonClipper(),
const CancelRidePageShow(),
CashConfirmPageShown(),

View File

@@ -18,472 +18,34 @@ class ApplyOrderWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Color _parseColor(String colorHex) {
if (colorHex.isEmpty) {
return Colors.grey; // Fallback for empty color
}
// Ensure the string starts with '0xff' for ARGB format
if (colorHex.isEmpty) return Colors.grey;
String processedHex = colorHex.replaceFirst('#', '0xff').trim();
if (!processedHex.startsWith('0xff')) {
processedHex = '0xff$processedHex'; // Add '0xff' if missing
}
return Color(int.parse(processedHex));
return Color(int.parse(processedHex.startsWith('0xff')
? processedHex
: '0xff$processedHex'));
}
return GetBuilder<MapPassengerController>(builder: (controller) {
if (controller.statusRide == 'Apply' &&
controller.isSearchingWindow == false) {
// double _height = Get.height * .2;
if (controller.statusRide == 'Apply' && !controller.isSearchingWindow) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: AppStyle.boxDecoration,
height: Get.height * .36,
child: ListView(
decoration: BoxDecoration(
// More modern BoxDecoration
color: Theme.of(context).cardColor,
borderRadius:
const BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [BoxShadow(blurRadius: 10, color: Colors.black12)],
),
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
InkWell(
onTap: () {
if (box.read(BoxName.carType) == 'Speed' ||
box.read(BoxName.carType) == 'Awfar Car' ||
box.read(BoxName.carType) == 'Delivery') {
Get.snackbar(
'This price is'.tr +
' ${controller.totalPassenger.toStringAsFixed(2)}'
.tr,
'This ride type does not allow changes to the destination or additional stops'
.tr,
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2),
backgroundColor: AppColor.yellowColor,
);
} else {
Get.snackbar(
'This price may be changed'.tr,
'This ride type allows changes, but the price may increase'
.tr,
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2),
backgroundColor: AppColor.yellowColor,
);
}
},
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'The driver accept your order for'.tr} ',
style: AppStyle.title,
),
TextSpan(
text: controller.totalPassenger.toStringAsFixed(2),
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold,
// fontSize: 22,
color: AppColor.redColor,
),
),
TextSpan(
text: ' ${'LE'.tr}',
style: AppStyle.title,
),
],
),
textAlign: TextAlign.center,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
width: 10,
),
Container(
height: Get.height * .31,
width: Get.width * .9,
decoration: AppStyle.boxDecoration,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
// 'Comfort',
box.read(BoxName.carType
.toString()), //car type fro box after selected
style: AppStyle.title,
),
const SizedBox(
width: 10,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// ColorFiltered(
// colorFilter: ColorFilter.mode(
// _parseColor(controller.colorHex),
// BlendMode.srcIn,
// ),
// child: Image.asset(
// box.read(BoxName.carType) == 'Comfort'
// ? 'assets/images/blob.png'
// : box.read(BoxName.carType) == 'Lady'
// ? 'assets/images/lady.png' // Assuming there's an image for Lady
// : box.read(BoxName.carType) == 'Speed'
// ? 'assets/images/carspeed.png'
// : box.read(BoxName.carType) ==
// 'Scooter'
// ? 'assets/images/moto.png'
// : box.read(BoxName.carType) ==
// 'Mishwar Vip'
// ? 'assets/images/freeRide.png'
// : box.read(BoxName
// .carType) ==
// 'Awfar Car'
// ? 'assets/images/balash.png'
// : box.read(BoxName
// .carType) ==
// 'Pink Bike'
// ? 'assets/images/pinkBike.png'
// : box.read(BoxName
// .carType) ==
// 'Rayeh Gai'
// ? 'assets/images/roundtrip.png'
// : 'assets/images/carspeed.png', // Default image if none of the above
// width: 80,
// ),
// ),
Column(
children: [
Text(
// 'Toyota Camry',
controller.model.toString(),
style: AppStyle.title,
),
Text(
// 'ر ل 2323',
controller.licensePlate.toString(),
style: AppStyle.title,
),
],
),
const SizedBox(
width: 10,
),
Text(
// 'Black',
controller.carColor.toString(),
style: AppStyle.title,
),
const SizedBox(
width: 10,
),
ColorFiltered(
colorFilter: ColorFilter.mode(
_parseColor(controller.colorHex),
BlendMode.srcIn,
),
child: Image.asset(
box.read(BoxName.carType) == 'Scooter' ||
box.read(BoxName.carType) ==
'Pink Bike'
? 'assets/images/moto.png'
: 'assets/images/car3.png',
width: 80,
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
radius: 25,
backgroundImage: NetworkImage(
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg',
),
child: Builder(
builder: (context) {
return Image.network(
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg',
fit: BoxFit.cover,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child; // Image is loaded
} else {
return Center(
child: CircularProgressIndicator(
value: loadingProgress
.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
(loadingProgress
.expectedTotalBytes ??
1)
: null,
),
);
}
},
errorBuilder: (BuildContext context,
Object error,
StackTrace? stackTrace) {
return const Icon(
Icons
.person, // Icon to show when image fails to load
size:
25, // Adjust the size as needed
color: AppColor
.blueColor, // Color for the error icon
);
},
);
},
),
),
Column(
children: [
Text(
// 'fadi ahmad',
controller.driverName,
style: AppStyle.title,
),
Text(
// '⭐ 4.8',
'${controller.driverRate}',
style: AppStyle.title,
),
],
),
IconButton(
onPressed: () async {
Get.defaultDialog(
title: 'Select one message',
titleStyle: AppStyle.title,
content: SizedBox(
width: 300,
height: Get.height * .5,
child: ListView(
children: [
InkWell(
onTap: () {
FirebaseMessagesController()
.sendNotificationToDriverMAP(
'message From passenger',
'Hello, I\'m at the agreed-upon location'
.tr,
controller.driverToken
.toString(),
[],
'ding.wav',
);
Get.back();
},
child: Container(
decoration:
AppStyle.boxDecoration,
child: Padding(
padding:
const EdgeInsets.all(
10),
child: Text(
'Hello, I\'m at the agreed-upon location'
.tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 5,
),
InkWell(
onTap: () {
FirebaseMessagesController()
.sendNotificationToDriverMAP(
'message From passenger',
'My location is correct. You can search for me using the navigation app'
.tr,
controller.driverToken,
[],
'ding.wav',
);
Get.back();
},
child: Container(
decoration:
AppStyle.boxDecoration,
child: Padding(
padding:
const EdgeInsets.all(
10),
child: Text(
'My location is correct. You can search for me using the navigation app'
.tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 5,
),
InkWell(
onTap: () {
FirebaseMessagesController()
.sendNotificationToDriverMAP(
'message From passenger',
'My location is correct. You can search for me using the navigation app'
.tr,
controller.driverToken,
[],
'ding.wav',
);
Get.back();
},
child: Container(
decoration:
AppStyle.boxDecoration,
child: Padding(
padding:
const EdgeInsets.all(
10),
child: Text(
'I\'m waiting for you'.tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 5,
),
InkWell(
onTap: () {
FirebaseMessagesController()
.sendNotificationToDriverMAP(
'message From passenger',
"How much longer will you be?"
.tr,
controller.driverToken,
[],
'ding.wav',
);
Get.back();
},
child: Container(
decoration:
AppStyle.boxDecoration,
child: Padding(
padding:
const EdgeInsets.all(
10),
child: Text(
"How much longer will you be?"
.tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 5,
),
SizedBox(
width: 190,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Form(
key: controller
.messagesFormKey,
child: SizedBox(
width: 160,
child: MyTextForm(
controller: controller
.messageToDriver,
label:
'Type Any thing'
.tr,
hint:
'Type Any thing'
.tr,
type:
TextInputType
.name),
)),
IconButton(
onPressed: () {
FirebaseMessagesController()
.sendNotificationToDriverMAP(
'message From passenger',
controller
.messageToDriver
.text,
controller
.driverToken,
[],
'ding.wav');
controller
.messageToDriver
.clear();
Get.back();
},
icon: const Icon(
Icons.send))
],
),
)
],
),
));
},
icon: const Icon(
Icons.message,
color: AppColor.blueColor,
size: 35,
),
),
IconButton(
onPressed: () async {
HapticFeedback.heavyImpact();
// Get.to(() => const CallPage());
// Get.to(() => PassengerCallPage());
makePhoneCall(controller.driverPhone);
},
icon: const Icon(
Icons.call,
color: AppColor.greenColor,
size: 35,
),
),
],
),
),
controller.isDriverArrivePassenger
? const DriverArrivePassengerAndWaitMinute()
: const TimeDriverToPassenger()
],
),
),
const SizedBox(
width: 10,
),
],
)
_buildPriceInfo(context, controller),
const SizedBox(height: 16),
_buildDriverInfoCard(context, controller, _parseColor),
],
),
),
@@ -493,45 +55,296 @@ class ApplyOrderWidget extends StatelessWidget {
}
});
}
Widget _buildPriceInfo(
BuildContext context, MapPassengerController controller) {
return InkWell(
onTap: () {
String message;
if (box.read(BoxName.carType) == 'Speed' ||
box.read(BoxName.carType) == 'Awfar Car' ||
box.read(BoxName.carType) == 'Delivery') {
message =
'This ride type does not allow changes to the destination or additional stops'
.tr;
} else {
message =
'This ride type allows changes, but the price may increase'.tr;
}
Get.snackbar(
'This price is'.tr +
' ${controller.totalPassenger.toStringAsFixed(2)}'.tr,
message,
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2),
backgroundColor:
AppColor.yellowColor.withOpacity(0.8), // More subtle background
);
},
child: Center(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'The driver accepted your order for'.tr} ',
style: AppStyle.title),
TextSpan(
text: controller.totalPassenger.toStringAsFixed(2),
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold, color: AppColor.redColor),
),
TextSpan(text: ' ${'LE'.tr}', style: AppStyle.title),
],
),
textAlign: TextAlign.center,
),
),
);
}
Widget _buildDriverInfoCard(BuildContext context,
MapPassengerController controller, Color Function(String) parseColor) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).canvasColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(box.read(BoxName.carType.toString()),
style:
AppStyle.title.copyWith(fontWeight: FontWeight.w500)),
Row(
children: [
_buildCarDetails(context, controller),
const SizedBox(width: 10),
_buildCarImage(controller, parseColor),
],
),
],
),
),
const Divider(height: 1, thickness: 1, color: Colors.grey),
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildDriverAvatarAndInfo(controller),
_buildContactButtons(context, controller),
],
),
),
Padding(
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, bottom: 12.0),
child: controller.isDriverArrivePassenger
? const DriverArrivePassengerAndWaitMinute()
: const TimeDriverToPassenger(),
),
],
),
);
}
Widget _buildCarDetails(
BuildContext context, MapPassengerController controller) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(controller.model.toString(), style: AppStyle.title),
Text(controller.licensePlate.toString(),
style: Theme.of(context).textTheme.bodyMedium),
Text(controller.carColor.toString(),
style: Theme.of(context).textTheme.bodyMedium),
],
);
}
Widget _buildCarImage(
MapPassengerController controller, Color Function(String) parseColor) {
return ColorFiltered(
colorFilter:
ColorFilter.mode(parseColor(controller.colorHex), BlendMode.srcIn),
child: Image.asset(
box.read(BoxName.carType) == 'Scooter' ||
box.read(BoxName.carType) == 'Pink Bike'
? 'assets/images/moto.png'
: 'assets/images/car3.png',
height: 60,
),
);
}
Widget _buildDriverAvatarAndInfo(MapPassengerController controller) {
return Row(
children: [
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg'),
onBackgroundImageError: (exception, stackTrace) =>
const Icon(Icons.person, size: 30, color: AppColor.blueColor),
),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(controller.driverName,
style: AppStyle.title.copyWith(fontWeight: FontWeight.w500)),
Text('${controller.driverRate}',
style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
],
);
}
Widget _buildContactButtons(
BuildContext context, MapPassengerController controller) {
return Row(
children: [
IconButton(
onPressed: () => _showContactOptionsDialog(context, controller),
icon: const Icon(Icons.message, color: AppColor.blueColor, size: 28),
),
IconButton(
onPressed: () {
HapticFeedback.heavyImpact();
makePhoneCall(controller.driverPhone);
},
icon: const Icon(Icons.call, color: AppColor.greenColor, size: 28),
),
],
);
}
void _showContactOptionsDialog(
BuildContext context, MapPassengerController controller) {
Get.defaultDialog(
title: 'Contact Options'.tr,
content: SizedBox(
width: 300,
height: Get.height * .4,
child: ListView(
// shrinkWrap: true,
children: [
..._buildPredefinedMessages(controller),
const SizedBox(height: 8),
_buildCustomMessageInput(controller, context),
],
),
),
);
}
List<Widget> _buildPredefinedMessages(MapPassengerController controller) {
const messages = [
'Hello, I\'m at the agreed-upon location',
'My location is correct. You can search for me using the navigation app',
'I\'m waiting for you',
"How much longer will you be?",
];
return messages
.map((message) => Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: ElevatedButton(
onPressed: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
'message From passenger',
message.tr,
controller.driverToken.toString(),
[],
'ding.wav',
);
Get.back();
},
child: Text(message.tr),
),
))
.toList();
}
Widget _buildCustomMessageInput(
MapPassengerController controller, BuildContext context) {
return Row(
children: [
Expanded(
child: Form(
key: controller.messagesFormKey,
child: MyTextForm(
controller: controller.messageToDriver,
label: 'Send a custom message'.tr,
hint: 'Type your message'.tr,
type: TextInputType.text,
),
),
),
IconButton(
onPressed: () {
if (controller.messagesFormKey.currentState!.validate()) {
FirebaseMessagesController().sendNotificationToDriverMAP(
'message From passenger',
controller.messageToDriver.text,
controller.driverToken,
[],
'ding.wav',
);
controller.messageToDriver.clear();
Get.back();
}
},
icon: const Icon(Icons.send),
),
],
);
}
}
class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
const DriverArrivePassengerAndWaitMinute({
super.key,
});
const DriverArrivePassengerAndWaitMinute({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) {
return Stack(
return Column(
children: [
LinearProgressIndicator(
backgroundColor: AppColor.accentColor,
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 25,
ClipRRect(
borderRadius: BorderRadius.circular(15),
value:
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
child: LinearProgressIndicator(
backgroundColor: AppColor.accentColor.withOpacity(0.3),
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 20,
value:
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'The driver waiting you in picked location .'.tr,
style: AppStyle.subtitle,
textAlign: TextAlign.center,
const SizedBox(height: 4),
Center(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'Driver is waiting at pickup.'.tr} ',
style: AppStyle.subtitle),
TextSpan(
text: controller
.stringRemainingTimeDriverWaitPassenger5Minute,
style: AppStyle.title),
],
),
const SizedBox(
width: 20,
),
Text(
controller.stringRemainingTimeDriverWaitPassenger5Minute,
style: AppStyle.title,
),
],
)
textAlign: TextAlign.center,
),
),
],
);
});
@@ -539,77 +352,50 @@ class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
}
class TimeDriverToPassenger extends StatelessWidget {
const TimeDriverToPassenger({
super.key,
});
const TimeDriverToPassenger({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) {
return controller.isDriverInPassengerWay == false ||
controller.timeToPassengerFromDriverAfterApplied > 0
? Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
child: Stack(
children: [
Container(
decoration: AppStyle.boxDecoration,
width: Get.width * .7,
height: 15,
// color: AppColor.yellowColor,
),
Stack(
? Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: LinearProgressIndicator(
backgroundColor: AppColor.accentColor.withOpacity(0.3),
color: controller
.remainingTimeToPassengerFromDriverAfterApplied <
60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 20,
value: controller
.progressTimerToPassengerFromDriverAfterApplied
.toDouble()
.clamp(0.0, 1.0),
),
),
const SizedBox(height: 4),
Center(
child: Text.rich(
TextSpan(
children: [
LinearProgressIndicator(
backgroundColor: AppColor.accentColor,
color: controller
.remainingTimeToPassengerFromDriverAfterApplied <
60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 25,
borderRadius: BorderRadius.circular(15),
value: () {
// Ensure valid value between 0.0 and 1.0
double progress = controller
.progressTimerToPassengerFromDriverAfterApplied
.toDouble();
if (progress.isNaN || progress.isInfinite) {
// Handle invalid progress (e.g., set to 0.0)
return 0.0;
} else {
return progress.clamp(
0.0, 1.0); // Clamp to valid range
}
}(),
TextSpan(
text: '${'Driver is on the way'.tr} ',
style: AppStyle.subtitle,
),
TextSpan(
text: controller.stringRemainingTimeToPassenger,
style: AppStyle.title,
),
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'The driver on your way'.tr,
style: AppStyle.title
.copyWith(color: AppColor.yellowColor),
textAlign: TextAlign.center,
),
const SizedBox(
width: 20,
),
Text(
controller.stringRemainingTimeToPassenger,
style: AppStyle.title,
),
],
),
)
],
),
],
textAlign: TextAlign.center,
),
),
),
],
)
: const SizedBox();
});

View File

@@ -102,20 +102,13 @@ class CarDetailsTypeToChoose extends StatelessWidget {
mapPassengerController.isBottomSheetShown &&
mapPassengerController.rideConfirm == false
? Positioned(
bottom: 0,
bottom: 15,
left: 8,
right: 8,
child: Container(
height: Get.height * .3,
height: Get.height * .32,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColor.secondaryColor,
AppColor.secondaryColor,
],
),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
@@ -130,6 +123,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.all(4),
@@ -139,7 +133,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
),
),
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(1.0),
child: SizedBox(
height: Get.height * .22, // Adjust height as needed
child: ListView.separated(
@@ -478,73 +472,101 @@ class PromoCode extends StatelessWidget {
Get.put(BlinkingController());
return GetBuilder<MapPassengerController>(
builder: (mapPassengerController) {
return mapPassengerController.data.isNotEmpty &&
mapPassengerController.isBottomSheetShown &&
mapPassengerController.rideConfirm == false &&
mapPassengerController.promoTaken == false
? GetBuilder<BlinkingController>(builder: (blinkingController) {
blinkingController.startBlinking();
return Positioned(
right: 5,
bottom: Get.height * 0.36,
child: Obx(() {
return AnimatedContainer(
duration: const Duration(milliseconds: 500),
width: 70, // Circle size
height: 70,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: blinkingController.isLightOn.value
? Colors.yellow
: Colors.grey, // Light on/off effect
border: Border.all(
color: blinkingController
.borderColor.value, // Animated border color
width: 3,
),
),
child: IconButton(
onPressed: () {
Get.defaultDialog(
title: 'Insert Your Promo Code'.tr,
content: Form(
key: mapPassengerController.promoFormKey,
child: MyTextForm(
controller: mapPassengerController.promo,
label: 'Insert Your Promo Code'.tr,
hint: 'Enter promo code here'.tr,
type: TextInputType.name,
),
final showPromoButton = mapPassengerController.data.isNotEmpty &&
mapPassengerController.isBottomSheetShown &&
!mapPassengerController.rideConfirm &&
!mapPassengerController.promoTaken;
return showPromoButton
? GetBuilder<BlinkingController>(
builder: (blinkingController) {
blinkingController.startBlinking();
return Positioned(
right: 16, // Adjusted from 5 for better spacing
bottom: Get.height * 0.36,
child: InkWell(
onTap: () {
Get.defaultDialog(
title: 'Apply Promo Code'.tr, // More engaging title
content: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Form(
key: mapPassengerController.promoFormKey,
child: MyTextForm(
controller: mapPassengerController.promo,
label: 'Promo Code'.tr, // Shortened label
hint: 'Enter your promo code'
.tr, // More friendly hint
type: TextInputType.name,
// style: AppStyle.normalTextBlack, // Apply consistent style
),
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
if (mapPassengerController
.promoFormKey.currentState!
.validate()) {
mapPassengerController
.applyPromoCodeToPassenger(context);
Get.back();
}
}));
},
icon: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.local_offer, size: 24), // Promo icon
SizedBox(height: 4),
Text(
"Promo",
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold),
),
),
confirm: MyElevatedButton(
title: 'Apply'.tr, // Shortened button title
onPressed: () {
if (mapPassengerController
.promoFormKey.currentState!
.validate()) {
mapPassengerController
.applyPromoCodeToPassenger(context);
Get.back();
}
},
),
cancel: OutlinedButton(
onPressed: () => Get.back(),
child: Text('Cancel'.tr),
),
);
},
child: Container(
width: 60, // Slightly smaller for a cleaner look
height: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white, // Solid white background
border: Border.all(
color: blinkingController.borderColor.value,
width: 2,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 5,
spreadRadius: 2,
),
],
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.local_offer,
size: 24,
color: blinkingController.isLightOn.value
? Colors.orange
: Colors
.grey.shade600, // Distinct promo color
),
const SizedBox(height: 2),
Text(
"Promo".tr,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
],
),
),
),
);
}),
);
})
),
);
},
)
: const SizedBox();
},
);
@@ -559,51 +581,89 @@ class BurcMoney extends StatelessWidget {
return GetBuilder<MapPassengerController>(
builder: (mapPassengerController) {
final passengerWallet =
double.tryParse(box.read(BoxName.passengerWalletTotal)) ??
0.0; // Handle potential parsing errors
double.tryParse(box.read(BoxName.passengerWalletTotal)) ?? 0.0;
return mapPassengerController.data.isNotEmpty &&
mapPassengerController.isBottomSheetShown &&
!mapPassengerController.rideConfirm
!mapPassengerController.rideConfirm &&
passengerWallet < 0.0 // Simplified condition
? Positioned(
bottom: Get.height * .41,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (passengerWallet < 0.0) // Use if statement for clarity
Container(
decoration: AppStyle.boxDecoration.copyWith(
color: AppColor.redColor.withOpacity(.3),
),
height: 50,
width: Get.width,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
left: 16, // Add left margin for better positioning
right: 16, // Add right margin
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.redColor
.withOpacity(0.8), // More prominent color
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Row(
children: [
const Icon(
Icons.warning_amber_rounded,
color: Colors.white,
size: 24,
),
const SizedBox(width: 8),
Expanded(
child: Text.rich(
TextSpan(
children: [
IconButton(
onPressed: () async => await Get.find<
TextToSpeechController>()
.speakText('you have a negative balance of'
.tr +
'${passengerWallet.toStringAsFixed(2)}'
' in your'
.tr +
' ${AppInformation.appName}'
' wallet due to a previous trip.'
.tr),
icon: const Icon(Icons.headphones)),
Text(
'${'you have a negative balance of'.tr}${'${passengerWallet.toStringAsFixed(2)}\n${' in your'.tr}'} ${AppInformation.appName}${' wallet due to a previous trip.'.tr}',
textAlign: TextAlign.center,
style: AppStyle.subtitle,
TextSpan(
text: '${'Negative Balance:'.tr} ',
style: AppStyle.subtitle.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
TextSpan(
text:
'${'You have a balance of'.tr} ${passengerWallet.toStringAsFixed(2)} ${box.read(BoxName.countryCode) == 'Egypt' ? 'LE'.tr : 'JOD'.tr} ${'due to a previous trip.'.tr}',
style: AppStyle.subtitle.copyWith(
color: Colors.white,
),
),
],
),
textAlign: TextAlign.start,
),
),
],
const SizedBox(width: 8),
GestureDetector(
onTap: () async =>
await Get.find<TextToSpeechController>().speakText(
'${'you have a negative balance of'.tr}${passengerWallet.toStringAsFixed(2)}${' in your'.tr} ${AppInformation.appName}${' wallet due to a previous trip.'.tr}'),
child: const Icon(
Icons.headphones,
color: Colors.white,
),
),
const SizedBox(width: 8),
// ElevatedButton(
// onPressed: () {
// Get.to(() => PassengerWallet());
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.white,
// foregroundColor: AppColor.redColor,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(6),
// ),
// padding: const EdgeInsets.symmetric(horizontal: 12),
// textStyle: const TextStyle(fontWeight: FontWeight.bold),
// ),
// child: Text('Top Up'.tr),
// ),
],
),
),
)
: const SizedBox();

View File

@@ -12,7 +12,6 @@ import '../../../controller/home/map_passenger_controller.dart';
import '../../../main.dart';
GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
// DbSql sql = DbSql.instance;
if (box.read(BoxName.addWork).toString() == '' ||
box.read(BoxName.addHome).toString() == '') {
box.write(BoxName.addWork, 'addWork');
@@ -20,349 +19,271 @@ GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
}
return GetBuilder<MapPassengerController>(
builder: (controller) => Column(
builder: (controller) => Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(6),
child: Column(
children: [
Container(
width: Get.width * .9,
height: 40,
decoration:
const BoxDecoration(color: AppColor.secondaryColor),
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.only(),
gapPadding: 4,
borderSide: BorderSide(
color: AppColor.redColor,
width: 2,
)),
suffixIcon: const Icon(Icons.search),
hintText: controller.hintTextDestinationPoint,
hintStyle: AppStyle.title,
hintMaxLines: 1,
prefixIcon: IconButton(
Expanded(
child: TextFormField(
controller: controller.placeDestinationController,
onChanged: (value) {
if (controller.placeDestinationController.text.length > 2) {
controller.getPlaces();
controller.changeHeightPlaces();
} else if (controller
.placeDestinationController.text.isEmpty) {
controller.clearPlacesDestination();
controller.changeHeightPlaces();
}
},
decoration: InputDecoration(
hintText: controller.hintTextDestinationPoint,
hintStyle:
AppStyle.subtitle.copyWith(color: Colors.grey[600]),
prefixIcon:
const Icon(Icons.search, color: AppColor.primaryColor),
suffixIcon: controller
.placeDestinationController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.clear, color: Colors.grey[400]),
onPressed: () {
controller.placeDestinationController.clear();
controller.clearPlacesDestination();
controller.changeHeightPlaces();
},
icon: Icon(
Icons.clear,
color: Colors.red[300],
),
),
),
controller: controller.placeDestinationController,
onChanged: (value) {
if (controller
.placeDestinationController.text.length >
5) {
controller.getPlaces();
controller.changeHeightPlaces();
}
},
// onEditingComplete: () => controller.changeHeight(),
),
)
: null,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
const SizedBox(
height: 10,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: AppColor.primaryColor),
),
Container(
decoration: AppStyle.boxDecoration1
.copyWith(color: AppColor.blueColor),
child: InkWell(
onTap: () {
controller.changeMainBottomMenuMap();
controller.changePickerShown();
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 4),
child: Text(
controller.isAnotherOreder
? 'Pick from map destination'.tr
: 'Pick from map'.tr,
style: AppStyle.title
.copyWith(color: AppColor.secondaryColor),
),
),
)),
const SizedBox(
height: 10,
),
SizedBox(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: () async {
if (box.read(BoxName.addWork) == 'addWork') {
controller.workLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
} else {
controller.hintTextDestinationPoint = 'To Work';
final latLng = LatLng(
double.parse(
box.read(BoxName.addWork).split(',')[0]),
double.parse(
box.read(BoxName.addWork).split(',')[1]),
);
controller.newMyLocation =
controller.newStartPointLocation;
controller.changeMainBottomMenuMap();
await controller.getDirectionMap(
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${latLng.latitude},${latLng.longitude}',
);
controller.currentLocationToFormPlaces = false;
controller.placesDestination = [];
// controller.isCancelRidePageShown = true;
controller.clearPlacesStart();
controller.clearPlacesDestination();
controller.passengerStartLocationFromMap =
false;
controller.isPickerShown = false;
controller.bottomSheet();
controller.showBottomSheet1();
}
},
onLongPress: () {
Get.defaultDialog(
title:
'Do you want to change Work location'.tr,
middleText: '',
confirm: MyElevatedButton(
title: 'Yes'.tr,
onPressed: () {
Get.back();
controller.workLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
}));
},
child: Container(
width: Get.width * .25,
decoration: BoxDecoration(
color: AppColor.blueColor.withOpacity(.4),
border: Border.all()),
child: Text(
' ${box.read(BoxName.addWork)}' == 'addWork'
? 'Add Work'.tr
: 'To Work'.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
),
),
InkWell(
onLongPress: () {
Get.defaultDialog(
title:
'Do you want to change Home location'.tr,
middleText: '',
confirm: MyElevatedButton(
title: 'Yes'.tr,
onPressed: () {
Get.back();
controller.homeLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
}));
},
onTap: () async {
if (box.read(BoxName.addHome) == 'addHome') {
controller.homeLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
} else {
controller.hintTextDestinationPoint = 'To Home';
final latLng = LatLng(
double.parse(
box.read(BoxName.addHome).split(',')[0]),
double.parse(
box.read(BoxName.addHome).split(',')[1]),
);
controller.changeMainBottomMenuMap();
// controller.newMyLocation = latLng;
await controller.getDirectionMap(
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${latLng.latitude},${latLng.longitude}',
);
controller.currentLocationToFormPlaces = false;
controller.placesDestination = [];
// controller.isCancelRidePageShown = true;
controller.clearPlacesStart();
controller.clearPlacesDestination();
controller.passengerStartLocationFromMap =
false;
controller.isPickerShown = false;
// controller.showBottomSheet1();
// Get.back();
controller.showBottomSheet1();
// controller.newMyLocation = latLng;
controller.update();
controller.update();
}
},
child: Container(
width: Get.width * .25,
decoration: BoxDecoration(
color: AppColor.blueColor.withOpacity(.4),
border: Border.all()),
child: Text(
style: AppStyle.title,
textAlign: TextAlign.center,
'${box.read(BoxName.addHome) == 'addHome' ? 'Add Home'.tr : "To Home".tr} '),
),
),
],
),
)
],
), //
filled: true,
fillColor: Colors.grey[50],
),
),
),
const SizedBox(width: 8.0),
IconButton(
onPressed: () {
controller.changeMainBottomMenuMap();
controller.changePickerShown();
},
icon: Icon(Icons.location_on_outlined,
color: AppColor.accentColor, size: 30),
tooltip: controller.isAnotherOreder
? 'Pick destination on map'
: 'Pick on map',
),
// controller.placesDestination.isEmpty
// ? InkWell(
// onTap: () {
// controller.changeMainBottomMenuMap();
// controller.changePickerShown();
// },
// child: Text(
// 'Choose from Map'.tr,
// style:
// AppStyle.title.copyWith(color: AppColor.blueColor),
// ),
// )
// : const SizedBox(),
Container(
height: controller.placesDestination.isNotEmpty
? controller.height
: 0,
color: AppColor.secondaryColor,
child: ListView.builder(
itemCount: controller.placesDestination.length,
itemBuilder: (BuildContext context, int index) {
var res = controller.placesDestination[index];
// Extract fields with null safety
var title = res['title']?.toString() ?? 'Unknown Place';
var position = res['position'];
var latitude = position?['lat'];
var longitude = position?['lng'];
var address =
res['address']?['label'] ?? 'Unknown Address';
var categories = res['categories'] ?? [];
var primaryCategory = categories.isNotEmpty
? categories[0]['name']
: 'Unknown Category';
return InkWell(
onTap: () async {
if (latitude != null && longitude != null) {
sql.insertMapLocation({
'latitude': latitude,
'longitude': longitude,
'name': title,
'rate': 'N/A',
'createdAt': DateTime.now().toIso8601String(),
// No rating in this structure, adjust as needed
}, TableName.recentLocations);
controller.passengerLocation =
controller.newMyLocation;
controller.myDestination =
LatLng(latitude, longitude);
controller
.convertHintTextDestinationNewPlaces(index);
controller.placesDestination = [];
controller.placeDestinationController.clear();
controller.changeMainBottomMenuMap();
controller.passengerStartLocationFromMap = true;
controller.isPickerShown = true;
} else {
Toast.show(
context,
'Invalid location data',
AppColor.redColor,
);
}
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
const Icon(Icons.place,
size: 20), // Fallback icon for places
IconButton(
onPressed: () async {
if (latitude != null &&
longitude != null) {
await sql.insertMapLocation({
'latitude': latitude,
'longitude': longitude,
'name': title,
'rate': 'N/A',
}, TableName.placesFavorite);
Toast.show(
context,
'$title ${'Saved Successfully'.tr}',
AppColor.primaryColor,
);
} else {
Toast.show(
context,
'Invalid location data',
AppColor.redColor,
);
}
},
icon: const Icon(Icons.favorite_border),
),
],
),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
title,
style: AppStyle.title,
),
Text(
address,
style: AppStyle.subtitle,
),
Text(
primaryCategory,
style: AppStyle.subtitle,
),
],
),
),
],
),
const Divider(thickness: 1),
],
),
),
);
},
))
],
));
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildQuickActionButton(
icon: Icons.work_outline,
text: box.read(BoxName.addWork) == 'addWork'
? 'Add Work'.tr
: 'To Work'.tr,
onTap: () async {
if (box.read(BoxName.addWork) == 'addWork') {
controller.workLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
} else {
_handleQuickAction(controller, BoxName.addWork, 'To Work');
}
},
onLongPress: () =>
_showChangeLocationDialog(controller, 'Work'),
),
_buildQuickActionButton(
icon: Icons.home_outlined,
text: box.read(BoxName.addHome) == 'addHome'
? 'Add Home'.tr
: 'To Home'.tr,
onTap: () async {
if (box.read(BoxName.addHome) == 'addHome') {
controller.homeLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
} else {
_handleQuickAction(controller, BoxName.addHome, 'To Home');
}
},
onLongPress: () =>
_showChangeLocationDialog(controller, 'Home'),
),
],
),
),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
height:
controller.placesDestination.isNotEmpty ? controller.height : 0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
),
margin: const EdgeInsets.symmetric(horizontal: 16.0),
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: controller.placesDestination.length,
separatorBuilder: (context, index) =>
const Divider(height: 1, color: Colors.grey),
itemBuilder: (BuildContext context, int index) {
var res = controller.placesDestination[index];
var title = res['title']?.toString() ?? 'Unknown Place';
var position = res['position'];
var latitude = position?['lat'];
var longitude = position?['lng'];
var address = res['address']?['label'] ?? 'Unknown Address';
var categories = res['categories'] ?? [];
var primaryCategory = categories.isNotEmpty
? categories[0]['name']
: 'Unknown Category';
return ListTile(
leading: const Icon(Icons.place, size: 30, color: Colors.grey),
title: Text(title,
style: AppStyle.subtitle
.copyWith(fontWeight: FontWeight.w500)),
subtitle: Text(address,
style: TextStyle(color: Colors.grey[600], fontSize: 12)),
trailing: IconButton(
icon: const Icon(Icons.favorite_border, color: Colors.grey),
onPressed: () async {
if (latitude != null && longitude != null) {
await sql.insertMapLocation({
'latitude': latitude,
'longitude': longitude,
'name': title,
'rate': 'N/A',
}, TableName.placesFavorite);
Toast.show(context, '$title ${'Saved Successfully'.tr}',
AppColor.primaryColor);
} else {
Toast.show(
context, 'Invalid location data', AppColor.redColor);
}
},
),
onTap: () async {
if (latitude != null && longitude != null) {
sql.insertMapLocation({
'latitude': latitude,
'longitude': longitude,
'name': title,
'rate': 'N/A',
'createdAt': DateTime.now().toIso8601String(),
}, TableName.recentLocations);
controller.passengerLocation = controller.newMyLocation;
controller.myDestination = LatLng(latitude, longitude);
controller.convertHintTextDestinationNewPlaces(index);
controller.placesDestination = [];
controller.placeDestinationController.clear();
controller.changeMainBottomMenuMap();
controller.passengerStartLocationFromMap = true;
controller.isPickerShown = true;
} else {
Toast.show(
context, 'Invalid location data', AppColor.redColor);
}
},
);
},
),
),
],
),
);
}
Widget _buildQuickActionButton({
required IconData icon,
required String text,
VoidCallback? onTap,
VoidCallback? onLongPress,
}) {
return InkWell(
onTap: onTap,
onLongPress: onLongPress,
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: AppColor.blueColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0),
border: Border.all(color: AppColor.blueColor.withOpacity(0.3)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, color: AppColor.blueColor),
const SizedBox(height: 4.0),
Text(
text,
textAlign: TextAlign.center,
style: AppStyle.title.copyWith(
color: AppColor.blueColor, fontWeight: FontWeight.w500),
),
],
),
),
);
}
void _showChangeLocationDialog(
MapPassengerController controller, String locationType) {
Get.defaultDialog(
title: 'Change $locationType location?'.tr,
middleText: '',
confirm: MyElevatedButton(
title: 'Yes'.tr,
onPressed: () {
Get.back();
if (locationType == 'Work') {
controller.workLocationFromMap = true;
} else {
controller.homeLocationFromMap = true;
}
controller.changeMainBottomMenuMap();
controller.changePickerShown();
},
),
);
}
void _handleQuickAction(
MapPassengerController controller, String boxName, String hintText) async {
final latLng = LatLng(
double.parse(box.read(boxName).toString().split(',')[0]),
double.parse(box.read(boxName).toString().split(',')[1]),
);
controller.hintTextDestinationPoint = hintText;
controller.changeMainBottomMenuMap();
await controller.getDirectionMap(
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${latLng.latitude},${latLng.longitude}',
);
controller.currentLocationToFormPlaces = false;
controller.placesDestination = [];
controller.clearPlacesStart();
controller.clearPlacesDestination();
controller.passengerStartLocationFromMap = false;
controller.isPickerShown = false;
controller.showBottomSheet1();
}

View File

@@ -9,181 +9,130 @@ import '../../../controller/home/map_passenger_controller.dart';
import '../../../main.dart';
GetBuilder<MapPassengerController> formSearchPlacesStart() {
// DbSql sql = DbSql.instance;
return GetBuilder<MapPassengerController>(
builder: (controller) => Column(
builder: (controller) => Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: Get.width * .75,
height: 40,
decoration:
const BoxDecoration(color: AppColor.secondaryColor),
child: TextFormField(
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.only(),
gapPadding: 4,
borderSide: BorderSide(
color: AppColor.redColor,
width: 2,
)),
suffixIcon: const Icon(Icons.search),
hintText: controller.hintTextStartPoint,
hintStyle: AppStyle.title,
hintMaxLines: 1,
prefixIcon: IconButton(
Expanded(
child: TextFormField(
controller: controller.placeStartController,
onChanged: (value) {
if (controller.placeStartController.text.length > 2) {
// Reduced character limit
controller.getPlacesStart();
controller.changeHeightStartPlaces();
} else if (controller.placeStartController.text.isEmpty) {
controller.clearPlacesStart();
controller.changeHeightPlaces(); // Collapse if empty
}
},
decoration: InputDecoration(
hintText: controller.hintTextStartPoint,
hintStyle:
AppStyle.subtitle.copyWith(color: Colors.grey[600]),
prefixIcon:
const Icon(Icons.search, color: AppColor.primaryColor),
suffixIcon: controller.placeStartController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.clear, color: Colors.grey[400]),
onPressed: () {
controller.placeStartController.clear();
controller.clearPlacesStart();
controller
.changeHeightPlaces(); // Collapse on clear
},
icon: Icon(
Icons.clear,
color: Colors.red[300],
),
),
),
controller: controller.placeStartController,
onChanged: (value) {
if (controller.placeStartController.text.length > 5) {
controller.getPlacesStart();
controller.changeHeightStartPlaces();
}
},
// onEditingComplete: () => controller.changeHeight(),
),
)
: null,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
IconButton(
onPressed: () {
controller.startLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
},
icon: const Icon(
Icons.map_outlined,
color: AppColor.yellowColor,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: AppColor.primaryColor),
),
],
filled: true,
fillColor: Colors.grey[50],
),
),
),
// controller.placesDestination.isEmpty
// ? InkWell(
// onTap: () {
// controller.startLocationFromMap = true;
// controller.changeMainBottomMenuMap();
// controller.changePickerShown();
// },
// child: Text(
// 'Choose from Map Start Point'.tr,
// style:
// AppStyle.title.copyWith(color: AppColor.blueColor),
// ),
// )
// : const SizedBox(),
Container(
height:
controller.placesStart.isNotEmpty ? controller.height : 0,
color: AppColor.secondaryColor,
child: ListView.builder(
itemCount: controller.placesStart.length,
itemBuilder: (BuildContext context, int index) {
var res = controller.placesStart[index];
return InkWell(
onTap: () async {
controller.changeHeightPlaces();
// if (controller.currentLocationToFormPlaces == true) {
// controller.newStartPointLocation =
// controller.myLocation;
// } else {
// controller.myLocation =
// controller.newStartPointLocation;
// }
await sql.insertMapLocation({
'latitude': res['geometry']['location']['lat'],
'longitude': res['geometry']['location']['lng'],
'name': res['name'].toString(),
'rate': res['rating'].toString(),
'createdAt': DateTime.now().toIso8601String(),
}, TableName.recentLocations);
controller.convertHintTextStartNewPlaces(index);
controller.currentLocationString = res['name'];
controller.placesStart = [];
controller.placeStartController.clear();
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Image.network(
res['icon'],
width: 20,
),
IconButton(
onPressed: () async {
await sql.insertMapLocation({
'latitude': res['geometry']
['location']['lat'],
'longitude': res['geometry']
['location']['lng'],
'name': res['name'].toString(),
'rate': res['rating'].toString(),
}, TableName.placesFavorite);
Toast.show(
context,
'${res['name']} ${'Saved Sucssefully'.tr}',
AppColor.primaryColor);
},
icon: const Icon(Icons.favorite_border),
),
],
),
Column(
children: [
Text(
res['name'].toString(),
style: AppStyle.title,
),
Text(
res['vicinity'].toString(),
style: AppStyle.subtitle,
),
],
),
Column(
children: [
Text(
'rate',
style: AppStyle.subtitle,
),
Text(
res['rating'].toString(),
style: AppStyle.subtitle,
),
],
),
],
),
const Divider(
thickness: 1,
)
],
),
),
);
const SizedBox(width: 8.0),
IconButton(
onPressed: () {
controller.startLocationFromMap = true;
controller.changeMainBottomMenuMap();
controller.changePickerShown();
},
icon: Icon(Icons.location_on_outlined,
color: AppColor.accentColor, size: 30),
tooltip: 'Choose on Map',
),
],
),
),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: controller.placesStart.isNotEmpty ? controller.height : 0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
),
margin: const EdgeInsets.symmetric(horizontal: 16.0),
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: controller.placesStart.length,
separatorBuilder: (context, index) =>
const Divider(height: 1, color: Colors.grey),
itemBuilder: (BuildContext context, int index) {
var res = controller.placesStart[index];
return ListTile(
leading: Image.network(res['icon'], width: 30, height: 30),
title: Text(res['name'].toString(),
style: AppStyle.subtitle
.copyWith(fontWeight: FontWeight.w500)),
subtitle: Text(res['vicinity'].toString(),
style: TextStyle(color: Colors.grey[600], fontSize: 12)),
trailing: IconButton(
icon: const Icon(Icons.favorite_border, color: Colors.grey),
onPressed: () async {
await sql.insertMapLocation({
'latitude': res['geometry']['location']['lat'],
'longitude': res['geometry']['location']['lng'],
'name': res['name'].toString(),
'rate': res['rating'].toString(),
}, TableName.placesFavorite);
Toast.show(
context,
'${res['name']} ${'Saved Successfully'.tr}',
AppColor.primaryColor);
},
),
)
],
));
onTap: () async {
controller.changeHeightPlaces();
await sql.insertMapLocation({
'latitude': res['geometry']['location']['lat'],
'longitude': res['geometry']['location']['lng'],
'name': res['name'].toString(),
'rate': res['rating'].toString(),
'createdAt': DateTime.now().toIso8601String(),
}, TableName.recentLocations);
controller.convertHintTextStartNewPlaces(index);
controller.currentLocationString = res['name'];
controller.placesStart = [];
controller.placeStartController.clear();
},
);
},
),
),
],
),
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,162 +15,182 @@ import 'package:url_launcher/url_launcher.dart';
import '../../../constant/colors.dart';
import '../../../controller/home/map_passenger_controller.dart';
import '../../notification/notification_page.dart';
import '../../widgets/icon_widget_menu.dart';
import '../setting_page.dart';
import '../profile/passenger_profile_page.dart';
class MapMenuWidget extends StatelessWidget {
const MapMenuWidget({
super.key,
});
const MapMenuWidget({super.key});
@override
Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(
builder: (controller) => Stack(children: [
Positioned(
right: 60,
left: 60,
child: Padding(
padding: const EdgeInsets.only(right: 20),
child: Opacity(
alwaysIncludeSemantics: false,
opacity: 1, // Adjust the opacity value as needed
child: AnimatedContainer(
width: Get.width * .6,
decoration: AppStyle.boxDecoration
.copyWith(color: AppColor.blueColor),
transform: Matrix4.translationValues(
controller.heightMenu * .1, 1, 1),
curve: Curves.easeOutCubic,
clipBehavior: Clip.hardEdge,
duration: const Duration(milliseconds: 300),
height: controller.heightMenu,
child: controller.heightMenuBool
? Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconWidgetMenu(
onpressed: () {
builder: (controller) => Stack(
children: [
// Top Menu Bar
Positioned(
top: 10, // Adjust as needed
left: 0,
right: 0,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// GestureDetector(
// onTap: controller.getDrawerMenu,
// child: Container(
// padding: const EdgeInsets.all(10),
// decoration: AppStyle.boxDecoration
// .copyWith(color: AppColor.blueColor),
// child: const Icon(Icons.menu, color: Colors.white),
// ),
// ),
if (controller.heightMenuBool)
Expanded(
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: 50, // Fixed height for the top menu
margin: const EdgeInsets.only(left: 10),
decoration: AppStyle.boxDecoration
.copyWith(color: AppColor.blueColor),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
onPressed: () {
Get.to(
() => const NotificationPage(),
transition: Transition.circularReveal,
);
},
title: 'Notifications'.tr,
icon: Icons.notifications),
IconWidgetMenu(
onpressed: () {
Get.to(
() => PassengerProfilePage(),
transition: Transition.zoom,
);
},
icon: Icons.person,
title: 'Profile'.tr,
),
IconWidgetMenu(
title: 'Home'.tr,
onpressed: () {
Get.to(
() => const SettingPage(),
transition: Transition.downToUp,
curve: Curves.easeInOutExpo,
);
icon: const Icon(Icons.notifications,
color: Colors.white),
),
IconButton(
onPressed: () {
Get.to(() => PassengerProfilePage(),
transition: Transition.zoom);
},
icon: Icons.settings),
],
)
: const SizedBox(), // Choose the desired overlay color
)),
icon: const Icon(Icons.person,
color: Colors.white),
),
IconButton(
onPressed: () {
Get.to(() => const SettingPage(),
transition: Transition.downToUp,
curve: Curves.easeInOutExpo);
},
icon: const Icon(Icons.settings,
color: Colors.white),
),
],
),
),
),
],
),
),
),
),
),
Positioned(
right: 5,
top: 80,
// Side Drawer (Main Menu)
Positioned(
top: 80, // Adjust as needed
left: 10,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: AppStyle.boxDecoration1,
width: controller.widthMenu,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconMainPageMap(
onTap: () {
Get.to(() => const PassengerWallet());
},
title: 'My Wallet'.tr,
icon: Icons.wallet,
),
IconMainPageMap(
onTap: () async {
Get.to(() => const OrderHistory());
},
title: 'Order History'.tr,
icon: Icons.history,
),
IconMainPageMap(
onTap: () {
Get.to(() => ContactUsPage());
},
title: "Contact Us".tr,
icon: Icons.contact_page,
),
],
),
)),
Positioned(
left: 5,
top: 80,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: AppStyle.boxDecoration1,
width: controller.widthMenu,
height: Get.height * .3,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconMainPageMap(
onTap: () async {
final String driverAppUrl;
if (defaultTargetPlatform == TargetPlatform.android) {
driverAppUrl =
'https://play.google.com/store/apps/details?id=com.sefer_driver&pli=1'; // Replace with your driver app's Play Store URL
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
driverAppUrl =
'https://apps.apple.com/app/sefer-driver/id6502189302'; // Replace with your driver app's App Store ID
} else {
// Handle other platforms or unknown platform (optional)
return;
}
constraints: const BoxConstraints(
maxWidth: 250), // Add max width constraint
if (await canLaunchUrl(Uri.parse(driverAppUrl))) {
await launchUrl(Uri.parse(driverAppUrl));
} else {
throw 'Could not launch app store URL';
}
},
title: 'Driver'.tr,
icon: WeatherIcons.wi_moon_14,
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Material(
color: Colors.white, // Background color of the drawer
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
IconMainPageMap(
onTap: () {
Get.to(() => const PassengerWallet());
},
title: 'My Wallet'.tr,
icon: Icons.wallet,
),
IconMainPageMap(
onTap: () async {
Get.to(() => const OrderHistory());
},
title: 'Order History'.tr,
icon: Icons.history,
),
IconMainPageMap(
onTap: () {
Get.to(() => ContactUsPage());
},
title: "Contact Us".tr,
icon: Icons.contact_page,
),
IconMainPageMap(
onTap: () async {
final String driverAppUrl;
if (defaultTargetPlatform == TargetPlatform.android) {
driverAppUrl =
'https://play.google.com/store/apps/details?id=your_android_driver_app_id'; // Replace with your driver app's Play Store URL
} else if (defaultTargetPlatform ==
TargetPlatform.iOS) {
driverAppUrl =
'https://apps.apple.com/app/your_ios_driver_app_id'; // Replace with your driver app's App Store ID
} else {
// Handle other platforms or unknown platform (optional)
return;
}
try {
final Uri url = Uri.parse(driverAppUrl);
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
Get.snackbar(
'Error',
'Could not launch driver app store.',
snackPosition: SnackPosition.BOTTOM,
);
}
} catch (e) {
debugPrint('Error launching URL: $e');
Get.snackbar(
'Error',
'Could not open the link.',
snackPosition: SnackPosition.BOTTOM,
);
}
},
title: 'Driver'.tr,
icon: WeatherIcons.wi_moon_14,
),
IconMainPageMap(
onTap: () {
Get.to(() => ComplaintPage());
},
title: 'Complaint'.tr,
icon: Icons.feedback,
),
IconMainPageMap(
onTap: () {
Get.to(() => const PromosPassengerPage());
},
title: 'Promos'.tr,
icon: Icons.monetization_on,
),
],
),
IconMainPageMap(
onTap: () {
Get.to(() => ComplaintPage());
},
title: 'Complaint'.tr,
icon: Icons.feedback,
),
IconMainPageMap(
onTap: () {
Get.to(() => const PromosPassengerPage());
},
title: 'Promos'.tr,
icon: Icons.monetization_on,
),
],
),
),
))
]),
),
),
],
),
);
}
}
@@ -189,29 +209,21 @@ class IconMainPageMap extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.delayed(const Duration(milliseconds: 400)),
builder: (context, snapshot) {
return GestureDetector(
onTap: onTap,
child: SizedBox(
height: Get.height * .1,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Icon(icon),
Text(
title.tr,
style: AppStyle.subtitle,
),
],
),
),
return InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 1),
child: Row(
children: [
Icon(icon, size: 24),
const SizedBox(width: 16),
Text(
title.tr,
style: AppStyle.subtitle,
),
);
});
],
),
),
);
}
}

View File

@@ -15,296 +15,252 @@ import '../../../controller/functions/toast.dart';
import '../../../controller/home/map_passenger_controller.dart';
class RideBeginPassenger extends StatelessWidget {
const RideBeginPassenger({
super.key,
});
const RideBeginPassenger({super.key});
@override
Widget build(BuildContext context) {
ProfileController profileController = Get.put(ProfileController());
AudioRecorderController audioController =
Get.put(AudioRecorderController());
// Get.put(MapPassengerController());
return GetBuilder<MapPassengerController>(builder: (controller) {
if (controller.statusRide == 'Begin' || !controller.statusRideFromStart) {
if (controller.statusRide == 'Begin') {
return Positioned(
left: 10,
right: 10,
bottom: 10,
child: Container(
decoration: AppStyle.boxDecoration,
height: controller.statusRide == 'Begin' ? Get.height * .33 : 0,
// width: 100,
child: Card(
// Wrapped in a Card
elevation: 5,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.min, // Use minimum space
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg'),
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg',
),
),
Column(
children: [
Container(
decoration: AppStyle.boxDecoration,
child: Text(
controller.driverName,
style: AppStyle.title,
),
),
Container(
decoration: AppStyle.boxDecoration,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(controller.driverName, style: AppStyle.title),
Row(
children: [
Text(
controller.make,
style: AppStyle.title,
),
Text(
controller.model,
style: AppStyle.title,
),
Text(controller.make, style: AppStyle.subtitle),
const SizedBox(width: 5),
Text(controller.model,
style: AppStyle.subtitle),
],
),
),
],
),
Column(
children: <Widget>[
const Text(''),
Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 4),
child: Text(
controller.licensePlate,
style: AppStyle.title,
),
),
),
],
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(3),
child: Text(
'${box.read(BoxName.carType)}',
style: AppStyle.title,
),
),
Text(
controller.licensePlate,
style: AppStyle.title.copyWith(fontSize: 16),
),
Text(
'${controller.driverRate} 📈',
style: AppStyle.title,
'${box.read(BoxName.carType)}',
style: AppStyle.title.copyWith(fontSize: 16),
),
Text(
'${controller.driverRate} ⭐️',
style: AppStyle.title
.copyWith(color: AppColor.greenColor),
),
],
),
],
),
// SizedBox(
// height: 5,
// ),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: () {
controller.getDialog('Arrival time'.tr,
'arrival time to reach your point'.tr, () {});
},
child: Container(
width: Get.width * .15,
decoration: AppStyle.boxDecoration,
SizedBox(
width: Get.width * 0.18,
child: InkWell(
onTap: () => controller.getDialog(
'Arrival time'.tr,
'arrival time to reach your point'.tr,
() {},
),
child: Column(
children: [
Text(
'⏱️',
style: AppStyle.title,
),
Text(
controller.arrivalTime,
style: AppStyle.title,
),
const Icon(Icons.timer_outlined, size: 28),
Text(controller.arrivalTime,
style: AppStyle.title),
],
),
),
),
InkWell(
onTap: () {
controller.getDialog(
'Price of trip'.tr,
'For Speed and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance'
.tr, () {
Get.back();
});
},
child: Container(
width: Get.width * .15,
decoration: AppStyle.boxDecoration,
SizedBox(
width: Get.width * 0.18,
child: InkWell(
onTap: () => controller.getDialog(
'Price of trip'.tr,
'For Speed and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance'
.tr,
() => Get.back(),
),
child: Column(
children: [
const Icon(Icons.monetization_on, size: 28),
Text(
'💵 ',
style: AppStyle.title,
),
Text(
controller.totalPassenger.toStringAsFixed(2),
style: AppStyle.title,
),
'${controller.totalPassenger.toStringAsFixed(2)}',
style: AppStyle.title),
],
),
),
),
Container(
width: Get.width * .15,
decoration: AppStyle.boxDecoration,
SizedBox(
width: Get.width * 0.18,
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
onPressed: () => Get.to(() => ComplaintPage(),
transition: Transition.downToUp),
icon: const Icon(Icons.note_add,
color: AppColor.redColor),
tooltip: 'Add Note',
),
),
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
),
SizedBox(
width: Get.width * 0.18,
child: IconButton(
onPressed: () async {
if (audioController.isRecording == false) {
await audioController.startRecording();
Toast.show(context, 'Start Record'.tr,
AppColor.greenColor);
} else {
await audioController.stopRecording();
Toast.show(context, 'Record saved'.tr,
AppColor.greenColor);
}
},
icon: Icon(
audioController.isRecording == false
? Icons.mic_none
: Icons.mic_off,
color: AppColor.greenColor,
),
tooltip: audioController.isRecording == false
? 'Start Recording'
: 'Stop Recording',
),
),
],
),
const SizedBox(height: 15),
Stack(
alignment: Alignment.center,
children: [
// StreamCounter(),
LinearProgressIndicator(
backgroundColor: AppColor.accentColor,
backgroundColor: AppColor.accentColor
.withOpacity(0.3), // Added background
color: controller.remainingTimeTimerRideBegin < 60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 25,
borderRadius: BorderRadius.circular(15),
minHeight: 20,
borderRadius: BorderRadius.circular(10),
value: controller.progressTimerRideBegin.toDouble(),
),
Center(
child: Text(
controller.stringRemainingTimeRideBegin,
style: AppStyle.title,
),
)
Text(
controller.stringRemainingTimeRideBegin,
style: AppStyle.title.copyWith(fontSize: 14),
),
],
),
const SizedBox(height: 15),
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,
),
SizedBox(
width: Get.width * 0.18,
child: Column(
children: [
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');
}
},
icon: const Icon(Icons.sos_rounded,
color: AppColor.redColor),
),
Text('SOS', style: AppStyle.title),
],
),
),
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,
),
SizedBox(
width: Get.width * 0.18,
child: Column(
children: [
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 {
final phoneNumber = box
.read(BoxName.sosPhonePassenger)
.toString();
final phone =
box.read(BoxName.countryCode) == 'Egypt'
? '+2$phoneNumber'
: '+962$phoneNumber';
controller.sendWhatsapp(phone);
}
},
icon: const Icon(FontAwesome.whatsapp,
color: AppColor.greenColor),
),
Text('WhatsApp', style: AppStyle.title),
],
),
),
Container(
decoration: AppStyle.boxDecoration,
width: Get.width * .15,
child: IconButton(
onPressed: () async {
await controller.getTokenForParent();
},
icon: const Icon(
Foundation.video,
color: AppColor.blueColor,
),
SizedBox(
width: Get.width * 0.18,
child: Column(
children: [
IconButton(
onPressed: () async {
await controller.getTokenForParent();
},
icon: const Icon(Foundation.video,
color: AppColor.blueColor),
),
Text('Video Call', style: AppStyle.title),
],
),
),
],
)
),
],
),
),
@@ -317,6 +273,7 @@ class RideBeginPassenger extends StatelessWidget {
}
}
// Removed the StreamCounter widget as it's not directly part of the RideBeginPassenger UI.
class StreamCounter extends StatelessWidget {
const StreamCounter({Key? key}) : super(key: key);

View File

@@ -21,35 +21,83 @@ class SearchingCaptainWindow extends StatelessWidget {
left: 0,
right: 0,
child: Container(
decoration: AppStyle.boxDecoration1,
height: Get.height * .25,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
// Use Stack for overlapping widgets
children: [
// Text elements
SizedBox(
width: Get.width * .7,
child: const LinearProgressIndicator(
minHeight: 6,
backgroundColor: AppColor.yellowColor,
color: AppColor.secondaryColor,
),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context)
.scaffoldBackgroundColor, // Use theme color
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, -5),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min, // Fit content
children: [
Text(
mapPassengerController.driversStatusForSearchWindow,
style: AppStyle.title,
style: AppStyle.title.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
// Text(
// "We are searching for the nearest driver to you".tr,
// style: AppStyle.title,
// ),
const SizedBox(height: 12),
Text(
'please wait till driver accept your order'.tr,
style: AppStyle.title,
), // Timer logic
_buildTimer(mapPassengerController),
'${'We are searching for the nearest driver to you'.tr}...', // Add ellipsis
style: AppStyle.subtitle.copyWith(
color: Colors.grey.shade600,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
SizedBox(
width: Get.width * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: LinearProgressIndicator(
minHeight: 8,
backgroundColor:
AppColor.accentColor.withOpacity(0.3),
color: AppColor.primaryColor,
valueColor: const AlwaysStoppedAnimation<Color>(
AppColor.primaryColor),
),
),
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.timer_outlined,
size: 16, color: Colors.grey),
const SizedBox(width: 4),
_buildTimer(mapPassengerController),
],
),
// const SizedBox(height: 8),
// ElevatedButton(
// onPressed: () {
// // Add logic to cancel the search if needed
// // mapPassengerController.cancelSearch();
// Get.back(); // Example: go back to the previous screen
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.grey.shade300,
// foregroundColor: Colors.black87,
// elevation: 0,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(8),
// ),
// ),
// child: Text('Cancel Search'.tr),
// ),
],
),
),
@@ -60,6 +108,22 @@ class SearchingCaptainWindow extends StatelessWidget {
}
}
// Widget _buildTimer(MapPassengerController mapPassengerController) {
// return Obx(() {
// final remainingSeconds = mapPassengerController.searchingDuration.value;
// final minutes = (remainingSeconds ~/ 60).toString().padLeft(2, '0');
// final seconds = (remainingSeconds % 60).toString().padLeft(2, '0');
// return Text(
// '$minutes:$seconds',
// style: const TextStyle(
// fontSize: 16,
// fontWeight: FontWeight.w500,
// color: Colors.grey,
// ),
// );
// });
// }
Widget _buildTimer(MapPassengerController mapPassengerController) {
// Start timer at 0
Timer? timer;

View File

@@ -1,4 +1,3 @@
import 'package:SEFER/controller/home/map_passenger_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:SEFER/constant/style.dart';
@@ -84,16 +83,54 @@ class OrderHistory extends StatelessWidget {
),
zoom: 12,
),
// bounds: LatLngBounds(
// northeast: LatLng(
// double.parse(rides['end_location'].toString().split(',')[0]),
// double.parse(rides['end_location'].toString().split(',')[1]),
// ),
// southwest: LatLng(
// double.parse(rides['start_location'].toString().split(',')[0]),
// double.parse(rides['start_location'].toString().split(',')[1]),
// ),
// ),
// Dynamically calculate the correct LatLngBounds
onMapCreated:
(GoogleMapController controller) {
final LatLng startLocation = LatLng(
double.parse(rides['start_location']
.toString()
.split(',')[0]),
double.parse(rides['start_location']
.toString()
.split(',')[1]),
);
final LatLng endLocation = LatLng(
double.parse(rides['end_location']
.toString()
.split(',')[0]),
double.parse(rides['end_location']
.toString()
.split(',')[1]),
);
final LatLngBounds bounds =
LatLngBounds(
northeast: LatLng(
startLocation.latitude >
endLocation.latitude
? startLocation.latitude
: endLocation.latitude,
startLocation.longitude >
endLocation.longitude
? startLocation.longitude
: endLocation.longitude,
),
southwest: LatLng(
startLocation.latitude <
endLocation.latitude
? startLocation.latitude
: endLocation.latitude,
startLocation.longitude <
endLocation.longitude
? startLocation.longitude
: endLocation.longitude,
),
);
controller.animateCamera(
CameraUpdate.newLatLngBounds(
bounds, 50));
},
zoomControlsEnabled: true,
polylines: {
Polyline(

View File

@@ -25,7 +25,7 @@ class IconWidgetMenu extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
width: 40,
decoration: const BoxDecoration(
color: AppColor.secondaryColor,
shape: BoxShape.circle,