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() { void getDrawerMenu() {
heightMenuBool = !heightMenuBool; heightMenuBool = !heightMenuBool;
widthMapTypeAndTraffic = heightMenuBool == true ? 0 : 50; widthMapTypeAndTraffic = heightMenuBool == true ? 0 : 50;
heightMenu = heightMenuBool == true ? 70 : 0; heightMenu = heightMenuBool == true ? 80 : 0;
widthMenu = heightMenuBool == true ? 110 : 0; widthMenu = heightMenuBool == true ? 110 : 0;
update(); update();
} }
@@ -3160,7 +3160,7 @@ class MapPassengerController extends GetxController {
} else { } else {
isMainBottomMenuMap = !isMainBottomMenuMap; isMainBottomMenuMap = !isMainBottomMenuMap;
mainBottomMenuMapHeight = mainBottomMenuMapHeight =
isMainBottomMenuMap == true ? Get.height * .2 : Get.height * .55; isMainBottomMenuMap == true ? Get.height * .2 : Get.height * .7;
isWayPointSheet = false; isWayPointSheet = false;
if (heightMenuBool == true) { if (heightMenuBool == true) {
getDrawerMenu(); getDrawerMenu();
@@ -4074,7 +4074,7 @@ class MapPassengerController extends GetxController {
LatLngBounds(northeast: northeast, southwest: southwest); LatLngBounds(northeast: northeast, southwest: southwest);
// Fit the camera to the bounds // Fit the camera to the bounds
var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 100); var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 130);
mapController!.animateCamera(cameraUpdate); mapController!.animateCamera(cameraUpdate);
// getDistanceFromText(data[0]['distance']['text']); // getDistanceFromText(data[0]['distance']['text']);
@@ -4132,11 +4132,25 @@ class MapPassengerController extends GetxController {
} }
Future<void> _animatePolyline(List<LatLng> coordinates) async { Future<void> _animatePolyline(List<LatLng> coordinates) async {
// Initial animation const int totalAnimations = 7;
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;
}
}
for (int cycle = 0; cycle < totalAnimations; cycle++) {
polyLines.clear(); polyLines.clear();
List<LatLng> animatedPoints = []; List<LatLng> animatedPoints = [];
// Draw initial polyline
for (int i = 0; i < coordinates.length; i++) { for (int i = 0; i < coordinates.length; i++) {
animatedPoints.add(coordinates[i]); animatedPoints.add(coordinates[i]);
polyLines.clear(); polyLines.clear();
@@ -4145,104 +4159,24 @@ class MapPassengerController extends GetxController {
polylineId: const PolylineId('animated_route'), polylineId: const PolylineId('animated_route'),
points: List<LatLng>.from(animatedPoints), points: List<LatLng>.from(animatedPoints),
width: 4, width: 4,
color: AppColor.primaryColor, color: getAnimationColor(cycle),
endCap: Cap.roundCap, endCap: Cap.roundCap,
startCap: Cap.roundCap, startCap: Cap.roundCap,
geodesic: true, geodesic: true,
), ),
); );
update(); update();
await Future.delayed(const Duration(milliseconds: 1)); await Future.delayed(const Duration(milliseconds: 10));
} }
// Color change animations if (cycle < totalAnimations - 1) {
for (int cycle = 0; cycle < 6; cycle++) {
// Change to green
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)); await Future.delayed(const Duration(milliseconds: 500));
// Change back to primary color
polyLines.clear(); 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(); update();
await Future.delayed(const Duration(milliseconds: 500)); 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) { String shortenAddress(String fullAddress) {
// Split the address into parts // Split the address into parts

File diff suppressed because it is too large Load Diff

View File

@@ -37,345 +37,210 @@ class LoginPage extends StatelessWidget {
isleading: false, isleading: false,
body: [ body: [
if (box.read(BoxName.agreeTerms) != 'agreed') if (box.read(BoxName.agreeTerms) != 'agreed')
agreedPage() _buildAgreementPage(controller)
else if (box.read(BoxName.countryCode) == null) else if (box.read(BoxName.countryCode) == null)
CountryPicker() _buildCountryPicker()
else if (box.read(BoxName.locationPermission) != 'true') else if (box.read(BoxName.locationPermission) != 'true')
locationPermissionDialog() _buildLocationPermissionDialog(controller)
else else
SingleChildScrollView( _buildLoginContent(controller, authController),
],
),
);
}
Widget _buildLoginContent(
LoginController controller, AuthController authController) {
return SingleChildScrollView(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
children: [ mainAxisAlignment: MainAxisAlignment.center,
Center(
child: Container(
decoration: AppStyle.boxDecoration1,
height: Get.height * .7,
width: Get.width * .9,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Image.asset( Image.asset(
'assets/images/logo.gif', 'assets/images/logo.gif',
height: Get.width * .3, height: Get.width * 0.4,
width: Get.width * .3, width: Get.width * 0.4,
fit: BoxFit.fill, fit: BoxFit.contain,
), ),
Platform.isIOS && controller.isTest == 0 const SizedBox(height: 32),
? Container( if (Platform.isIOS && controller.isTest == 0)
decoration: AppStyle.boxDecoration, _buildEmailPasswordForm(controller)
child: Column( else
children: [ Padding(
Form( padding: const EdgeInsets.only(bottom: 24.0),
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( child: Text(
'Sign in with Google for easier email and name entry' 'Sign in for a seamless experience'.tr,
.tr,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: AppStyle.title, style: AppStyle.subtitle,
), ),
), ),
),
// MyElevatedButton(
// title: 'Sign In by Google'.tr,
// onPressed: () async {
// await GoogleSignInHelper.signInFromLogin();
// },
// kolor: AppColor.blueColor,
// ),
InkWell( InkWell(
onTap: () async { onTap: () async => await GoogleSignInHelper().signInFromLogin(),
await GoogleSignInHelper().signInFromLogin(); child: _buildSocialButton(
}, icon: FontAwesome.google,
child: Container( text: 'Sign In with Google'.tr,
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: AppColor.redColor, 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,
), ),
), ),
], const SizedBox(height: 16),
), if (!Platform.isAndroid)
), GestureDetector(
),
!Platform.isAndroid
? GestureDetector(
onTap: () async { onTap: () async {
User? user = User? user = await authController.signInWithApple();
await authController.signInWithApple();
if (user != null) { if (user != null) {
box.write(BoxName.passengerID, user.uid); box.write(BoxName.passengerID, user.uid);
box.write(BoxName.email, user.email); box.write(BoxName.email, user.email);
await controller.loginUsingCredentials( await controller.loginUsingCredentials(
box box.read(BoxName.passengerID).toString(),
.read(BoxName.passengerID)
.toString(),
box.read(BoxName.email).toString(), box.read(BoxName.email).toString(),
); );
// Navigate to another screen or perform other actions
} else { } else {
Get.snackbar('user not found'.tr, '', Get.snackbar('User not found'.tr, '',
backgroundColor: AppColor.redColor); backgroundColor: AppColor.redColor);
} }
}, },
child: Container( child: _buildSocialButton(
padding: const EdgeInsets.symmetric( icon: Icons.apple,
horizontal: 16, vertical: 10), text: 'Sign in with Apple'.tr,
decoration: BoxDecoration(
color: Colors.black, 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(height: 40),
),
),
)
: const SizedBox(),
],
),
)),
SizedBox(
height: Get.height * .1,
),
GestureDetector( GestureDetector(
onTap: () => Get.to(() => ContactUsPage()), onTap: () => Get.to(() => ContactUsPage()),
child: Text( child: Text(
'If you need assistance, contact us' 'Need assistance? Contact us'.tr,
.tr, // Improved wording style: AppStyle.subtitle.copyWith(color: Colors.grey),
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,
),
], ],
), ),
), ),
) );
}
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),
),
], ],
), ),
); );
} }
Padding agreedPage() { Widget _buildEmailPasswordForm(LoginController controller) {
return Padding( return Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: SingleChildScrollView( decoration: BoxDecoration(
child: Column( color: Colors.white,
children: [ borderRadius: BorderRadius.circular(12),
Row( boxShadow: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, BoxShadow(
children: [ color: Colors.grey.withOpacity(0.2),
Image.asset( spreadRadius: 2,
'assets/images/notepad.png', blurRadius: 5,
width: Get.width * .2, offset: const Offset(0, 3),
), ),
SizedBox( ],
width: Get.width * .7, ),
child: Text( child: Form(
'Accept Ride\'s Terms & Review Privacy Notice'.tr, key: controller.formKey,
style: AppStyle.headTitle2, 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),
), ),
), ),
], ],
), ),
const SizedBox(
height: 30,
), ),
);
}
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( RichText(
textAlign: TextAlign.left,
text: TextSpan( 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, style: AppStyle.title,
children: <TextSpan>[ 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( TextSpan(
text: 'Privacy Notice'.tr, text: 'Privacy Notice'.tr,
style: const TextStyle( style: const TextStyle(
@@ -384,114 +249,85 @@ class LoginPage extends StatelessWidget {
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
Get.defaultDialog( Get.defaultDialog(
title: ''.tr, title: 'Privacy Notice'.tr,
content: const SizedBox( content: const SizedBox(
height: 400, height: 400,
width: 400, width: 400,
child: SingleChildScrollView( child: SingleChildScrollView(
child: child: HtmlWidget(AppInformation.privacyPolicy),
HtmlWidget(AppInformation.privacyPolicy),
), ),
));
}),
TextSpan(
text: '. I am at least 18 years of age.'.tr,
), ),
);
},
),
TextSpan(text: '. I am at least 18 years old.'.tr),
], ],
), ),
), ),
const SizedBox( const SizedBox(height: 40),
height: 100,
),
GetBuilder<LoginController>(
builder: (controller) => Column(
children: [
Row( Row(
children: [ children: [
Checkbox.adaptive( Checkbox(
autofocus: true,
tristate: true,
splashRadius: 25,
activeColor: AppColor.primaryColor,
value: controller.isAgreeTerms, value: controller.isAgreeTerms,
onChanged: (value) => controller.changeAgreeTerm(), onChanged: (newValue) => controller.changeAgreeTerm(),
), activeColor: AppColor.primaryColor,
Text(
'I Agree'.tr,
style: controller.isAgreeTerms
? AppStyle.title
: AppStyle.title
.copyWith(color: AppColor.accentColor),
), ),
Text('I Agree'.tr, style: AppStyle.title),
], ],
), ),
MyElevatedButton( const Spacer(),
title: 'Submit'.tr, Align(
onPressed: () => controller.saveAgreementTerms()), alignment: Alignment.bottomCenter,
], child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: controller.isAgreeTerms
? () => controller.saveAgreementTerms()
: null,
child: Text('Continue'.tr),
), ),
)
],
), ),
), ),
],
),
); );
} }
locationPermissionDialog() { Widget _buildLocationPermissionDialog(LoginController controller) {
return GetBuilder<LoginController>(builder: (controller) {
return Padding( return Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(32),
child: Container(
height: Get.height * .4,
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
const Icon(Icons.location_on, size: 60, color: AppColor.primaryColor),
const SizedBox(height: 20),
Text( 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.' '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, .tr,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: AppStyle.title, style: AppStyle.title,
), ),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async => await controller.getLocationPermission(),
child: Text('Allow Location Access'.tr),
),
TextButton( TextButton(
onPressed: () { onPressed: () => openAppSettings(),
// Optionally, navigate to app settings for manual permission control child: Text('Open Settings'.tr),
openAppSettings();
},
child: Text(
"Open Settings".tr,
style: const TextStyle(color: AppColor.blueColor),
), ),
),
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();
// }
},
kolor: AppColor.greenColor,
)
], ],
), ),
),
),
),
); );
}); }
Widget _buildCountryPicker() {
return CountryPicker();
} }
} }

View File

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

View File

@@ -18,472 +18,34 @@ class ApplyOrderWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Color _parseColor(String colorHex) { Color _parseColor(String colorHex) {
if (colorHex.isEmpty) { if (colorHex.isEmpty) return Colors.grey;
return Colors.grey; // Fallback for empty color
}
// Ensure the string starts with '0xff' for ARGB format
String processedHex = colorHex.replaceFirst('#', '0xff').trim(); String processedHex = colorHex.replaceFirst('#', '0xff').trim();
return Color(int.parse(processedHex.startsWith('0xff')
if (!processedHex.startsWith('0xff')) { ? processedHex
processedHex = '0xff$processedHex'; // Add '0xff' if missing : '0xff$processedHex'));
}
return Color(int.parse(processedHex));
} }
return GetBuilder<MapPassengerController>(builder: (controller) { return GetBuilder<MapPassengerController>(builder: (controller) {
if (controller.statusRide == 'Apply' && if (controller.statusRide == 'Apply' && !controller.isSearchingWindow) {
controller.isSearchingWindow == false) {
// double _height = Get.height * .2;
return Positioned( return Positioned(
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
child: Container( child: Container(
decoration: AppStyle.boxDecoration, decoration: BoxDecoration(
height: Get.height * .36, // More modern BoxDecoration
child: ListView( color: Theme.of(context).cardColor,
children: [ borderRadius:
InkWell( const BorderRadius.vertical(top: Radius.circular(20)),
onTap: () { boxShadow: [BoxShadow(blurRadius: 10, color: Colors.black12)],
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( padding: const EdgeInsets.all(16),
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( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( _buildPriceInfo(context, controller),
mainAxisAlignment: MainAxisAlignment.end, const SizedBox(height: 16),
children: [ _buildDriverInfoCard(context, controller, _parseColor),
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,
),
],
)
], ],
), ),
), ),
@@ -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 { class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
const DriverArrivePassengerAndWaitMinute({ const DriverArrivePassengerAndWaitMinute({Key? key}) : super(key: key);
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) { return GetBuilder<MapPassengerController>(builder: (controller) {
return Stack( return Column(
children: [ children: [
LinearProgressIndicator( ClipRRect(
backgroundColor: AppColor.accentColor, borderRadius: BorderRadius.circular(15),
child: LinearProgressIndicator(
backgroundColor: AppColor.accentColor.withOpacity(0.3),
color: controller.remainingTimeDriverWaitPassenger5Minute < 60 color: controller.remainingTimeDriverWaitPassenger5Minute < 60
? AppColor.redColor ? AppColor.redColor
: AppColor.greenColor, : AppColor.greenColor,
minHeight: 25, minHeight: 20,
borderRadius: BorderRadius.circular(15),
value: value:
controller.progressTimerDriverWaitPassenger5Minute.toDouble(), controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
), ),
Row( ),
mainAxisAlignment: MainAxisAlignment.center, const SizedBox(height: 4),
Center(
child: Text.rich(
TextSpan(
children: [ children: [
Text( TextSpan(
'The driver waiting you in picked location .'.tr, text: '${'Driver is waiting at pickup.'.tr} ',
style: AppStyle.subtitle, style: AppStyle.subtitle),
TextSpan(
text: controller
.stringRemainingTimeDriverWaitPassenger5Minute,
style: AppStyle.title),
],
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(
width: 20,
), ),
Text(
controller.stringRemainingTimeDriverWaitPassenger5Minute,
style: AppStyle.title,
),
],
)
], ],
); );
}); });
@@ -539,77 +352,50 @@ class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
} }
class TimeDriverToPassenger extends StatelessWidget { class TimeDriverToPassenger extends StatelessWidget {
const TimeDriverToPassenger({ const TimeDriverToPassenger({Key? key}) : super(key: key);
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) { return GetBuilder<MapPassengerController>(builder: (controller) {
return controller.isDriverInPassengerWay == false || return controller.isDriverInPassengerWay == false ||
controller.timeToPassengerFromDriverAfterApplied > 0 controller.timeToPassengerFromDriverAfterApplied > 0
? Container( ? Column(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
child: Stack(
children: [ children: [
Container( ClipRRect(
decoration: AppStyle.boxDecoration, borderRadius: BorderRadius.circular(15),
width: Get.width * .7, child: LinearProgressIndicator(
height: 15, backgroundColor: AppColor.accentColor.withOpacity(0.3),
// color: AppColor.yellowColor,
),
Stack(
children: [
LinearProgressIndicator(
backgroundColor: AppColor.accentColor,
color: controller color: controller
.remainingTimeToPassengerFromDriverAfterApplied < .remainingTimeToPassengerFromDriverAfterApplied <
60 60
? AppColor.redColor ? AppColor.redColor
: AppColor.greenColor, : AppColor.greenColor,
minHeight: 25, minHeight: 20,
borderRadius: BorderRadius.circular(15), value: controller
value: () {
// Ensure valid value between 0.0 and 1.0
double progress = controller
.progressTimerToPassengerFromDriverAfterApplied .progressTimerToPassengerFromDriverAfterApplied
.toDouble(); .toDouble()
if (progress.isNaN || progress.isInfinite) { .clamp(0.0, 1.0),
// Handle invalid progress (e.g., set to 0.0)
return 0.0;
} else {
return progress.clamp(
0.0, 1.0); // Clamp to valid range
}
}(),
), ),
),
const SizedBox(height: 4),
Center( Center(
child: Row( child: Text.rich(
mainAxisAlignment: MainAxisAlignment.center, TextSpan(
children: [ children: [
Text( TextSpan(
'The driver on your way'.tr, text: '${'Driver is on the way'.tr} ',
style: AppStyle.title style: AppStyle.subtitle,
.copyWith(color: AppColor.yellowColor),
textAlign: TextAlign.center,
), ),
const SizedBox( TextSpan(
width: 20, text: controller.stringRemainingTimeToPassenger,
),
Text(
controller.stringRemainingTimeToPassenger,
style: AppStyle.title, style: AppStyle.title,
), ),
], ],
), ),
) textAlign: TextAlign.center,
], ),
), ),
], ],
),
),
) )
: const SizedBox(); : const SizedBox();
}); });

View File

@@ -102,20 +102,13 @@ class CarDetailsTypeToChoose extends StatelessWidget {
mapPassengerController.isBottomSheetShown && mapPassengerController.isBottomSheetShown &&
mapPassengerController.rideConfirm == false mapPassengerController.rideConfirm == false
? Positioned( ? Positioned(
bottom: 0, bottom: 15,
left: 8, left: 8,
right: 8, right: 8,
child: Container( child: Container(
height: Get.height * .3, height: Get.height * .32,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( color: AppColor.secondaryColor,
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColor.secondaryColor,
AppColor.secondaryColor,
],
),
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@@ -130,6 +123,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
), ),
), ),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
@@ -139,7 +133,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(1.0),
child: SizedBox( child: SizedBox(
height: Get.height * .22, // Adjust height as needed height: Get.height * .22, // Adjust height as needed
child: ListView.separated( child: ListView.separated(
@@ -478,46 +472,38 @@ class PromoCode extends StatelessWidget {
Get.put(BlinkingController()); Get.put(BlinkingController());
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (mapPassengerController) { builder: (mapPassengerController) {
return mapPassengerController.data.isNotEmpty && final showPromoButton = mapPassengerController.data.isNotEmpty &&
mapPassengerController.isBottomSheetShown && mapPassengerController.isBottomSheetShown &&
mapPassengerController.rideConfirm == false && !mapPassengerController.rideConfirm &&
mapPassengerController.promoTaken == false !mapPassengerController.promoTaken;
? GetBuilder<BlinkingController>(builder: (blinkingController) {
return showPromoButton
? GetBuilder<BlinkingController>(
builder: (blinkingController) {
blinkingController.startBlinking(); blinkingController.startBlinking();
return Positioned( return Positioned(
right: 5, right: 16, // Adjusted from 5 for better spacing
bottom: Get.height * 0.36, bottom: Get.height * 0.36,
child: Obx(() { child: InkWell(
return AnimatedContainer( onTap: () {
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( Get.defaultDialog(
title: 'Insert Your Promo Code'.tr, title: 'Apply Promo Code'.tr, // More engaging title
content: Form( content: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Form(
key: mapPassengerController.promoFormKey, key: mapPassengerController.promoFormKey,
child: MyTextForm( child: MyTextForm(
controller: mapPassengerController.promo, controller: mapPassengerController.promo,
label: 'Insert Your Promo Code'.tr, label: 'Promo Code'.tr, // Shortened label
hint: 'Enter promo code here'.tr, hint: 'Enter your promo code'
.tr, // More friendly hint
type: TextInputType.name, type: TextInputType.name,
// style: AppStyle.normalTextBlack, // Apply consistent style
),
), ),
), ),
confirm: MyElevatedButton( confirm: MyElevatedButton(
title: 'Ok'.tr, title: 'Apply'.tr, // Shortened button title
onPressed: () { onPressed: () {
if (mapPassengerController if (mapPassengerController
.promoFormKey.currentState! .promoFormKey.currentState!
@@ -526,25 +512,61 @@ class PromoCode extends StatelessWidget {
.applyPromoCodeToPassenger(context); .applyPromoCodeToPassenger(context);
Get.back(); Get.back();
} }
}));
}, },
icon: const Column( ),
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, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.local_offer, size: 24), // Promo icon Icon(
SizedBox(height: 4), Icons.local_offer,
size: 24,
color: blinkingController.isLightOn.value
? Colors.orange
: Colors
.grey.shade600, // Distinct promo color
),
const SizedBox(height: 2),
Text( Text(
"Promo", "Promo".tr,
style: TextStyle( style: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold), fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
), ),
], ],
), ),
), ),
),
),
); );
}), },
); )
})
: const SizedBox(); : const SizedBox();
}, },
); );
@@ -559,52 +581,90 @@ class BurcMoney extends StatelessWidget {
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (mapPassengerController) { builder: (mapPassengerController) {
final passengerWallet = final passengerWallet =
double.tryParse(box.read(BoxName.passengerWalletTotal)) ?? double.tryParse(box.read(BoxName.passengerWalletTotal)) ?? 0.0;
0.0; // Handle potential parsing errors
return mapPassengerController.data.isNotEmpty && return mapPassengerController.data.isNotEmpty &&
mapPassengerController.isBottomSheetShown && mapPassengerController.isBottomSheetShown &&
!mapPassengerController.rideConfirm !mapPassengerController.rideConfirm &&
passengerWallet < 0.0 // Simplified condition
? Positioned( ? Positioned(
bottom: Get.height * .41, bottom: Get.height * .41,
child: Row( left: 16, // Add left margin for better positioning
mainAxisAlignment: MainAxisAlignment.end, right: 16, // Add right margin
children: [ child: Container(
if (passengerWallet < 0.0) // Use if statement for clarity padding: const EdgeInsets.all(12),
Container( decoration: BoxDecoration(
decoration: AppStyle.boxDecoration.copyWith( color: AppColor.redColor
color: AppColor.redColor.withOpacity(.3), .withOpacity(0.8), // More prominent color
), borderRadius: BorderRadius.circular(8),
height: 50, boxShadow: [
width: Get.width, BoxShadow(
child: Padding( color: Colors.black.withOpacity(0.1),
padding: const EdgeInsets.symmetric(horizontal: 8), blurRadius: 4,
child: Row( offset: const Offset(0, 2),
mainAxisAlignment: MainAxisAlignment.spaceAround,
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,
), ),
], ],
), ),
child: Row(
children: [
const Icon(
Icons.warning_amber_rounded,
color: Colors.white,
size: 24,
),
const SizedBox(width: 8),
Expanded(
child: Text.rich(
TextSpan(
children: [
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(); : const SizedBox();
}, },

View File

@@ -12,7 +12,6 @@ import '../../../controller/home/map_passenger_controller.dart';
import '../../../main.dart'; import '../../../main.dart';
GetBuilder<MapPassengerController> formSearchPlacesDestenation() { GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
// DbSql sql = DbSql.instance;
if (box.read(BoxName.addWork).toString() == '' || if (box.read(BoxName.addWork).toString() == '' ||
box.read(BoxName.addHome).toString() == '') { box.read(BoxName.addHome).toString() == '') {
box.write(BoxName.addWork, 'addWork'); box.write(BoxName.addWork, 'addWork');
@@ -23,247 +22,163 @@ GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
builder: (controller) => Column( builder: (controller) => Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Column( child: Row(
children: [ children: [
Container( Expanded(
width: Get.width * .9, child: TextFormField(
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(
onPressed: () {
controller.placeDestinationController.clear();
controller.clearPlacesDestination();
},
icon: Icon(
Icons.clear,
color: Colors.red[300],
),
),
),
controller: controller.placeDestinationController, controller: controller.placeDestinationController,
onChanged: (value) { onChanged: (value) {
if (controller if (controller.placeDestinationController.text.length > 2) {
.placeDestinationController.text.length >
5) {
controller.getPlaces(); controller.getPlaces();
controller.changeHeightPlaces(); controller.changeHeightPlaces();
} else if (controller
.placeDestinationController.text.isEmpty) {
controller.clearPlacesDestination();
controller.changeHeightPlaces();
} }
}, },
// onEditingComplete: () => controller.changeHeight(), 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();
},
)
: null,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: AppColor.primaryColor),
),
filled: true,
fillColor: Colors.grey[50],
), ),
), ),
const SizedBox(
height: 10,
), ),
Container( const SizedBox(width: 8.0),
decoration: AppStyle.boxDecoration1 IconButton(
.copyWith(color: AppColor.blueColor), onPressed: () {
child: InkWell(
onTap: () {
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
controller.changePickerShown(); controller.changePickerShown();
}, },
child: Padding( icon: Icon(Icons.location_on_outlined,
padding: const EdgeInsets.symmetric( color: AppColor.accentColor, size: 30),
horizontal: 20, vertical: 4), tooltip: controller.isAnotherOreder
child: Text( ? 'Pick destination on map'
controller.isAnotherOreder : 'Pick on map',
? 'Pick from map destination'.tr ),
: 'Pick from map'.tr, ],
style: AppStyle.title
.copyWith(color: AppColor.secondaryColor),
), ),
), ),
)), Padding(
const SizedBox( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
height: 10,
),
SizedBox(
height: 50,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
InkWell( _buildQuickActionButton(
icon: Icons.work_outline,
text: box.read(BoxName.addWork) == 'addWork'
? 'Add Work'.tr
: 'To Work'.tr,
onTap: () async { onTap: () async {
if (box.read(BoxName.addWork) == 'addWork') { if (box.read(BoxName.addWork) == 'addWork') {
controller.workLocationFromMap = true; controller.workLocationFromMap = true;
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
controller.changePickerShown(); controller.changePickerShown();
} else { } else {
controller.hintTextDestinationPoint = 'To Work'; _handleQuickAction(controller, BoxName.addWork, '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: () { onLongPress: () =>
Get.defaultDialog( _showChangeLocationDialog(controller, 'Work'),
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,
), ),
), _buildQuickActionButton(
), icon: Icons.home_outlined,
InkWell( text: box.read(BoxName.addHome) == 'addHome'
onLongPress: () { ? 'Add Home'.tr
Get.defaultDialog( : 'To Home'.tr,
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 { onTap: () async {
if (box.read(BoxName.addHome) == 'addHome') { if (box.read(BoxName.addHome) == 'addHome') {
controller.homeLocationFromMap = true; controller.homeLocationFromMap = true;
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
controller.changePickerShown(); controller.changePickerShown();
} else { } else {
controller.hintTextDestinationPoint = 'To Home'; _handleQuickAction(controller, BoxName.addHome, '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( onLongPress: () =>
width: Get.width * .25, _showChangeLocationDialog(controller, 'Home'),
),
],
),
),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
height:
controller.placesDestination.isNotEmpty ? controller.height : 0,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.blueColor.withOpacity(.4), color: Colors.white,
border: Border.all()), borderRadius: BorderRadius.circular(8.0),
child: Text(
style: AppStyle.title,
textAlign: TextAlign.center,
'${box.read(BoxName.addHome) == 'addHome' ? 'Add Home'.tr : "To Home".tr} '),
), ),
), margin: const EdgeInsets.symmetric(horizontal: 16.0),
], child: ListView.separated(
), shrinkWrap: true,
) physics: const NeverScrollableScrollPhysics(),
],
), //
),
// 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, itemCount: controller.placesDestination.length,
separatorBuilder: (context, index) =>
const Divider(height: 1, color: Colors.grey),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
var res = controller.placesDestination[index]; var res = controller.placesDestination[index];
// Extract fields with null safety
var title = res['title']?.toString() ?? 'Unknown Place'; var title = res['title']?.toString() ?? 'Unknown Place';
var position = res['position']; var position = res['position'];
var latitude = position?['lat']; var latitude = position?['lat'];
var longitude = position?['lng']; var longitude = position?['lng'];
var address = var address = res['address']?['label'] ?? 'Unknown Address';
res['address']?['label'] ?? 'Unknown Address';
var categories = res['categories'] ?? []; var categories = res['categories'] ?? [];
var primaryCategory = categories.isNotEmpty var primaryCategory = categories.isNotEmpty
? categories[0]['name'] ? categories[0]['name']
: 'Unknown Category'; : 'Unknown Category';
return InkWell( 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 { onTap: () async {
if (latitude != null && longitude != null) { if (latitude != null && longitude != null) {
sql.insertMapLocation({ sql.insertMapLocation({
@@ -272,15 +187,11 @@ GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
'name': title, 'name': title,
'rate': 'N/A', 'rate': 'N/A',
'createdAt': DateTime.now().toIso8601String(), 'createdAt': DateTime.now().toIso8601String(),
// No rating in this structure, adjust as needed
}, TableName.recentLocations); }, TableName.recentLocations);
controller.passengerLocation = controller.passengerLocation = controller.newMyLocation;
controller.newMyLocation; controller.myDestination = LatLng(latitude, longitude);
controller.myDestination = controller.convertHintTextDestinationNewPlaces(index);
LatLng(latitude, longitude);
controller
.convertHintTextDestinationNewPlaces(index);
controller.placesDestination = []; controller.placesDestination = [];
controller.placeDestinationController.clear(); controller.placeDestinationController.clear();
@@ -289,80 +200,90 @@ GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
controller.isPickerShown = true; controller.isPickerShown = true;
} else { } else {
Toast.show( Toast.show(
context, context, 'Invalid location data', AppColor.redColor);
'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),
],
),
),
); );
}, },
)) ),
),
], ],
)); ),
);
}
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,100 +9,112 @@ import '../../../controller/home/map_passenger_controller.dart';
import '../../../main.dart'; import '../../../main.dart';
GetBuilder<MapPassengerController> formSearchPlacesStart() { GetBuilder<MapPassengerController> formSearchPlacesStart() {
// DbSql sql = DbSql.instance;
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (controller) => Column( builder: (controller) => Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Container( Expanded(
width: Get.width * .75,
height: 40,
decoration:
const BoxDecoration(color: AppColor.secondaryColor),
child: TextFormField( 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( 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, hintText: controller.hintTextStartPoint,
hintStyle: AppStyle.title, hintStyle:
hintMaxLines: 1, AppStyle.subtitle.copyWith(color: Colors.grey[600]),
prefixIcon: IconButton( prefixIcon:
const Icon(Icons.search, color: AppColor.primaryColor),
suffixIcon: controller.placeStartController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.clear, color: Colors.grey[400]),
onPressed: () { onPressed: () {
controller.placeStartController.clear(); controller.placeStartController.clear();
controller.clearPlacesStart(); controller.clearPlacesStart();
controller
.changeHeightPlaces(); // Collapse on clear
}, },
icon: Icon( )
Icons.clear, : null,
color: Colors.red[300], contentPadding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(color: AppColor.primaryColor),
),
filled: true,
fillColor: Colors.grey[50],
), ),
), ),
), ),
controller: controller.placeStartController, const SizedBox(width: 8.0),
onChanged: (value) {
if (controller.placeStartController.text.length > 5) {
controller.getPlacesStart();
controller.changeHeightStartPlaces();
}
},
// onEditingComplete: () => controller.changeHeight(),
),
),
IconButton( IconButton(
onPressed: () { onPressed: () {
controller.startLocationFromMap = true; controller.startLocationFromMap = true;
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
controller.changePickerShown(); controller.changePickerShown();
}, },
icon: const Icon( icon: Icon(Icons.location_on_outlined,
Icons.map_outlined, color: AppColor.accentColor, size: 30),
color: AppColor.yellowColor, tooltip: 'Choose on Map',
),
), ),
], ],
), ),
), ),
// controller.placesDestination.isEmpty AnimatedContainer(
// ? InkWell( duration: const Duration(milliseconds: 200),
// onTap: () { height: controller.placesStart.isNotEmpty ? controller.height : 0,
// controller.startLocationFromMap = true; decoration: BoxDecoration(
// controller.changeMainBottomMenuMap(); color: Colors.white,
// controller.changePickerShown(); borderRadius: BorderRadius.circular(8.0),
// }, ),
// child: Text( margin: const EdgeInsets.symmetric(horizontal: 16.0),
// 'Choose from Map Start Point'.tr, child: ListView.separated(
// style: shrinkWrap: true,
// AppStyle.title.copyWith(color: AppColor.blueColor), physics: const NeverScrollableScrollPhysics(),
// ),
// )
// : const SizedBox(),
Container(
height:
controller.placesStart.isNotEmpty ? controller.height : 0,
color: AppColor.secondaryColor,
child: ListView.builder(
itemCount: controller.placesStart.length, itemCount: controller.placesStart.length,
separatorBuilder: (context, index) =>
const Divider(height: 1, color: Colors.grey),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
var res = controller.placesStart[index]; var res = controller.placesStart[index];
return InkWell( 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 { onTap: () async {
controller.changeHeightPlaces(); controller.changeHeightPlaces();
// if (controller.currentLocationToFormPlaces == true) {
// controller.newStartPointLocation =
// controller.myLocation;
// } else {
// controller.myLocation =
// controller.newStartPointLocation;
// }
await sql.insertMapLocation({ await sql.insertMapLocation({
'latitude': res['geometry']['location']['lat'], 'latitude': res['geometry']['location']['lat'],
'longitude': res['geometry']['location']['lng'], 'longitude': res['geometry']['location']['lng'],
@@ -116,74 +128,11 @@ GetBuilder<MapPassengerController> formSearchPlacesStart() {
controller.placesStart = []; controller.placesStart = [];
controller.placeStartController.clear(); 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,
)
],
),
),
); );
}, },
), ),
) ),
], ],
)); ),
);
} }

View File

@@ -26,177 +26,156 @@ class MainBottomMenuMap extends StatelessWidget {
Get.put(MapPassengerController()); Get.put(MapPassengerController());
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (controller) => Positioned( builder: (controller) => Positioned(
bottom: 3, bottom: 16, // Increased bottom padding
left: 5, left: 16,
right: 5, right: 16,
child: GestureDetector( child: GestureDetector(
onTap: controller
.changeMainBottomMenuMap, // Make the whole area tappable
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 500), duration: const Duration(
milliseconds: 300), // Reduced duration for smoother animation
curve: Curves.easeInOut, // Added animation curve
height: controller.mainBottomMenuMapHeight, height: controller.mainBottomMenuMapHeight,
decoration: AppStyle.boxDecoration, decoration: BoxDecoration(
color: AppColor.secondaryColor, // Use a solid background color
borderRadius: BorderRadius.circular(16), // More rounded corners
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const BouncingScrollPhysics(), // Add bouncing effect
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment
.stretch, // Stretch children to full width
children: [ children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
controller.isMainBottomMenuMap controller.isMainBottomMenuMap
? Padding( ? 'Where are you going?'.tr
padding: const EdgeInsets.all(15), : 'Quick Actions'.tr,
style: AppStyle.title
.copyWith(fontWeight: FontWeight.bold),
),
IconButton(
onPressed: controller.changeMainBottomMenuMap,
icon: Icon(
controller.isMainBottomMenuMap
? Icons.keyboard_arrow_down_rounded
: Icons.keyboard_arrow_up_rounded,
size: 28,
color: AppColor.primaryColor,
),
),
],
),
),
if (controller.isMainBottomMenuMap) ...[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: InkWell( child: InkWell(
onTap: () => onTap: () => controller.changeMainBottomMenuMap(),
controller.changeMainBottomMenuMap(),
child: Container( child: Container(
width: Get.width * .8, padding: const EdgeInsets.all(12),
height: Get.height * .1,
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( color: AppColor.primaryColor
colors: [ .withOpacity(0.05), // Subtle background
AppColor.blueColor.withOpacity(0.8), borderRadius: BorderRadius.circular(12),
AppColor.blueColor.withOpacity(0.6),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
), ),
boxShadow: const [
BoxShadow(
color: Color.fromARGB(
255, 237, 230, 230),
blurRadius: 8,
offset: Offset(4, 8),
),
BoxShadow(
color: Color.fromARGB(
255, 242, 237, 237),
blurRadius: 8,
offset: Offset(-4, -4),
),
],
borderRadius: BorderRadius.circular(30),
),
// decoration: AppStyle.boxDecoration1,
child: DefaultTextStyle( child: DefaultTextStyle(
style: AppStyle.title.copyWith( style: AppStyle.subtitle
color: AppColor.secondaryColor), .copyWith(color: AppColor.writeColor),
child: Center( child: Center(
child: controller.isPickerShown child: controller.isPickerShown
? clickPointPosition( ? clickPointPosition(controller, context)
controller, context)
: whereWidgetSmall(controller), : whereWidgetSmall(controller),
), ),
)),
),
)
: IconButton(
onPressed: () {
controller.changeMainBottomMenuMap();
},
icon: controller.isMainBottomMenuMap
? const Icon(
Icons.ads_click,
color: AppColor.secondaryColor,
size: 35,
)
: const Icon(
Icons.arrow_circle_down_rounded,
size: 35,
), ),
), ),
controller.isMainBottomMenuMap ),
? recentPlacesWidget(controller) ),
: const SizedBox(), const SizedBox(height: 12),
// controller.isMainBottomMenuMap if (controller.recentPlaces.isNotEmpty)
// ? const SizedBox() Padding(
// : InkWell( padding: const EdgeInsets.symmetric(horizontal: 16.0),
// onTap: () async { child: Column(
// controller.getCurrentLocationFormString(); crossAxisAlignment: CrossAxisAlignment.start,
// },
// child: Text(
// 'From :'.tr +
// ' ${controller.currentLocationString}'.tr,
// style: AppStyle.subtitle,
// ),
// ),
controller.isMainBottomMenuMap
? const SizedBox()
: Column(
children: [ children: [
!controller.isAnotherOreder Text('Recent Places'.tr, style: AppStyle.subtitle),
SizedBox(
height: 60,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: controller.recentPlaces.length,
separatorBuilder: (context, index) =>
const SizedBox(width: 8),
itemBuilder: (context, index) =>
_buildRecentPlaceButton(
controller, context, index),
),
),
],
),
),
] else ...[
if (!controller.isAnotherOreder)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'${'From:'.tr} ${controller.currentLocationString}'
.tr,
style: AppStyle.subtitle,
),
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: !controller.isAnotherOreder
? const SizedBox() ? const SizedBox()
: formSearchPlacesStart(), : formSearchPlacesStart(),
formSearchPlacesDestenation(),
const SizedBox(
height: 10,
), ),
// MyElevatedButton( Padding(
// title: 'Get Details of Trip'.tr, padding: const EdgeInsets.symmetric(horizontal: 16.0),
// onPressed: () async { child: formSearchPlacesDestenation(),
// controller.changeMainBottomMenuMap(); ),
// const SizedBox(height: 16),
// await controller.getMap( Padding(
// '${controller.newStartPointLocation.latitude},${controller.newStartPointLocation.longitude}', padding: const EdgeInsets.symmetric(horizontal: 16.0),
// '${controller.newMyLocation.latitude},${controller.newMyLocation.longitude}', child: GestureDetector(
// );
// controller.currentLocationToFormPlaces =
// false;
// controller.placesDestination = [];
// // controller.isCancelRidePageShown = true;
// controller.clearPlacesStart();
// controller.clearPlacesDestination();
//
// controller.showBottomSheet1();
// Get.back();
// controller.showBottomSheet1();
// }),
//todo If you want add stop click here
InkWell(
onTap: () { onTap: () {
Get.dialog( Get.dialog(
Dialog( AlertDialog(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: borderRadius: BorderRadius.circular(16)),
BorderRadius.circular(16)), title: Text('WhatsApp Location Extractor'.tr),
child: Padding( content: Form(
padding: const EdgeInsets.all(16), key: controller.sosFormKey,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [
Text(
'WhatsApp Location Extractor'
.tr,
style: AppStyle.title,
),
const SizedBox(height: 16),
Form(
key: controller.sosFormKey,
child: Column(
children: [ children: [
MyTextForm( MyTextForm(
controller: controller controller:
.whatsAppLocationText, controller.whatsAppLocationText,
label: label: 'Location Link'.tr,
'Location Link'.tr, hint: 'Paste location link here'.tr,
hint:
'Paste location link here'
.tr,
type: TextInputType.url, type: TextInputType.url,
), ),
const SizedBox( const SizedBox(height: 16),
height: 16),
MyElevatedButton( MyElevatedButton(
title: title: 'Go to this location'.tr,
'Go to this location'
.tr,
onPressed: () async { onPressed: () async {
controller controller.goToWhatappLocation();
.goToWhatappLocation();
}, },
)
],
),
), ),
], ],
), ),
@@ -206,102 +185,58 @@ class MainBottomMenuMap extends StatelessWidget {
}, },
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( color: Colors.blue.shade100, // Lighter background
colors: [
Colors.blue[300]!,
Colors.blue[600]!
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
boxShadow: const [ border: Border.all(
BoxShadow( color: Colors.blue.shade400), // Add a border
color: Colors.black26,
offset: Offset(0, 4),
blurRadius: 5.0,
), ),
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(Icons.link, color: Colors.blue.shade700),
const SizedBox(width: 8),
Expanded(
child: Text(
'Paste WhatsApp location link'.tr,
style: TextStyle(color: Colors.blue.shade700),
),
),
const Icon(Icons.arrow_forward_ios_rounded,
size: 16, color: Colors.blueGrey),
], ],
), ),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Paste WhatsApp location link here'
.tr,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
), ),
), ),
), ),
), const SizedBox(height: 16),
CupertinoButton( Padding(
child: Text( padding: const EdgeInsets.symmetric(horizontal: 16.0),
!controller.isAnotherOreder child: OutlinedButton(
? 'I want to order for someone else'
.tr
: 'I want to order for myself'.tr,
),
onPressed: () { onPressed: () {
showCupertinoModalPopup( showCupertinoModalPopup(
context: context, context: context,
builder: (BuildContext context) => builder: (BuildContext context) =>
CupertinoActionSheet( CupertinoActionSheet(
title: Text('Select Order Type'.tr), title: Text('Select Order Type'.tr),
message: Text( message: Text('Choose who this order is for'.tr),
'Choose who this order is for'
.tr),
actions: <Widget>[ actions: <Widget>[
CupertinoActionSheetAction( CupertinoActionSheetAction(
child: Row( child: Text('I want to order for myself'.tr),
mainAxisAlignment:
MainAxisAlignment.center,
children: [
const Icon(
CupertinoIcons.person,
color: CupertinoColors
.activeBlue),
const SizedBox(width: 15),
Text(
'I want to order for myself'
.tr),
],
),
onPressed: () { onPressed: () {
controller controller.changeisAnotherOreder(false);
.changeisAnotherOreder(
false);
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
CupertinoActionSheetAction( CupertinoActionSheetAction(
child: Row( child: Text(
mainAxisAlignment: 'I want to order for someone else'.tr),
MainAxisAlignment.center,
children: [
const Icon(
CupertinoIcons.person_2,
color: CupertinoColors
.activeBlue),
const SizedBox(width: 15),
Text(
'I want to order for someone else'
.tr),
],
),
onPressed: () { onPressed: () {
controller controller.changeisAnotherOreder(true);
.changeisAnotherOreder(
true);
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
], ],
cancelButton: cancelButton: CupertinoActionSheetAction(
CupertinoActionSheetAction(
isDefaultAction: true, isDefaultAction: true,
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
@@ -311,43 +246,39 @@ class MainBottomMenuMap extends StatelessWidget {
), ),
); );
}, },
) child: Text(
!controller.isAnotherOreder
? 'Order for someone else'.tr
: 'Order for myself'.tr,
),
),
),
], ],
) const SizedBox(height: 8),
], ],
), ),
), ),
), ),
), ),
)); ),
);
} }
SizedBox recentPlacesWidget(MapPassengerController controller) { Widget _buildRecentPlaceButton(
final textToSpeechController = Get.put(TextToSpeechController()); MapPassengerController controller, BuildContext context, int index) {
return SizedBox( final textToSpeechController = Get.find<TextToSpeechController>();
height: controller.recentPlaces.isEmpty ? 0 : 50, return InkWell(
child: ListView.builder( onTap: () {
itemCount: controller.recentPlaces.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return TextButton(
onPressed: () {
Get.defaultDialog( Get.defaultDialog(
title: 'Are you want to go this site'.tr, title: 'Are you want to go this site'.tr,
titleStyle: AppStyle.title, titleStyle: AppStyle.title,
middleText: '', middleText: '',
content: IconButton( content: IconButton(
onPressed: () { onPressed: () => textToSpeechController
textToSpeechController .speakText('Are you want to go this site'.tr),
.speakText('Are you want to go this site'.tr); icon: const Icon(Icons.headphones, size: 36),
},
icon: const Icon(
Icons.headphones,
size: 45,
), ),
), confirm: ElevatedButton(
confirm: MyElevatedButton(
title: 'Yes'.tr,
onPressed: () async { onPressed: () async {
Get.back(); Get.back();
await controller.getLocation(); await controller.getLocation();
@@ -355,48 +286,55 @@ class MainBottomMenuMap extends StatelessWidget {
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}', '${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${controller.recentPlaces[index]['latitude']},${controller.recentPlaces[index]['longitude']}', '${controller.recentPlaces[index]['latitude']},${controller.recentPlaces[index]['longitude']}',
); );
// controller.changePickerShown();
controller.showBottomSheet1(); controller.showBottomSheet1();
// controller.showBottomSheet1();
}, },
)); child: Text('Yes'.tr),
),
cancel:
OutlinedButton(onPressed: () => Get.back(), child: Text('No'.tr)),
);
}, },
onLongPress: () { onLongPress: () {
MyDialog().getDialog( MyDialog().getDialog(
"Are you sure to delete this location?".tr, '', () { "Are you sure to delete this location?".tr,
'',
() {
sql.deleteData(TableName.recentLocations,
controller.recentPlaces[index]['id']);
controller.getFavioratePlaces();
controller.update();
Get.back();
mySnackbarSuccess('deleted'.tr);
},
);
},
child: Chip(
label: Text(controller.recentPlaces[index]['name'],
style: const TextStyle(fontSize: 14)),
onDeleted: () {
MyDialog().getDialog(
"Are you sure to delete this location?".tr,
'',
() {
sql.deleteData(TableName.recentLocations, sql.deleteData(TableName.recentLocations,
controller.recentPlaces[index]['id']); controller.recentPlaces[index]['id']);
controller.getFavioratePlaces(); controller.getFavioratePlaces();
controller.update(); controller.update();
Get.back(); Get.back();
mySnackbarSuccess('deleted'.tr); mySnackbarSuccess('deleted'.tr);
});
}, },
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(2),
child: Text(
controller.recentPlaces[index]['name'],
style: AppStyle.title,
),
),
),
); );
}, },
), ),
); );
} }
TextButton clickPointPosition( Widget clickPointPosition(
MapPassengerController controller, BuildContext context) { MapPassengerController controller, BuildContext context) {
return TextButton( return TextButton(
onPressed: () async { onPressed: () async {
controller.clearPolyline(); controller.clearPolyline();
controller.data = []; controller.data = [];
//todo add isAnothorOrder
if (controller.passengerStartLocationFromMap == true) { if (controller.passengerStartLocationFromMap == true) {
controller.newMyLocation = controller.newStartPointLocation; controller.newMyLocation = controller.newStartPointLocation;
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
@@ -407,16 +345,11 @@ class MainBottomMenuMap extends StatelessWidget {
); );
controller.currentLocationToFormPlaces = false; controller.currentLocationToFormPlaces = false;
controller.placesDestination = []; controller.placesDestination = [];
// controller.isCancelRidePageShown = true;
controller.clearPlacesStart(); controller.clearPlacesStart();
controller.clearPlacesDestination(); controller.clearPlacesDestination();
controller.passengerStartLocationFromMap = false; controller.passengerStartLocationFromMap = false;
controller.isPickerShown = false; controller.isPickerShown = false;
// controller.showBottomSheet1();
// Get.back();
controller.showBottomSheet1(); controller.showBottomSheet1();
// controller.hintTextStartPoint =
// '${controller.newStartPointLocation.latitude.toStringAsFixed(4)} , ${controller.newStartPointLocation.longitude.toStringAsFixed(4)}';
} else if (controller.startLocationFromMap == true) { } else if (controller.startLocationFromMap == true) {
controller.newMyLocation = controller.newStartPointLocation; controller.newMyLocation = controller.newStartPointLocation;
controller.hintTextStartPoint = controller.hintTextStartPoint =
@@ -468,7 +401,7 @@ class MainBottomMenuMap extends StatelessWidget {
onPressed: () { onPressed: () {
Get.back(); Get.back();
})); }));
} else {} }
if (controller.isWhatsAppOrder == true) { if (controller.isWhatsAppOrder == true) {
Get.defaultDialog( Get.defaultDialog(
title: 'Destination selected'.tr, title: 'Destination selected'.tr,
@@ -482,99 +415,64 @@ class MainBottomMenuMap extends StatelessWidget {
onPressed: () { onPressed: () {
Get.back(); Get.back();
})); }));
} else {} }
} }
controller.placesDestination = []; controller.placesDestination = [];
controller.placeDestinationController.clear(); controller.placeDestinationController.clear();
controller.showBottomSheet1(); controller.showBottomSheet1();
// Get.back();
// controller.showBottomSheet1();
controller.changeMainBottomMenuMap(); controller.changeMainBottomMenuMap();
}, },
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
IconButton( Icon(
onPressed: () { controller.passengerStartLocationFromMap
// controller.changeMainBottomMenuMap(); ? Icons.location_on
}, : Icons.location_searching,
icon: controller.isMainBottomMenuMap size: 20,
? const Icon( color: AppColor.primaryColor,
Icons.arrow_circle_up_rounded,
size: 35,
color: AppColor.secondaryColor,
)
: const Icon(
Icons.arrow_circle_down_rounded,
size: 35,
),
), ),
const SizedBox(width: 8),
Text( Text(
controller.passengerStartLocationFromMap controller.passengerStartLocationFromMap
? 'Pick or Tap to confirm'.tr ? 'Confirm Pick-up Location'.tr
// ? 'Pick your ride location on the map - Tap to confirm'.tr : "Set Location on Map".tr,
: "Click here point".tr, style: AppStyle.subtitle.copyWith(
style: AppStyle.title.copyWith(
color: AppColor.secondaryColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18), color: AppColor.primaryColor,
),
), ),
], ],
), ),
),
); );
} }
Row whereWidgetSmall(MapPassengerController controller) { Widget whereWidgetSmall(MapPassengerController controller) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
IconButton( Icon(Icons.location_searching, color: AppColor.primaryColor),
onPressed: () { const SizedBox(width: 8),
controller.changeMainBottomMenuMap();
},
icon: controller.isMainBottomMenuMap
? const Icon(
Icons.ads_click,
color: AppColor.secondaryColor,
size: 35,
)
: const Icon(
Icons.arrow_circle_down_rounded,
size: 35,
),
),
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 25,
child: Text('${'Where to'.tr} ${box.read(BoxName.name)}')),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text('${'Where to'.tr} ${box.read(BoxName.name)}',
style: AppStyle.subtitle),
if (controller.noCarString) if (controller.noCarString)
Text('Nearest Car for you about '.tr) Text('Nearest Car: ~'.tr,
style: TextStyle(color: Colors.grey.shade600))
else else
Container( Text(
decoration: BoxDecoration( controller.nearestCar != null
borderRadius: BorderRadius.circular(12), ? 'Nearest Car: ${controller.nearestDistance.toStringAsFixed(0)} m'
color: AppColor.redColor, : 'No cars nearby'.tr,
style: TextStyle(color: Colors.grey.shade600),
), ),
child: null,
),
if (!controller.noCarString)
Padding(
padding: const EdgeInsets.all(4),
child: Text(
(controller.nearestCar != null
? controller.nearestDistance.toStringAsFixed(0)
: ''),
),
),
],
)
], ],
), ),
], ],
@@ -583,17 +481,13 @@ class MainBottomMenuMap extends StatelessWidget {
} }
class FaviouratePlacesDialog extends StatelessWidget { class FaviouratePlacesDialog extends StatelessWidget {
const FaviouratePlacesDialog({ const FaviouratePlacesDialog({super.key});
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Get.put(MapPassengerController()); Get.put(MapPassengerController());
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (controller) => DefaultTextStyle( builder: (controller) => Center(
style: AppStyle.title,
child: Center(
child: InkWell( child: InkWell(
onTap: () async { onTap: () async {
List favoritePlaces = List favoritePlaces =
@@ -609,74 +503,67 @@ class FaviouratePlacesDialog extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon( const Icon(
Icons.hourglass_empty_rounded, Icons.star_border_rounded,
size: 99, size: 99,
color: AppColor.primaryColor, color: AppColor.accentColor,
), ),
Text( Text(
'You Dont Have Any places yet !'.tr, 'No favorite places yet!'.tr,
style: AppStyle.title, style: AppStyle.title,
), ),
], ],
), ),
) )
: ListView.builder( : ListView.separated(
itemCount: favoritePlaces.length, itemCount: favoritePlaces.length,
separatorBuilder: (context, index) => const Divider(),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Row( return ListTile(
mainAxisAlignment: leading:
MainAxisAlignment.spaceBetween, const Icon(Icons.star, color: Colors.amber),
children: [ title: Text(favoritePlaces[index]['name'],
TextButton( style: AppStyle.title),
trailing: IconButton(
icon: const Icon(Icons.delete_outline,
color: Colors.redAccent),
onPressed: () async { onPressed: () async {
await sql.deleteData(TableName.placesFavorite,
favoritePlaces[index]['id']);
Get.back();
Toast.show(
context,
'${'Deleted'.tr} ${favoritePlaces[index]['name']} from your favorites',
AppColor.redColor);
},
),
onTap: () async {
Get.back(); Get.back();
await controller.getLocation(); await controller.getLocation();
await controller.getDirectionMap( await controller.getDirectionMap(
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}', '${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
'${favoritePlaces[index]['latitude']},${favoritePlaces[index]['longitude']}', '${favoritePlaces[index]['latitude']},${favoritePlaces[index]['longitude']}',
); );
// controller.changePickerShown();
controller.showBottomSheet1();
controller.showBottomSheet1(); controller.showBottomSheet1();
}, },
child: Text(
favoritePlaces[index]['name'],
style: AppStyle.title,
),
),
IconButton(
onPressed: () async {
await sql.deleteData(
TableName.placesFavorite,
favoritePlaces[index]['id']);
Get.back();
// ignore: use_build_context_synchronously
Toast.show(
context,
'${'You are Delete'.tr} ${favoritePlaces[index]['name']} from your list',
AppColor.redColor);
// Get.snackbar('Deleted'.tr,
// '${'You are Delete'.tr} ${favoritePlaces[index]['name']} from your list',
// backgroundColor:
// AppColor.accentColor);
},
icon: const Icon(Icons.favorite_outlined),
),
],
); );
}, },
), ),
), ),
cancel: MyElevatedButton( confirm: MyElevatedButton(
title: 'Back'.tr, onPressed: () => Get.back()), title: 'Back'.tr, onPressed: () => Get.back()),
); );
}, },
child: Text( child: Row(
'\u{1F3D8} ' 'Favorite Places'.tr, mainAxisSize: MainAxisSize.min,
style: AppStyle.title, children: [
const Icon(Icons.star_border_rounded,
color: AppColor.accentColor),
const SizedBox(width: 8),
Text('Favorite Places'.tr, style: AppStyle.title),
],
), ),
)), ),
)); ),
);
} }
} }

View File

@@ -15,85 +15,100 @@ import 'package:url_launcher/url_launcher.dart';
import '../../../constant/colors.dart'; import '../../../constant/colors.dart';
import '../../../controller/home/map_passenger_controller.dart'; import '../../../controller/home/map_passenger_controller.dart';
import '../../notification/notification_page.dart'; import '../../notification/notification_page.dart';
import '../../widgets/icon_widget_menu.dart';
import '../setting_page.dart'; import '../setting_page.dart';
import '../profile/passenger_profile_page.dart'; import '../profile/passenger_profile_page.dart';
class MapMenuWidget extends StatelessWidget { class MapMenuWidget extends StatelessWidget {
const MapMenuWidget({ const MapMenuWidget({super.key});
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>( return GetBuilder<MapPassengerController>(
builder: (controller) => Stack(children: [ builder: (controller) => Stack(
children: [
// Top Menu Bar
Positioned( Positioned(
right: 60, top: 10, // Adjust as needed
left: 60, left: 0,
right: 0,
child: SafeArea(
child: Padding( child: Padding(
padding: const EdgeInsets.only(right: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Opacity( child: Row(
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, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
IconWidgetMenu( // GestureDetector(
onpressed: () { // 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( Get.to(
() => const NotificationPage(), () => const NotificationPage(),
transition: Transition.circularReveal, transition: Transition.circularReveal,
); );
}, },
title: 'Notifications'.tr, icon: const Icon(Icons.notifications,
icon: Icons.notifications), color: Colors.white),
IconWidgetMenu(
onpressed: () {
Get.to(
() => PassengerProfilePage(),
transition: Transition.zoom,
);
},
icon: Icons.person,
title: 'Profile'.tr,
), ),
IconWidgetMenu( IconButton(
title: 'Home'.tr, onPressed: () {
onpressed: () { Get.to(() => PassengerProfilePage(),
Get.to( transition: Transition.zoom);
() => const SettingPage(), },
icon: const Icon(Icons.person,
color: Colors.white),
),
IconButton(
onPressed: () {
Get.to(() => const SettingPage(),
transition: Transition.downToUp, transition: Transition.downToUp,
curve: Curves.easeInOutExpo, curve: Curves.easeInOutExpo);
);
}, },
icon: Icons.settings), icon: const Icon(Icons.settings,
color: Colors.white),
),
], ],
)
: const SizedBox(), // Choose the desired overlay color
)),
), ),
), ),
),
],
),
),
),
),
// Side Drawer (Main Menu)
Positioned( Positioned(
right: 5, top: 80, // Adjust as needed
top: 80, left: 10,
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
decoration: AppStyle.boxDecoration1,
width: controller.widthMenu, width: controller.widthMenu,
constraints: const BoxConstraints(
maxWidth: 250), // Add max width constraint
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Material(
color: Colors.white, // Background color of the drawer
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisSize: MainAxisSize.min,
children: [ children: [
IconMainPageMap( IconMainPageMap(
onTap: () { onTap: () {
@@ -116,38 +131,39 @@ class MapMenuWidget extends StatelessWidget {
title: "Contact Us".tr, title: "Contact Us".tr,
icon: Icons.contact_page, 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( IconMainPageMap(
onTap: () async { onTap: () async {
final String driverAppUrl; final String driverAppUrl;
if (defaultTargetPlatform == TargetPlatform.android) { if (defaultTargetPlatform == TargetPlatform.android) {
driverAppUrl = driverAppUrl =
'https://play.google.com/store/apps/details?id=com.sefer_driver&pli=1'; // Replace with your driver app's Play Store URL '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) { } else if (defaultTargetPlatform ==
TargetPlatform.iOS) {
driverAppUrl = driverAppUrl =
'https://apps.apple.com/app/sefer-driver/id6502189302'; // Replace with your driver app's App Store ID 'https://apps.apple.com/app/your_ios_driver_app_id'; // Replace with your driver app's App Store ID
} else { } else {
// Handle other platforms or unknown platform (optional) // Handle other platforms or unknown platform (optional)
return; return;
} }
if (await canLaunchUrl(Uri.parse(driverAppUrl))) { try {
await launchUrl(Uri.parse(driverAppUrl)); final Uri url = Uri.parse(driverAppUrl);
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else { } else {
throw 'Could not launch app store URL'; 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, title: 'Driver'.tr,
@@ -169,8 +185,12 @@ class MapMenuWidget extends StatelessWidget {
), ),
], ],
), ),
)) ),
]), ),
),
),
],
),
); );
} }
} }
@@ -189,20 +209,14 @@ class IconMainPageMap extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder( return InkWell(
future: Future.delayed(const Duration(milliseconds: 400)),
builder: (context, snapshot) {
return GestureDetector(
onTap: onTap, onTap: onTap,
child: SizedBox(
height: Get.height * .1,
width: double.maxFinite,
// decoration: AppStyle.boxDecoration,
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 1),
child: Column( child: Row(
children: [ children: [
Icon(icon), Icon(icon, size: 24),
const SizedBox(width: 16),
Text( Text(
title.tr, title.tr,
style: AppStyle.subtitle, style: AppStyle.subtitle,
@@ -210,8 +224,6 @@ class IconMainPageMap extends StatelessWidget {
], ],
), ),
), ),
),
); );
});
} }
} }

View File

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

View File

@@ -21,37 +21,85 @@ class SearchingCaptainWindow extends StatelessWidget {
left: 0, left: 0,
right: 0, right: 0,
child: Container( child: Container(
decoration: AppStyle.boxDecoration1, padding: const EdgeInsets.all(16),
height: Get.height * .25, 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( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisSize: MainAxisSize.min, // Fit content
// Use Stack for overlapping widgets
children: [ children: [
// Text elements
SizedBox(
width: Get.width * .7,
child: const LinearProgressIndicator(
minHeight: 6,
backgroundColor: AppColor.yellowColor,
color: AppColor.secondaryColor,
),
),
Text( Text(
mapPassengerController.driversStatusForSearchWindow, mapPassengerController.driversStatusForSearchWindow,
style: AppStyle.title, style: AppStyle.title.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
), ),
// Text( textAlign: TextAlign.center,
// "We are searching for the nearest driver to you".tr, ),
// style: AppStyle.title, const SizedBox(height: 12),
// ),
Text( Text(
'please wait till driver accept your order'.tr, '${'We are searching for the nearest driver to you'.tr}...', // Add ellipsis
style: AppStyle.title, style: AppStyle.subtitle.copyWith(
), // Timer logic 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), _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),
// ),
],
),
), ),
) )
: const SizedBox(); : const SizedBox();
@@ -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) { Widget _buildTimer(MapPassengerController mapPassengerController) {
// Start timer at 0 // Start timer at 0
Timer? timer; Timer? timer;

View File

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

View File

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