24-12/26/1
This commit is contained in:
@@ -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,117 +4132,51 @@ class MapPassengerController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _animatePolyline(List<LatLng> coordinates) async {
|
Future<void> _animatePolyline(List<LatLng> coordinates) async {
|
||||||
// Initial animation
|
const int totalAnimations = 7;
|
||||||
polyLines.clear();
|
|
||||||
List<LatLng> animatedPoints = [];
|
|
||||||
|
|
||||||
// Draw initial polyline
|
Color getAnimationColor(int cycle) {
|
||||||
for (int i = 0; i < coordinates.length; i++) {
|
switch (cycle) {
|
||||||
animatedPoints.add(coordinates[i]);
|
case 0:
|
||||||
polyLines.clear();
|
return AppColor.primaryColor;
|
||||||
polyLines.add(
|
case 1:
|
||||||
Polyline(
|
return AppColor.writeColor;
|
||||||
polylineId: const PolylineId('animated_route'),
|
case 2:
|
||||||
points: List<LatLng>.from(animatedPoints),
|
return AppColor.primaryColor;
|
||||||
width: 4,
|
default:
|
||||||
color: AppColor.primaryColor,
|
return AppColor.primaryColor;
|
||||||
endCap: Cap.roundCap,
|
}
|
||||||
startCap: Cap.roundCap,
|
|
||||||
geodesic: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
update();
|
|
||||||
await Future.delayed(const Duration(milliseconds: 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color change animations
|
for (int cycle = 0; cycle < totalAnimations; cycle++) {
|
||||||
for (int cycle = 0; cycle < 6; cycle++) {
|
|
||||||
// Change to green
|
|
||||||
polyLines.clear();
|
polyLines.clear();
|
||||||
polyLines.add(
|
List<LatLng> animatedPoints = [];
|
||||||
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));
|
|
||||||
|
|
||||||
// Change back to primary color
|
for (int i = 0; i < coordinates.length; i++) {
|
||||||
polyLines.clear();
|
animatedPoints.add(coordinates[i]);
|
||||||
polyLines.add(
|
polyLines.clear();
|
||||||
Polyline(
|
polyLines.add(
|
||||||
polylineId: const PolylineId('animated_route'),
|
Polyline(
|
||||||
points: coordinates,
|
polylineId: const PolylineId('animated_route'),
|
||||||
width: 4,
|
points: List<LatLng>.from(animatedPoints),
|
||||||
color: AppColor.writeColor,
|
width: 4,
|
||||||
endCap: Cap.roundCap,
|
color: getAnimationColor(cycle),
|
||||||
startCap: Cap.roundCap,
|
endCap: Cap.roundCap,
|
||||||
geodesic: true,
|
startCap: Cap.roundCap,
|
||||||
),
|
geodesic: true,
|
||||||
);
|
),
|
||||||
update();
|
);
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
update();
|
||||||
|
await Future.delayed(const Duration(milliseconds: 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycle < totalAnimations - 1) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
polyLines.clear();
|
||||||
|
update();
|
||||||
|
await Future.delayed(const Duration(milliseconds: 200));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add this method to your controller class
|
|
||||||
// Future<void> _animatePolyline(List<LatLng> coordinates) async {
|
|
||||||
// // Clear existing polylines
|
|
||||||
// polyLines.clear();
|
|
||||||
|
|
||||||
// // Create segments for animation
|
|
||||||
// List<LatLng> animatedPoints = [];
|
|
||||||
|
|
||||||
// // Calculate step size for smoother animation
|
|
||||||
// int stepSize = (coordinates.length / 20).round();
|
|
||||||
// stepSize = stepSize < 1 ? 1 : stepSize;
|
|
||||||
|
|
||||||
// for (int i = 0; i < coordinates.length; i += stepSize) {
|
|
||||||
// // Add points gradually
|
|
||||||
// animatedPoints.add(coordinates[i]);
|
|
||||||
|
|
||||||
// if (animatedPoints.length > 1) {
|
|
||||||
// // Remove previous polyline
|
|
||||||
// if (polyLines.isNotEmpty) {
|
|
||||||
// polyLines.clear();
|
|
||||||
// }
|
|
||||||
// // Add new polyline segment
|
|
||||||
// polyLines.add(
|
|
||||||
// Polyline(
|
|
||||||
// polylineId: const PolylineId('animated_route'),
|
|
||||||
// points: List<LatLng>.from(animatedPoints),
|
|
||||||
// width: 4,
|
|
||||||
// color: Colors.blue,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Update camera position to follow animation
|
|
||||||
// if (mapController != null) {
|
|
||||||
// final bounds = LatLngBounds(
|
|
||||||
// southwest: animatedPoints.reduce((value, element) => LatLng(
|
|
||||||
// min(value.latitude, element.latitude),
|
|
||||||
// min(value.longitude, element.longitude))),
|
|
||||||
// northeast: animatedPoints.reduce((value, element) => LatLng(
|
|
||||||
// max(value.latitude, element.latitude),
|
|
||||||
// max(value.longitude, element.longitude))),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// mapController!.animateCamera(
|
|
||||||
// CameraUpdate.newLatLngBounds(bounds, 100),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// update();
|
|
||||||
// await Future.delayed(const Duration(milliseconds: 50));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
String shortenAddress(String fullAddress) {
|
String shortenAddress(String fullAddress) {
|
||||||
// Split the address into parts
|
// Split the address into parts
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -37,461 +37,297 @@ 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),
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Center(
|
|
||||||
child: Container(
|
|
||||||
decoration: AppStyle.boxDecoration1,
|
|
||||||
height: Get.height * .7,
|
|
||||||
width: Get.width * .9,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Image.asset(
|
|
||||||
'assets/images/logo.gif',
|
|
||||||
height: Get.width * .3,
|
|
||||||
width: Get.width * .3,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
),
|
|
||||||
Platform.isIOS && controller.isTest == 0
|
|
||||||
? Container(
|
|
||||||
decoration: AppStyle.boxDecoration,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Form(
|
|
||||||
key: controller.formKey,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
TextFormField(
|
|
||||||
keyboardType: TextInputType
|
|
||||||
.emailAddress,
|
|
||||||
controller: controller
|
|
||||||
.emailController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
focusedBorder:
|
|
||||||
OutlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
const BorderSide(
|
|
||||||
color: AppColor
|
|
||||||
.primaryColor,
|
|
||||||
width: 2.0,
|
|
||||||
),
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(
|
|
||||||
10),
|
|
||||||
),
|
|
||||||
fillColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
hoverColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
focusColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
border: const OutlineInputBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
12))),
|
|
||||||
labelText: 'Email'.tr,
|
|
||||||
hintText:
|
|
||||||
'Enter your email address'
|
|
||||||
.tr,
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value!.isEmpty ||
|
|
||||||
(!value.contains('@') ||
|
|
||||||
!value.contains(
|
|
||||||
'.'))) {
|
|
||||||
return 'Please enter Your Email.'
|
|
||||||
.tr;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
obscureText: true,
|
|
||||||
keyboardType: TextInputType
|
|
||||||
.emailAddress,
|
|
||||||
controller: controller
|
|
||||||
.passwordController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
focusedBorder:
|
|
||||||
OutlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
const BorderSide(
|
|
||||||
color: AppColor
|
|
||||||
.primaryColor,
|
|
||||||
width: 2.0,
|
|
||||||
),
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(
|
|
||||||
10),
|
|
||||||
),
|
|
||||||
fillColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
hoverColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
focusColor:
|
|
||||||
AppColor.accentColor,
|
|
||||||
border: const OutlineInputBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
12))),
|
|
||||||
labelText: 'Password'.tr,
|
|
||||||
hintText:
|
|
||||||
'Please enter your phone number.'
|
|
||||||
.tr,
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value!.isEmpty) {
|
|
||||||
return 'Please enter Your Password.'
|
|
||||||
.tr;
|
|
||||||
}
|
|
||||||
if (value.length < 6) {
|
|
||||||
return 'Password must br at least 6 character.'
|
|
||||||
.tr;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GetBuilder<LoginController>(
|
|
||||||
builder: (controller) =>
|
|
||||||
controller.isloading
|
|
||||||
? const MyCircularProgressIndicator()
|
|
||||||
: MyElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
if (controller
|
|
||||||
.formKey
|
|
||||||
.currentState!
|
|
||||||
.validate()) {
|
|
||||||
controller
|
|
||||||
.login();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title:
|
|
||||||
'Submit'.tr,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
decoration: AppStyle.boxDecoration1,
|
|
||||||
height: Get.height * .3,
|
|
||||||
width: Get.width * .8,
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'Sign in with Google for easier email and name entry'
|
|
||||||
.tr,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// MyElevatedButton(
|
|
||||||
// title: 'Sign In by Google'.tr,
|
|
||||||
// onPressed: () async {
|
|
||||||
// await GoogleSignInHelper.signInFromLogin();
|
|
||||||
// },
|
|
||||||
// kolor: AppColor.blueColor,
|
|
||||||
// ),
|
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
await GoogleSignInHelper().signInFromLogin();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 16, vertical: 10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColor.redColor,
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
FontAwesome.google,
|
|
||||||
color: AppColor.blueColor,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
'Sign In by Google'.tr,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
!Platform.isAndroid
|
|
||||||
? GestureDetector(
|
|
||||||
onTap: () async {
|
|
||||||
User? user =
|
|
||||||
await authController.signInWithApple();
|
|
||||||
if (user != null) {
|
|
||||||
box.write(BoxName.passengerID, user.uid);
|
|
||||||
box.write(BoxName.email, user.email);
|
|
||||||
await controller.loginUsingCredentials(
|
|
||||||
box
|
|
||||||
.read(BoxName.passengerID)
|
|
||||||
.toString(),
|
|
||||||
box.read(BoxName.email).toString(),
|
|
||||||
);
|
|
||||||
// Navigate to another screen or perform other actions
|
|
||||||
} else {
|
|
||||||
Get.snackbar('user not found'.tr, '',
|
|
||||||
backgroundColor: AppColor.redColor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 16, vertical: 10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black,
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.apple,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
'Sign in with Apple'.tr,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
SizedBox(
|
|
||||||
height: Get.height * .1,
|
|
||||||
),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () => Get.to(() => ContactUsPage()),
|
|
||||||
child: Text(
|
|
||||||
'If you need assistance, contact us'
|
|
||||||
.tr, // Improved wording
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Text(
|
|
||||||
// 'if you dont have account'.tr,
|
|
||||||
// style: AppStyle.subtitle,
|
|
||||||
// ),
|
|
||||||
// AnimatedTextKit(
|
|
||||||
// onTap: () => Get.to(() => SmsSignupEgypt()),
|
|
||||||
// animatedTexts: [
|
|
||||||
// TypewriterAnimatedText(
|
|
||||||
// 'Register'.tr,
|
|
||||||
// textStyle: AppStyle.headTitle2,
|
|
||||||
// speed: const Duration(milliseconds: 200),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// totalRepeatCount: 4,
|
|
||||||
// pause: const Duration(milliseconds: 200),
|
|
||||||
// displayFullTextOnTap: true,
|
|
||||||
// stopPauseOnTap: true,
|
|
||||||
// ),
|
|
||||||
// const Spacer(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 100,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Padding agreedPage() {
|
Widget _buildLoginContent(
|
||||||
return Padding(
|
LoginController controller, AuthController authController) {
|
||||||
padding: const EdgeInsets.all(16),
|
return SingleChildScrollView(
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Image.asset(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
'assets/images/logo.gif',
|
||||||
children: [
|
height: Get.width * 0.4,
|
||||||
Image.asset(
|
width: Get.width * 0.4,
|
||||||
'assets/images/notepad.png',
|
fit: BoxFit.contain,
|
||||||
width: Get.width * .2,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: Get.width * .7,
|
|
||||||
child: Text(
|
|
||||||
'Accept Ride\'s Terms & Review Privacy Notice'.tr,
|
|
||||||
style: AppStyle.headTitle2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(height: 32),
|
||||||
height: 30,
|
if (Platform.isIOS && controller.isTest == 0)
|
||||||
),
|
_buildEmailPasswordForm(controller)
|
||||||
RichText(
|
else
|
||||||
text: TextSpan(
|
Padding(
|
||||||
text:
|
padding: const EdgeInsets.only(bottom: 24.0),
|
||||||
'By selecting "I Agree" below, I have reviewed and agree to the Terms of Use and acknowledge the '
|
child: Text(
|
||||||
.tr,
|
'Sign in for a seamless experience'.tr,
|
||||||
style: AppStyle.title,
|
textAlign: TextAlign.center,
|
||||||
children: <TextSpan>[
|
style: AppStyle.subtitle,
|
||||||
TextSpan(
|
),
|
||||||
text: 'Privacy Notice'.tr,
|
),
|
||||||
style: const TextStyle(
|
InkWell(
|
||||||
decoration: TextDecoration.underline,
|
onTap: () async => await GoogleSignInHelper().signInFromLogin(),
|
||||||
color: AppColor.blueColor),
|
child: _buildSocialButton(
|
||||||
recognizer: TapGestureRecognizer()
|
icon: FontAwesome.google,
|
||||||
..onTap = () {
|
text: 'Sign In with Google'.tr,
|
||||||
Get.defaultDialog(
|
color: AppColor.redColor,
|
||||||
title: ''.tr,
|
|
||||||
content: const SizedBox(
|
|
||||||
height: 400,
|
|
||||||
width: 400,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child:
|
|
||||||
HtmlWidget(AppInformation.privacyPolicy),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}),
|
|
||||||
TextSpan(
|
|
||||||
text: '. I am at least 18 years of age.'.tr,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(height: 16),
|
||||||
height: 100,
|
if (!Platform.isAndroid)
|
||||||
),
|
GestureDetector(
|
||||||
GetBuilder<LoginController>(
|
onTap: () async {
|
||||||
builder: (controller) => Column(
|
User? user = await authController.signInWithApple();
|
||||||
children: [
|
if (user != null) {
|
||||||
Row(
|
box.write(BoxName.passengerID, user.uid);
|
||||||
children: [
|
box.write(BoxName.email, user.email);
|
||||||
Checkbox.adaptive(
|
await controller.loginUsingCredentials(
|
||||||
autofocus: true,
|
box.read(BoxName.passengerID).toString(),
|
||||||
tristate: true,
|
box.read(BoxName.email).toString(),
|
||||||
splashRadius: 25,
|
);
|
||||||
activeColor: AppColor.primaryColor,
|
} else {
|
||||||
value: controller.isAgreeTerms,
|
Get.snackbar('User not found'.tr, '',
|
||||||
onChanged: (value) => controller.changeAgreeTerm(),
|
backgroundColor: AppColor.redColor);
|
||||||
),
|
}
|
||||||
Text(
|
},
|
||||||
'I Agree'.tr,
|
child: _buildSocialButton(
|
||||||
style: controller.isAgreeTerms
|
icon: Icons.apple,
|
||||||
? AppStyle.title
|
text: 'Sign in with Apple'.tr,
|
||||||
: AppStyle.title
|
color: Colors.black,
|
||||||
.copyWith(color: AppColor.accentColor),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
MyElevatedButton(
|
|
||||||
title: 'Submit'.tr,
|
|
||||||
onPressed: () => controller.saveAgreementTerms()),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(height: 40),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Get.to(() => ContactUsPage()),
|
||||||
|
child: Text(
|
||||||
|
'Need assistance? Contact us'.tr,
|
||||||
|
style: AppStyle.subtitle.copyWith(color: Colors.grey),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
locationPermissionDialog() {
|
Widget _buildSocialButton({
|
||||||
return GetBuilder<LoginController>(builder: (controller) {
|
required IconData icon,
|
||||||
return Padding(
|
required String text,
|
||||||
padding: const EdgeInsets.all(16),
|
required Color color,
|
||||||
child: Container(
|
}) {
|
||||||
height: Get.height * .4,
|
return Container(
|
||||||
decoration: AppStyle.boxDecoration1,
|
padding: const EdgeInsets.all(12),
|
||||||
child: Padding(
|
decoration: BoxDecoration(
|
||||||
padding: const EdgeInsets.all(20.0),
|
color: color,
|
||||||
child: Center(
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Icon(icon, color: Colors.white),
|
||||||
'We use your precise location to find the nearest available driver and provide accurate pickup and dropoff information. You can manage this in Settings.'
|
const SizedBox(width: 12),
|
||||||
.tr,
|
Text(
|
||||||
textAlign: TextAlign.center,
|
text,
|
||||||
style: AppStyle.title,
|
style: const TextStyle(
|
||||||
),
|
color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
TextButton(
|
),
|
||||||
onPressed: () {
|
],
|
||||||
// Optionally, navigate to app settings for manual permission control
|
),
|
||||||
openAppSettings();
|
);
|
||||||
},
|
}
|
||||||
child: Text(
|
|
||||||
"Open Settings".tr,
|
Widget _buildEmailPasswordForm(LoginController controller) {
|
||||||
style: const TextStyle(color: AppColor.blueColor),
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.grey.withOpacity(0.2),
|
||||||
|
spreadRadius: 2,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: const Offset(0, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Form(
|
||||||
|
key: controller.formKey,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
controller: controller.emailController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Email'.tr,
|
||||||
|
hintText: 'Your email address'.tr,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
validator: (value) => value == null ||
|
||||||
|
value.isEmpty ||
|
||||||
|
!value.contains('@') ||
|
||||||
|
!value.contains('.')
|
||||||
|
? 'Enter a valid email'.tr
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextFormField(
|
||||||
|
obscureText: true,
|
||||||
|
controller: controller.passwordController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Password'.tr,
|
||||||
|
hintText: 'Your password'.tr,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
validator: (value) => value == null || value.isEmpty
|
||||||
|
? 'Enter your password'.tr
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
GetBuilder<LoginController>(
|
||||||
|
builder: (controller) => controller.isloading
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (controller.formKey.currentState!.validate()) {
|
||||||
|
controller.login();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('Submit'.tr),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
MyElevatedButton(
|
],
|
||||||
title: 'Next'.tr,
|
),
|
||||||
onPressed: () async {
|
),
|
||||||
// if (box.read(BoxName.locationPermission) != 'true') {
|
);
|
||||||
// Get.put(MyDialog()).getDialog(
|
}
|
||||||
// 'Location Permission is requiered for find drivers'
|
|
||||||
// .tr,
|
Widget _buildAgreementPage(LoginController controller) {
|
||||||
// 'You can just manage your account!'.tr, () {
|
return Padding(
|
||||||
// Get.back();
|
padding: const EdgeInsets.all(16),
|
||||||
// Get.to(() {
|
child: Column(
|
||||||
// PassengerProfilePage();
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// });
|
children: [
|
||||||
// });
|
ListTile(
|
||||||
// } else {
|
leading: Image.asset('assets/images/notepad.png', width: 40),
|
||||||
await controller.getLocationPermission();
|
title: Text('Terms of Use & Privacy Notice'.tr,
|
||||||
// }
|
style: AppStyle.headTitle2),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
RichText(
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
text: TextSpan(
|
||||||
|
style: AppStyle.title,
|
||||||
|
children: <TextSpan>[
|
||||||
|
TextSpan(
|
||||||
|
text:
|
||||||
|
'By selecting "I Agree" below, I confirm that I have read and agree to the '
|
||||||
|
.tr),
|
||||||
|
TextSpan(
|
||||||
|
text: 'Terms of Use'.tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
color: AppColor.blueColor),
|
||||||
|
),
|
||||||
|
const TextSpan(text: ' and acknowledge the '),
|
||||||
|
TextSpan(
|
||||||
|
text: 'Privacy Notice'.tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
color: AppColor.blueColor),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
Get.defaultDialog(
|
||||||
|
title: 'Privacy Notice'.tr,
|
||||||
|
content: const SizedBox(
|
||||||
|
height: 400,
|
||||||
|
width: 400,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: HtmlWidget(AppInformation.privacyPolicy),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
kolor: AppColor.greenColor,
|
),
|
||||||
)
|
TextSpan(text: '. I am at least 18 years old.'.tr),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: controller.isAgreeTerms,
|
||||||
|
onChanged: (newValue) => controller.changeAgreeTerm(),
|
||||||
|
activeColor: AppColor.primaryColor,
|
||||||
|
),
|
||||||
|
Text('I Agree'.tr, style: AppStyle.title),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: controller.isAgreeTerms
|
||||||
|
? () => controller.saveAgreementTerms()
|
||||||
|
: null,
|
||||||
|
child: Text('Continue'.tr),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
});
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildLocationPermissionDialog(LoginController controller) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(32),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.location_on, size: 60, color: AppColor.primaryColor),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'Enable Location Access'.tr,
|
||||||
|
style: AppStyle.headTitle2,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
'We need your location to find nearby drivers for pickups and drop-offs.'
|
||||||
|
.tr,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: AppStyle.title,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async => await controller.getLocationPermission(),
|
||||||
|
child: Text('Allow Location Access'.tr),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => openAppSettings(),
|
||||||
|
child: Text('Open Settings'.tr),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCountryPicker() {
|
||||||
|
return CountryPicker();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
|
boxShadow: [BoxShadow(blurRadius: 10, color: Colors.black12)],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
_buildPriceInfo(context, controller),
|
||||||
onTap: () {
|
const SizedBox(height: 16),
|
||||||
if (box.read(BoxName.carType) == 'Speed' ||
|
_buildDriverInfoCard(context, controller, _parseColor),
|
||||||
box.read(BoxName.carType) == 'Awfar Car' ||
|
|
||||||
box.read(BoxName.carType) == 'Delivery') {
|
|
||||||
Get.snackbar(
|
|
||||||
'This price is'.tr +
|
|
||||||
' ${controller.totalPassenger.toStringAsFixed(2)}'
|
|
||||||
.tr,
|
|
||||||
'This ride type does not allow changes to the destination or additional stops'
|
|
||||||
.tr,
|
|
||||||
snackPosition: SnackPosition.BOTTOM,
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
backgroundColor: AppColor.yellowColor,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Get.snackbar(
|
|
||||||
'This price may be changed'.tr,
|
|
||||||
'This ride type allows changes, but the price may increase'
|
|
||||||
.tr,
|
|
||||||
snackPosition: SnackPosition.BOTTOM,
|
|
||||||
duration: const Duration(seconds: 2),
|
|
||||||
backgroundColor: AppColor.yellowColor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: '${'The driver accept your order for'.tr} ',
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: controller.totalPassenger.toStringAsFixed(2),
|
|
||||||
style: AppStyle.title.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
// fontSize: 22,
|
|
||||||
color: AppColor.redColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: ' ${'LE'.tr}',
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: Get.height * .31,
|
|
||||||
width: Get.width * .9,
|
|
||||||
decoration: AppStyle.boxDecoration,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
// 'Comfort',
|
|
||||||
box.read(BoxName.carType
|
|
||||||
.toString()), //car type fro box after selected
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
// ColorFiltered(
|
|
||||||
// colorFilter: ColorFilter.mode(
|
|
||||||
// _parseColor(controller.colorHex),
|
|
||||||
// BlendMode.srcIn,
|
|
||||||
// ),
|
|
||||||
// child: Image.asset(
|
|
||||||
// box.read(BoxName.carType) == 'Comfort'
|
|
||||||
// ? 'assets/images/blob.png'
|
|
||||||
// : box.read(BoxName.carType) == 'Lady'
|
|
||||||
// ? 'assets/images/lady.png' // Assuming there's an image for Lady
|
|
||||||
// : box.read(BoxName.carType) == 'Speed'
|
|
||||||
// ? 'assets/images/carspeed.png'
|
|
||||||
// : box.read(BoxName.carType) ==
|
|
||||||
// 'Scooter'
|
|
||||||
// ? 'assets/images/moto.png'
|
|
||||||
// : box.read(BoxName.carType) ==
|
|
||||||
// 'Mishwar Vip'
|
|
||||||
// ? 'assets/images/freeRide.png'
|
|
||||||
// : box.read(BoxName
|
|
||||||
// .carType) ==
|
|
||||||
// 'Awfar Car'
|
|
||||||
// ? 'assets/images/balash.png'
|
|
||||||
// : box.read(BoxName
|
|
||||||
// .carType) ==
|
|
||||||
// 'Pink Bike'
|
|
||||||
// ? 'assets/images/pinkBike.png'
|
|
||||||
// : box.read(BoxName
|
|
||||||
// .carType) ==
|
|
||||||
// 'Rayeh Gai'
|
|
||||||
// ? 'assets/images/roundtrip.png'
|
|
||||||
// : 'assets/images/carspeed.png', // Default image if none of the above
|
|
||||||
// width: 80,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
// 'Toyota Camry',
|
|
||||||
controller.model.toString(),
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
// 'ر ل 2323',
|
|
||||||
controller.licensePlate.toString(),
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
// 'Black',
|
|
||||||
controller.carColor.toString(),
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
ColorFiltered(
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
_parseColor(controller.colorHex),
|
|
||||||
BlendMode.srcIn,
|
|
||||||
),
|
|
||||||
child: Image.asset(
|
|
||||||
box.read(BoxName.carType) == 'Scooter' ||
|
|
||||||
box.read(BoxName.carType) ==
|
|
||||||
'Pink Bike'
|
|
||||||
? 'assets/images/moto.png'
|
|
||||||
: 'assets/images/car3.png',
|
|
||||||
width: 80,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
CircleAvatar(
|
|
||||||
radius: 25,
|
|
||||||
backgroundImage: NetworkImage(
|
|
||||||
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg',
|
|
||||||
),
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
return Image.network(
|
|
||||||
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg',
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
loadingBuilder: (BuildContext context,
|
|
||||||
Widget child,
|
|
||||||
ImageChunkEvent? loadingProgress) {
|
|
||||||
if (loadingProgress == null) {
|
|
||||||
return child; // Image is loaded
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
value: loadingProgress
|
|
||||||
.expectedTotalBytes !=
|
|
||||||
null
|
|
||||||
? loadingProgress
|
|
||||||
.cumulativeBytesLoaded /
|
|
||||||
(loadingProgress
|
|
||||||
.expectedTotalBytes ??
|
|
||||||
1)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
errorBuilder: (BuildContext context,
|
|
||||||
Object error,
|
|
||||||
StackTrace? stackTrace) {
|
|
||||||
return const Icon(
|
|
||||||
Icons
|
|
||||||
.person, // Icon to show when image fails to load
|
|
||||||
size:
|
|
||||||
25, // Adjust the size as needed
|
|
||||||
color: AppColor
|
|
||||||
.blueColor, // Color for the error icon
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
// 'fadi ahmad',
|
|
||||||
controller.driverName,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
// '⭐ 4.8',
|
|
||||||
'⭐ ${controller.driverRate}',
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title: 'Select one message',
|
|
||||||
titleStyle: AppStyle.title,
|
|
||||||
content: SizedBox(
|
|
||||||
width: 300,
|
|
||||||
height: Get.height * .5,
|
|
||||||
child: ListView(
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
FirebaseMessagesController()
|
|
||||||
.sendNotificationToDriverMAP(
|
|
||||||
'message From passenger',
|
|
||||||
'Hello, I\'m at the agreed-upon location'
|
|
||||||
.tr,
|
|
||||||
controller.driverToken
|
|
||||||
.toString(),
|
|
||||||
[],
|
|
||||||
'ding.wav',
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration:
|
|
||||||
AppStyle.boxDecoration,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.all(
|
|
||||||
10),
|
|
||||||
child: Text(
|
|
||||||
'Hello, I\'m at the agreed-upon location'
|
|
||||||
.tr,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
FirebaseMessagesController()
|
|
||||||
.sendNotificationToDriverMAP(
|
|
||||||
'message From passenger',
|
|
||||||
'My location is correct. You can search for me using the navigation app'
|
|
||||||
.tr,
|
|
||||||
controller.driverToken,
|
|
||||||
[],
|
|
||||||
'ding.wav',
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration:
|
|
||||||
AppStyle.boxDecoration,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.all(
|
|
||||||
10),
|
|
||||||
child: Text(
|
|
||||||
'My location is correct. You can search for me using the navigation app'
|
|
||||||
.tr,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
FirebaseMessagesController()
|
|
||||||
.sendNotificationToDriverMAP(
|
|
||||||
'message From passenger',
|
|
||||||
'My location is correct. You can search for me using the navigation app'
|
|
||||||
.tr,
|
|
||||||
controller.driverToken,
|
|
||||||
[],
|
|
||||||
'ding.wav',
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration:
|
|
||||||
AppStyle.boxDecoration,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.all(
|
|
||||||
10),
|
|
||||||
child: Text(
|
|
||||||
'I\'m waiting for you'.tr,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
FirebaseMessagesController()
|
|
||||||
.sendNotificationToDriverMAP(
|
|
||||||
'message From passenger',
|
|
||||||
"How much longer will you be?"
|
|
||||||
.tr,
|
|
||||||
controller.driverToken,
|
|
||||||
[],
|
|
||||||
'ding.wav',
|
|
||||||
);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration:
|
|
||||||
AppStyle.boxDecoration,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.all(
|
|
||||||
10),
|
|
||||||
child: Text(
|
|
||||||
"How much longer will you be?"
|
|
||||||
.tr,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 190,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Form(
|
|
||||||
key: controller
|
|
||||||
.messagesFormKey,
|
|
||||||
child: SizedBox(
|
|
||||||
width: 160,
|
|
||||||
child: MyTextForm(
|
|
||||||
controller: controller
|
|
||||||
.messageToDriver,
|
|
||||||
label:
|
|
||||||
'Type Any thing'
|
|
||||||
.tr,
|
|
||||||
hint:
|
|
||||||
'Type Any thing'
|
|
||||||
.tr,
|
|
||||||
type:
|
|
||||||
TextInputType
|
|
||||||
.name),
|
|
||||||
)),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
FirebaseMessagesController()
|
|
||||||
.sendNotificationToDriverMAP(
|
|
||||||
'message From passenger',
|
|
||||||
controller
|
|
||||||
.messageToDriver
|
|
||||||
.text,
|
|
||||||
controller
|
|
||||||
.driverToken,
|
|
||||||
[],
|
|
||||||
'ding.wav');
|
|
||||||
controller
|
|
||||||
.messageToDriver
|
|
||||||
.clear();
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.send))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.message,
|
|
||||||
color: AppColor.blueColor,
|
|
||||||
size: 35,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
HapticFeedback.heavyImpact();
|
|
||||||
// Get.to(() => const CallPage());
|
|
||||||
// Get.to(() => PassengerCallPage());
|
|
||||||
makePhoneCall(controller.driverPhone);
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.call,
|
|
||||||
color: AppColor.greenColor,
|
|
||||||
size: 35,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
controller.isDriverArrivePassenger
|
|
||||||
? const DriverArrivePassengerAndWaitMinute()
|
|
||||||
: const TimeDriverToPassenger()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 10,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -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,
|
|
||||||
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
|
|
||||||
? AppColor.redColor
|
|
||||||
: AppColor.greenColor,
|
|
||||||
minHeight: 25,
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(15),
|
||||||
value:
|
child: LinearProgressIndicator(
|
||||||
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
|
backgroundColor: AppColor.accentColor.withOpacity(0.3),
|
||||||
|
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
|
||||||
|
? AppColor.redColor
|
||||||
|
: AppColor.greenColor,
|
||||||
|
minHeight: 20,
|
||||||
|
value:
|
||||||
|
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Row(
|
const SizedBox(height: 4),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Center(
|
||||||
children: [
|
child: Text.rich(
|
||||||
Text(
|
TextSpan(
|
||||||
'The driver waiting you in picked location .'.tr,
|
children: [
|
||||||
style: AppStyle.subtitle,
|
TextSpan(
|
||||||
textAlign: TextAlign.center,
|
text: '${'Driver is waiting at pickup.'.tr} ',
|
||||||
|
style: AppStyle.subtitle),
|
||||||
|
TextSpan(
|
||||||
|
text: controller
|
||||||
|
.stringRemainingTimeDriverWaitPassenger5Minute,
|
||||||
|
style: AppStyle.title),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
textAlign: TextAlign.center,
|
||||||
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,
|
children: [
|
||||||
child: Padding(
|
ClipRRect(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
|
borderRadius: BorderRadius.circular(15),
|
||||||
child: Stack(
|
child: LinearProgressIndicator(
|
||||||
children: [
|
backgroundColor: AppColor.accentColor.withOpacity(0.3),
|
||||||
Container(
|
color: controller
|
||||||
decoration: AppStyle.boxDecoration,
|
.remainingTimeToPassengerFromDriverAfterApplied <
|
||||||
width: Get.width * .7,
|
60
|
||||||
height: 15,
|
? AppColor.redColor
|
||||||
// color: AppColor.yellowColor,
|
: AppColor.greenColor,
|
||||||
),
|
minHeight: 20,
|
||||||
Stack(
|
value: controller
|
||||||
|
.progressTimerToPassengerFromDriverAfterApplied
|
||||||
|
.toDouble()
|
||||||
|
.clamp(0.0, 1.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Center(
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
LinearProgressIndicator(
|
TextSpan(
|
||||||
backgroundColor: AppColor.accentColor,
|
text: '${'Driver is on the way'.tr} ',
|
||||||
color: controller
|
style: AppStyle.subtitle,
|
||||||
.remainingTimeToPassengerFromDriverAfterApplied <
|
),
|
||||||
60
|
TextSpan(
|
||||||
? AppColor.redColor
|
text: controller.stringRemainingTimeToPassenger,
|
||||||
: AppColor.greenColor,
|
style: AppStyle.title,
|
||||||
minHeight: 25,
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
|
||||||
value: () {
|
|
||||||
// Ensure valid value between 0.0 and 1.0
|
|
||||||
double progress = controller
|
|
||||||
.progressTimerToPassengerFromDriverAfterApplied
|
|
||||||
.toDouble();
|
|
||||||
if (progress.isNaN || progress.isInfinite) {
|
|
||||||
// Handle invalid progress (e.g., set to 0.0)
|
|
||||||
return 0.0;
|
|
||||||
} else {
|
|
||||||
return progress.clamp(
|
|
||||||
0.0, 1.0); // Clamp to valid range
|
|
||||||
}
|
|
||||||
}(),
|
|
||||||
),
|
),
|
||||||
Center(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'The driver on your way'.tr,
|
|
||||||
style: AppStyle.title
|
|
||||||
.copyWith(color: AppColor.yellowColor),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 20,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
controller.stringRemainingTimeToPassenger,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
)
|
)
|
||||||
: const SizedBox();
|
: const SizedBox();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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,73 +472,101 @@ 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) {
|
|
||||||
blinkingController.startBlinking();
|
return showPromoButton
|
||||||
return Positioned(
|
? GetBuilder<BlinkingController>(
|
||||||
right: 5,
|
builder: (blinkingController) {
|
||||||
bottom: Get.height * 0.36,
|
blinkingController.startBlinking();
|
||||||
child: Obx(() {
|
return Positioned(
|
||||||
return AnimatedContainer(
|
right: 16, // Adjusted from 5 for better spacing
|
||||||
duration: const Duration(milliseconds: 500),
|
bottom: Get.height * 0.36,
|
||||||
width: 70, // Circle size
|
child: InkWell(
|
||||||
height: 70,
|
onTap: () {
|
||||||
decoration: BoxDecoration(
|
Get.defaultDialog(
|
||||||
shape: BoxShape.circle,
|
title: 'Apply Promo Code'.tr, // More engaging title
|
||||||
color: blinkingController.isLightOn.value
|
content: Padding(
|
||||||
? Colors.yellow
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
: Colors.grey, // Light on/off effect
|
child: Form(
|
||||||
border: Border.all(
|
key: mapPassengerController.promoFormKey,
|
||||||
color: blinkingController
|
child: MyTextForm(
|
||||||
.borderColor.value, // Animated border color
|
controller: mapPassengerController.promo,
|
||||||
width: 3,
|
label: 'Promo Code'.tr, // Shortened label
|
||||||
),
|
hint: 'Enter your promo code'
|
||||||
),
|
.tr, // More friendly hint
|
||||||
child: IconButton(
|
type: TextInputType.name,
|
||||||
onPressed: () {
|
// style: AppStyle.normalTextBlack, // Apply consistent style
|
||||||
Get.defaultDialog(
|
|
||||||
title: 'Insert Your Promo Code'.tr,
|
|
||||||
content: Form(
|
|
||||||
key: mapPassengerController.promoFormKey,
|
|
||||||
child: MyTextForm(
|
|
||||||
controller: mapPassengerController.promo,
|
|
||||||
label: 'Insert Your Promo Code'.tr,
|
|
||||||
hint: 'Enter promo code here'.tr,
|
|
||||||
type: TextInputType.name,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
confirm: MyElevatedButton(
|
),
|
||||||
title: 'Ok'.tr,
|
),
|
||||||
onPressed: () {
|
confirm: MyElevatedButton(
|
||||||
if (mapPassengerController
|
title: 'Apply'.tr, // Shortened button title
|
||||||
.promoFormKey.currentState!
|
onPressed: () {
|
||||||
.validate()) {
|
if (mapPassengerController
|
||||||
mapPassengerController
|
.promoFormKey.currentState!
|
||||||
.applyPromoCodeToPassenger(context);
|
.validate()) {
|
||||||
Get.back();
|
mapPassengerController
|
||||||
}
|
.applyPromoCodeToPassenger(context);
|
||||||
}));
|
Get.back();
|
||||||
},
|
}
|
||||||
icon: const Column(
|
},
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
),
|
||||||
children: [
|
cancel: OutlinedButton(
|
||||||
Icon(Icons.local_offer, size: 24), // Promo icon
|
onPressed: () => Get.back(),
|
||||||
SizedBox(height: 4),
|
child: Text('Cancel'.tr),
|
||||||
Text(
|
),
|
||||||
"Promo",
|
);
|
||||||
style: TextStyle(
|
},
|
||||||
fontSize: 12, fontWeight: FontWeight.bold),
|
child: Container(
|
||||||
|
width: 60, // Slightly smaller for a cleaner look
|
||||||
|
height: 60,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: Colors.white, // Solid white background
|
||||||
|
border: Border.all(
|
||||||
|
color: blinkingController.borderColor.value,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 5,
|
||||||
|
spreadRadius: 2,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.local_offer,
|
||||||
|
size: 24,
|
||||||
|
color: blinkingController.isLightOn.value
|
||||||
|
? Colors.orange
|
||||||
|
: Colors
|
||||||
|
.grey.shade600, // Distinct promo color
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
"Promo".tr,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}),
|
);
|
||||||
);
|
},
|
||||||
})
|
)
|
||||||
: const SizedBox();
|
: const SizedBox();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -559,51 +581,89 @@ 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,
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.warning_amber_rounded,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
TextSpan(
|
||||||
onPressed: () async => await Get.find<
|
text: '${'Negative Balance:'.tr} ',
|
||||||
TextToSpeechController>()
|
style: AppStyle.subtitle.copyWith(
|
||||||
.speakText('you have a negative balance of'
|
color: Colors.white,
|
||||||
.tr +
|
fontWeight: FontWeight.bold,
|
||||||
'${passengerWallet.toStringAsFixed(2)}'
|
),
|
||||||
' in your'
|
),
|
||||||
.tr +
|
TextSpan(
|
||||||
' ${AppInformation.appName}'
|
text:
|
||||||
' wallet due to a previous trip.'
|
'${'You have a balance of'.tr} ${passengerWallet.toStringAsFixed(2)} ${box.read(BoxName.countryCode) == 'Egypt' ? 'LE'.tr : 'JOD'.tr} ${'due to a previous trip.'.tr}',
|
||||||
.tr),
|
style: AppStyle.subtitle.copyWith(
|
||||||
icon: const Icon(Icons.headphones)),
|
color: Colors.white,
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
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();
|
||||||
|
|||||||
@@ -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');
|
||||||
@@ -20,349 +19,271 @@ GetBuilder<MapPassengerController> formSearchPlacesDestenation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return GetBuilder<MapPassengerController>(
|
return GetBuilder<MapPassengerController>(
|
||||||
builder: (controller) => Column(
|
builder: (controller) => Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Expanded(
|
||||||
padding: const EdgeInsets.all(6),
|
child: TextFormField(
|
||||||
child: Column(
|
controller: controller.placeDestinationController,
|
||||||
children: [
|
onChanged: (value) {
|
||||||
Container(
|
if (controller.placeDestinationController.text.length > 2) {
|
||||||
width: Get.width * .9,
|
controller.getPlaces();
|
||||||
height: 40,
|
controller.changeHeightPlaces();
|
||||||
decoration:
|
} else if (controller
|
||||||
const BoxDecoration(color: AppColor.secondaryColor),
|
.placeDestinationController.text.isEmpty) {
|
||||||
child: TextField(
|
controller.clearPlacesDestination();
|
||||||
decoration: InputDecoration(
|
controller.changeHeightPlaces();
|
||||||
border: const OutlineInputBorder(
|
}
|
||||||
borderRadius: BorderRadius.only(),
|
},
|
||||||
gapPadding: 4,
|
decoration: InputDecoration(
|
||||||
borderSide: BorderSide(
|
hintText: controller.hintTextDestinationPoint,
|
||||||
color: AppColor.redColor,
|
hintStyle:
|
||||||
width: 2,
|
AppStyle.subtitle.copyWith(color: Colors.grey[600]),
|
||||||
)),
|
prefixIcon:
|
||||||
suffixIcon: const Icon(Icons.search),
|
const Icon(Icons.search, color: AppColor.primaryColor),
|
||||||
hintText: controller.hintTextDestinationPoint,
|
suffixIcon: controller
|
||||||
hintStyle: AppStyle.title,
|
.placeDestinationController.text.isNotEmpty
|
||||||
hintMaxLines: 1,
|
? IconButton(
|
||||||
prefixIcon: IconButton(
|
icon: Icon(Icons.clear, color: Colors.grey[400]),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
controller.placeDestinationController.clear();
|
controller.placeDestinationController.clear();
|
||||||
controller.clearPlacesDestination();
|
controller.clearPlacesDestination();
|
||||||
|
controller.changeHeightPlaces();
|
||||||
},
|
},
|
||||||
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),
|
||||||
controller: controller.placeDestinationController,
|
borderSide: BorderSide.none,
|
||||||
onChanged: (value) {
|
|
||||||
if (controller
|
|
||||||
.placeDestinationController.text.length >
|
|
||||||
5) {
|
|
||||||
controller.getPlaces();
|
|
||||||
controller.changeHeightPlaces();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// onEditingComplete: () => controller.changeHeight(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
focusedBorder: OutlineInputBorder(
|
||||||
height: 10,
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(color: AppColor.primaryColor),
|
||||||
),
|
),
|
||||||
Container(
|
filled: true,
|
||||||
decoration: AppStyle.boxDecoration1
|
fillColor: Colors.grey[50],
|
||||||
.copyWith(color: AppColor.blueColor),
|
),
|
||||||
child: InkWell(
|
),
|
||||||
onTap: () {
|
),
|
||||||
controller.changeMainBottomMenuMap();
|
const SizedBox(width: 8.0),
|
||||||
controller.changePickerShown();
|
IconButton(
|
||||||
},
|
onPressed: () {
|
||||||
child: Padding(
|
controller.changeMainBottomMenuMap();
|
||||||
padding: const EdgeInsets.symmetric(
|
controller.changePickerShown();
|
||||||
horizontal: 20, vertical: 4),
|
},
|
||||||
child: Text(
|
icon: Icon(Icons.location_on_outlined,
|
||||||
controller.isAnotherOreder
|
color: AppColor.accentColor, size: 30),
|
||||||
? 'Pick from map destination'.tr
|
tooltip: controller.isAnotherOreder
|
||||||
: 'Pick from map'.tr,
|
? 'Pick destination on map'
|
||||||
style: AppStyle.title
|
: 'Pick on map',
|
||||||
.copyWith(color: AppColor.secondaryColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
if (box.read(BoxName.addWork) == 'addWork') {
|
|
||||||
controller.workLocationFromMap = true;
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.changePickerShown();
|
|
||||||
} else {
|
|
||||||
controller.hintTextDestinationPoint = 'To Work';
|
|
||||||
final latLng = LatLng(
|
|
||||||
double.parse(
|
|
||||||
box.read(BoxName.addWork).split(',')[0]),
|
|
||||||
double.parse(
|
|
||||||
box.read(BoxName.addWork).split(',')[1]),
|
|
||||||
);
|
|
||||||
controller.newMyLocation =
|
|
||||||
controller.newStartPointLocation;
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
|
|
||||||
await controller.getDirectionMap(
|
|
||||||
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
|
|
||||||
'${latLng.latitude},${latLng.longitude}',
|
|
||||||
);
|
|
||||||
controller.currentLocationToFormPlaces = false;
|
|
||||||
controller.placesDestination = [];
|
|
||||||
// controller.isCancelRidePageShown = true;
|
|
||||||
controller.clearPlacesStart();
|
|
||||||
controller.clearPlacesDestination();
|
|
||||||
controller.passengerStartLocationFromMap =
|
|
||||||
false;
|
|
||||||
controller.isPickerShown = false;
|
|
||||||
controller.bottomSheet();
|
|
||||||
controller.showBottomSheet1();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLongPress: () {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title:
|
|
||||||
'Do you want to change Work location'.tr,
|
|
||||||
middleText: '',
|
|
||||||
confirm: MyElevatedButton(
|
|
||||||
title: 'Yes'.tr,
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
controller.workLocationFromMap = true;
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.changePickerShown();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
width: Get.width * .25,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColor.blueColor.withOpacity(.4),
|
|
||||||
border: Border.all()),
|
|
||||||
child: Text(
|
|
||||||
' ${box.read(BoxName.addWork)}' == 'addWork'
|
|
||||||
? 'Add Work'.tr
|
|
||||||
: 'To Work'.tr,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onLongPress: () {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title:
|
|
||||||
'Do you want to change Home location'.tr,
|
|
||||||
middleText: '',
|
|
||||||
confirm: MyElevatedButton(
|
|
||||||
title: 'Yes'.tr,
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
controller.homeLocationFromMap = true;
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.changePickerShown();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
onTap: () async {
|
|
||||||
if (box.read(BoxName.addHome) == 'addHome') {
|
|
||||||
controller.homeLocationFromMap = true;
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.changePickerShown();
|
|
||||||
} else {
|
|
||||||
controller.hintTextDestinationPoint = 'To Home';
|
|
||||||
final latLng = LatLng(
|
|
||||||
double.parse(
|
|
||||||
box.read(BoxName.addHome).split(',')[0]),
|
|
||||||
double.parse(
|
|
||||||
box.read(BoxName.addHome).split(',')[1]),
|
|
||||||
);
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
|
|
||||||
// controller.newMyLocation = latLng;
|
|
||||||
await controller.getDirectionMap(
|
|
||||||
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
|
|
||||||
'${latLng.latitude},${latLng.longitude}',
|
|
||||||
);
|
|
||||||
controller.currentLocationToFormPlaces = false;
|
|
||||||
controller.placesDestination = [];
|
|
||||||
// controller.isCancelRidePageShown = true;
|
|
||||||
controller.clearPlacesStart();
|
|
||||||
controller.clearPlacesDestination();
|
|
||||||
controller.passengerStartLocationFromMap =
|
|
||||||
false;
|
|
||||||
controller.isPickerShown = false;
|
|
||||||
// controller.showBottomSheet1();
|
|
||||||
// Get.back();
|
|
||||||
controller.showBottomSheet1();
|
|
||||||
// controller.newMyLocation = latLng;
|
|
||||||
controller.update();
|
|
||||||
controller.update();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
width: Get.width * .25,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColor.blueColor.withOpacity(.4),
|
|
||||||
border: Border.all()),
|
|
||||||
child: Text(
|
|
||||||
style: AppStyle.title,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
'${box.read(BoxName.addHome) == 'addHome' ? 'Add Home'.tr : "To Home".tr} '),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
), //
|
|
||||||
),
|
),
|
||||||
// controller.placesDestination.isEmpty
|
|
||||||
// ? InkWell(
|
|
||||||
// onTap: () {
|
|
||||||
// controller.changeMainBottomMenuMap();
|
|
||||||
// controller.changePickerShown();
|
|
||||||
// },
|
|
||||||
// child: Text(
|
|
||||||
// 'Choose from Map'.tr,
|
|
||||||
// style:
|
|
||||||
// AppStyle.title.copyWith(color: AppColor.blueColor),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// : const SizedBox(),
|
|
||||||
Container(
|
|
||||||
height: controller.placesDestination.isNotEmpty
|
|
||||||
? controller.height
|
|
||||||
: 0,
|
|
||||||
color: AppColor.secondaryColor,
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: controller.placesDestination.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
var res = controller.placesDestination[index];
|
|
||||||
|
|
||||||
// Extract fields with null safety
|
|
||||||
var title = res['title']?.toString() ?? 'Unknown Place';
|
|
||||||
var position = res['position'];
|
|
||||||
var latitude = position?['lat'];
|
|
||||||
var longitude = position?['lng'];
|
|
||||||
var address =
|
|
||||||
res['address']?['label'] ?? 'Unknown Address';
|
|
||||||
var categories = res['categories'] ?? [];
|
|
||||||
var primaryCategory = categories.isNotEmpty
|
|
||||||
? categories[0]['name']
|
|
||||||
: 'Unknown Category';
|
|
||||||
|
|
||||||
return InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
if (latitude != null && longitude != null) {
|
|
||||||
sql.insertMapLocation({
|
|
||||||
'latitude': latitude,
|
|
||||||
'longitude': longitude,
|
|
||||||
'name': title,
|
|
||||||
'rate': 'N/A',
|
|
||||||
'createdAt': DateTime.now().toIso8601String(),
|
|
||||||
// No rating in this structure, adjust as needed
|
|
||||||
}, TableName.recentLocations);
|
|
||||||
|
|
||||||
controller.passengerLocation =
|
|
||||||
controller.newMyLocation;
|
|
||||||
controller.myDestination =
|
|
||||||
LatLng(latitude, longitude);
|
|
||||||
controller
|
|
||||||
.convertHintTextDestinationNewPlaces(index);
|
|
||||||
|
|
||||||
controller.placesDestination = [];
|
|
||||||
controller.placeDestinationController.clear();
|
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.passengerStartLocationFromMap = true;
|
|
||||||
controller.isPickerShown = true;
|
|
||||||
} else {
|
|
||||||
Toast.show(
|
|
||||||
context,
|
|
||||||
'Invalid location data',
|
|
||||||
AppColor.redColor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.place,
|
|
||||||
size: 20), // Fallback icon for places
|
|
||||||
IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
if (latitude != null &&
|
|
||||||
longitude != null) {
|
|
||||||
await sql.insertMapLocation({
|
|
||||||
'latitude': latitude,
|
|
||||||
'longitude': longitude,
|
|
||||||
'name': title,
|
|
||||||
'rate': 'N/A',
|
|
||||||
}, TableName.placesFavorite);
|
|
||||||
Toast.show(
|
|
||||||
context,
|
|
||||||
'$title ${'Saved Successfully'.tr}',
|
|
||||||
AppColor.primaryColor,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Toast.show(
|
|
||||||
context,
|
|
||||||
'Invalid location data',
|
|
||||||
AppColor.redColor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.favorite_border),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
address,
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
primaryCategory,
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Divider(thickness: 1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
))
|
|
||||||
],
|
],
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
_buildQuickActionButton(
|
||||||
|
icon: Icons.work_outline,
|
||||||
|
text: box.read(BoxName.addWork) == 'addWork'
|
||||||
|
? 'Add Work'.tr
|
||||||
|
: 'To Work'.tr,
|
||||||
|
onTap: () async {
|
||||||
|
if (box.read(BoxName.addWork) == 'addWork') {
|
||||||
|
controller.workLocationFromMap = true;
|
||||||
|
controller.changeMainBottomMenuMap();
|
||||||
|
controller.changePickerShown();
|
||||||
|
} else {
|
||||||
|
_handleQuickAction(controller, BoxName.addWork, 'To Work');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongPress: () =>
|
||||||
|
_showChangeLocationDialog(controller, 'Work'),
|
||||||
|
),
|
||||||
|
_buildQuickActionButton(
|
||||||
|
icon: Icons.home_outlined,
|
||||||
|
text: box.read(BoxName.addHome) == 'addHome'
|
||||||
|
? 'Add Home'.tr
|
||||||
|
: 'To Home'.tr,
|
||||||
|
onTap: () async {
|
||||||
|
if (box.read(BoxName.addHome) == 'addHome') {
|
||||||
|
controller.homeLocationFromMap = true;
|
||||||
|
controller.changeMainBottomMenuMap();
|
||||||
|
controller.changePickerShown();
|
||||||
|
} else {
|
||||||
|
_handleQuickAction(controller, BoxName.addHome, 'To Home');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongPress: () =>
|
||||||
|
_showChangeLocationDialog(controller, 'Home'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
height:
|
||||||
|
controller.placesDestination.isNotEmpty ? controller.height : 0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: ListView.separated(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: controller.placesDestination.length,
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
const Divider(height: 1, color: Colors.grey),
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
var res = controller.placesDestination[index];
|
||||||
|
var title = res['title']?.toString() ?? 'Unknown Place';
|
||||||
|
var position = res['position'];
|
||||||
|
var latitude = position?['lat'];
|
||||||
|
var longitude = position?['lng'];
|
||||||
|
var address = res['address']?['label'] ?? 'Unknown Address';
|
||||||
|
var categories = res['categories'] ?? [];
|
||||||
|
var primaryCategory = categories.isNotEmpty
|
||||||
|
? categories[0]['name']
|
||||||
|
: 'Unknown Category';
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
leading: const Icon(Icons.place, size: 30, color: Colors.grey),
|
||||||
|
title: Text(title,
|
||||||
|
style: AppStyle.subtitle
|
||||||
|
.copyWith(fontWeight: FontWeight.w500)),
|
||||||
|
subtitle: Text(address,
|
||||||
|
style: TextStyle(color: Colors.grey[600], fontSize: 12)),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.favorite_border, color: Colors.grey),
|
||||||
|
onPressed: () async {
|
||||||
|
if (latitude != null && longitude != null) {
|
||||||
|
await sql.insertMapLocation({
|
||||||
|
'latitude': latitude,
|
||||||
|
'longitude': longitude,
|
||||||
|
'name': title,
|
||||||
|
'rate': 'N/A',
|
||||||
|
}, TableName.placesFavorite);
|
||||||
|
Toast.show(context, '$title ${'Saved Successfully'.tr}',
|
||||||
|
AppColor.primaryColor);
|
||||||
|
} else {
|
||||||
|
Toast.show(
|
||||||
|
context, 'Invalid location data', AppColor.redColor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
if (latitude != null && longitude != null) {
|
||||||
|
sql.insertMapLocation({
|
||||||
|
'latitude': latitude,
|
||||||
|
'longitude': longitude,
|
||||||
|
'name': title,
|
||||||
|
'rate': 'N/A',
|
||||||
|
'createdAt': DateTime.now().toIso8601String(),
|
||||||
|
}, TableName.recentLocations);
|
||||||
|
|
||||||
|
controller.passengerLocation = controller.newMyLocation;
|
||||||
|
controller.myDestination = LatLng(latitude, longitude);
|
||||||
|
controller.convertHintTextDestinationNewPlaces(index);
|
||||||
|
|
||||||
|
controller.placesDestination = [];
|
||||||
|
controller.placeDestinationController.clear();
|
||||||
|
controller.changeMainBottomMenuMap();
|
||||||
|
controller.passengerStartLocationFromMap = true;
|
||||||
|
controller.isPickerShown = true;
|
||||||
|
} else {
|
||||||
|
Toast.show(
|
||||||
|
context, 'Invalid location data', AppColor.redColor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildQuickActionButton({
|
||||||
|
required IconData icon,
|
||||||
|
required String text,
|
||||||
|
VoidCallback? onTap,
|
||||||
|
VoidCallback? onLongPress,
|
||||||
|
}) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.blueColor.withOpacity(0.1),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
border: Border.all(color: AppColor.blueColor.withOpacity(0.3)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(icon, color: AppColor.blueColor),
|
||||||
|
const SizedBox(height: 4.0),
|
||||||
|
Text(
|
||||||
|
text,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: AppStyle.title.copyWith(
|
||||||
|
color: AppColor.blueColor, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showChangeLocationDialog(
|
||||||
|
MapPassengerController controller, String locationType) {
|
||||||
|
Get.defaultDialog(
|
||||||
|
title: 'Change $locationType location?'.tr,
|
||||||
|
middleText: '',
|
||||||
|
confirm: MyElevatedButton(
|
||||||
|
title: 'Yes'.tr,
|
||||||
|
onPressed: () {
|
||||||
|
Get.back();
|
||||||
|
if (locationType == 'Work') {
|
||||||
|
controller.workLocationFromMap = true;
|
||||||
|
} else {
|
||||||
|
controller.homeLocationFromMap = true;
|
||||||
|
}
|
||||||
|
controller.changeMainBottomMenuMap();
|
||||||
|
controller.changePickerShown();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleQuickAction(
|
||||||
|
MapPassengerController controller, String boxName, String hintText) async {
|
||||||
|
final latLng = LatLng(
|
||||||
|
double.parse(box.read(boxName).toString().split(',')[0]),
|
||||||
|
double.parse(box.read(boxName).toString().split(',')[1]),
|
||||||
|
);
|
||||||
|
controller.hintTextDestinationPoint = hintText;
|
||||||
|
controller.changeMainBottomMenuMap();
|
||||||
|
|
||||||
|
await controller.getDirectionMap(
|
||||||
|
'${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}',
|
||||||
|
'${latLng.latitude},${latLng.longitude}',
|
||||||
|
);
|
||||||
|
controller.currentLocationToFormPlaces = false;
|
||||||
|
controller.placesDestination = [];
|
||||||
|
controller.clearPlacesStart();
|
||||||
|
controller.clearPlacesDestination();
|
||||||
|
controller.passengerStartLocationFromMap = false;
|
||||||
|
controller.isPickerShown = false;
|
||||||
|
controller.showBottomSheet1();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,181 +9,130 @@ 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: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Expanded(
|
||||||
padding: const EdgeInsets.all(8),
|
child: TextFormField(
|
||||||
child: Row(
|
controller: controller.placeStartController,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
onChanged: (value) {
|
||||||
children: [
|
if (controller.placeStartController.text.length > 2) {
|
||||||
Container(
|
// Reduced character limit
|
||||||
width: Get.width * .75,
|
controller.getPlacesStart();
|
||||||
height: 40,
|
controller.changeHeightStartPlaces();
|
||||||
decoration:
|
} else if (controller.placeStartController.text.isEmpty) {
|
||||||
const BoxDecoration(color: AppColor.secondaryColor),
|
controller.clearPlacesStart();
|
||||||
child: TextFormField(
|
controller.changeHeightPlaces(); // Collapse if empty
|
||||||
decoration: InputDecoration(
|
}
|
||||||
border: const OutlineInputBorder(
|
},
|
||||||
borderRadius: BorderRadius.only(),
|
decoration: InputDecoration(
|
||||||
gapPadding: 4,
|
hintText: controller.hintTextStartPoint,
|
||||||
borderSide: BorderSide(
|
hintStyle:
|
||||||
color: AppColor.redColor,
|
AppStyle.subtitle.copyWith(color: Colors.grey[600]),
|
||||||
width: 2,
|
prefixIcon:
|
||||||
)),
|
const Icon(Icons.search, color: AppColor.primaryColor),
|
||||||
suffixIcon: const Icon(Icons.search),
|
suffixIcon: controller.placeStartController.text.isNotEmpty
|
||||||
hintText: controller.hintTextStartPoint,
|
? IconButton(
|
||||||
hintStyle: AppStyle.title,
|
icon: Icon(Icons.clear, color: Colors.grey[400]),
|
||||||
hintMaxLines: 1,
|
|
||||||
prefixIcon: IconButton(
|
|
||||||
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),
|
||||||
controller: controller.placeStartController,
|
borderSide: BorderSide.none,
|
||||||
onChanged: (value) {
|
|
||||||
if (controller.placeStartController.text.length > 5) {
|
|
||||||
controller.getPlacesStart();
|
|
||||||
controller.changeHeightStartPlaces();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// onEditingComplete: () => controller.changeHeight(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
IconButton(
|
focusedBorder: OutlineInputBorder(
|
||||||
onPressed: () {
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
controller.startLocationFromMap = true;
|
borderSide: BorderSide(color: AppColor.primaryColor),
|
||||||
controller.changeMainBottomMenuMap();
|
|
||||||
controller.changePickerShown();
|
|
||||||
},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.map_outlined,
|
|
||||||
color: AppColor.yellowColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
filled: true,
|
||||||
|
fillColor: Colors.grey[50],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// controller.placesDestination.isEmpty
|
const SizedBox(width: 8.0),
|
||||||
// ? InkWell(
|
IconButton(
|
||||||
// onTap: () {
|
onPressed: () {
|
||||||
// controller.startLocationFromMap = true;
|
controller.startLocationFromMap = true;
|
||||||
// controller.changeMainBottomMenuMap();
|
controller.changeMainBottomMenuMap();
|
||||||
// controller.changePickerShown();
|
controller.changePickerShown();
|
||||||
// },
|
},
|
||||||
// child: Text(
|
icon: Icon(Icons.location_on_outlined,
|
||||||
// 'Choose from Map Start Point'.tr,
|
color: AppColor.accentColor, size: 30),
|
||||||
// style:
|
tooltip: 'Choose on Map',
|
||||||
// AppStyle.title.copyWith(color: AppColor.blueColor),
|
),
|
||||||
// ),
|
],
|
||||||
// )
|
),
|
||||||
// : const SizedBox(),
|
),
|
||||||
Container(
|
AnimatedContainer(
|
||||||
height:
|
duration: const Duration(milliseconds: 200),
|
||||||
controller.placesStart.isNotEmpty ? controller.height : 0,
|
height: controller.placesStart.isNotEmpty ? controller.height : 0,
|
||||||
color: AppColor.secondaryColor,
|
decoration: BoxDecoration(
|
||||||
child: ListView.builder(
|
color: Colors.white,
|
||||||
itemCount: controller.placesStart.length,
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
itemBuilder: (BuildContext context, int index) {
|
),
|
||||||
var res = controller.placesStart[index];
|
margin: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
return InkWell(
|
child: ListView.separated(
|
||||||
onTap: () async {
|
shrinkWrap: true,
|
||||||
controller.changeHeightPlaces();
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
// if (controller.currentLocationToFormPlaces == true) {
|
itemCount: controller.placesStart.length,
|
||||||
// controller.newStartPointLocation =
|
separatorBuilder: (context, index) =>
|
||||||
// controller.myLocation;
|
const Divider(height: 1, color: Colors.grey),
|
||||||
// } else {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
// controller.myLocation =
|
var res = controller.placesStart[index];
|
||||||
// controller.newStartPointLocation;
|
return ListTile(
|
||||||
// }
|
leading: Image.network(res['icon'], width: 30, height: 30),
|
||||||
await sql.insertMapLocation({
|
title: Text(res['name'].toString(),
|
||||||
'latitude': res['geometry']['location']['lat'],
|
style: AppStyle.subtitle
|
||||||
'longitude': res['geometry']['location']['lng'],
|
.copyWith(fontWeight: FontWeight.w500)),
|
||||||
'name': res['name'].toString(),
|
subtitle: Text(res['vicinity'].toString(),
|
||||||
'rate': res['rating'].toString(),
|
style: TextStyle(color: Colors.grey[600], fontSize: 12)),
|
||||||
'createdAt': DateTime.now().toIso8601String(),
|
trailing: IconButton(
|
||||||
}, TableName.recentLocations);
|
icon: const Icon(Icons.favorite_border, color: Colors.grey),
|
||||||
|
onPressed: () async {
|
||||||
controller.convertHintTextStartNewPlaces(index);
|
await sql.insertMapLocation({
|
||||||
controller.currentLocationString = res['name'];
|
'latitude': res['geometry']['location']['lat'],
|
||||||
controller.placesStart = [];
|
'longitude': res['geometry']['location']['lng'],
|
||||||
controller.placeStartController.clear();
|
'name': res['name'].toString(),
|
||||||
},
|
'rate': res['rating'].toString(),
|
||||||
child: Padding(
|
}, TableName.placesFavorite);
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
Toast.show(
|
||||||
child: Column(
|
context,
|
||||||
children: [
|
'${res['name']} ${'Saved Successfully'.tr}',
|
||||||
Row(
|
AppColor.primaryColor);
|
||||||
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,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
onTap: () async {
|
||||||
],
|
controller.changeHeightPlaces();
|
||||||
));
|
await sql.insertMapLocation({
|
||||||
|
'latitude': res['geometry']['location']['lat'],
|
||||||
|
'longitude': res['geometry']['location']['lng'],
|
||||||
|
'name': res['name'].toString(),
|
||||||
|
'rate': res['rating'].toString(),
|
||||||
|
'createdAt': DateTime.now().toIso8601String(),
|
||||||
|
}, TableName.recentLocations);
|
||||||
|
|
||||||
|
controller.convertHintTextStartNewPlaces(index);
|
||||||
|
controller.currentLocationString = res['name'];
|
||||||
|
controller.placesStart = [];
|
||||||
|
controller.placeStartController.clear();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -15,162 +15,182 @@ 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(
|
||||||
Positioned(
|
children: [
|
||||||
right: 60,
|
// Top Menu Bar
|
||||||
left: 60,
|
Positioned(
|
||||||
child: Padding(
|
top: 10, // Adjust as needed
|
||||||
padding: const EdgeInsets.only(right: 20),
|
left: 0,
|
||||||
child: Opacity(
|
right: 0,
|
||||||
alwaysIncludeSemantics: false,
|
child: SafeArea(
|
||||||
opacity: 1, // Adjust the opacity value as needed
|
child: Padding(
|
||||||
child: AnimatedContainer(
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
width: Get.width * .6,
|
child: Row(
|
||||||
decoration: AppStyle.boxDecoration
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
.copyWith(color: AppColor.blueColor),
|
children: [
|
||||||
transform: Matrix4.translationValues(
|
// GestureDetector(
|
||||||
controller.heightMenu * .1, 1, 1),
|
// onTap: controller.getDrawerMenu,
|
||||||
curve: Curves.easeOutCubic,
|
// child: Container(
|
||||||
clipBehavior: Clip.hardEdge,
|
// padding: const EdgeInsets.all(10),
|
||||||
duration: const Duration(milliseconds: 300),
|
// decoration: AppStyle.boxDecoration
|
||||||
height: controller.heightMenu,
|
// .copyWith(color: AppColor.blueColor),
|
||||||
child: controller.heightMenuBool
|
// child: const Icon(Icons.menu, color: Colors.white),
|
||||||
? Row(
|
// ),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
// ),
|
||||||
children: [
|
if (controller.heightMenuBool)
|
||||||
IconWidgetMenu(
|
Expanded(
|
||||||
onpressed: () {
|
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: () {
|
IconButton(
|
||||||
Get.to(
|
onPressed: () {
|
||||||
() => PassengerProfilePage(),
|
Get.to(() => PassengerProfilePage(),
|
||||||
transition: Transition.zoom,
|
transition: Transition.zoom);
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: Icons.person,
|
|
||||||
title: 'Profile'.tr,
|
|
||||||
),
|
|
||||||
IconWidgetMenu(
|
|
||||||
title: 'Home'.tr,
|
|
||||||
onpressed: () {
|
|
||||||
Get.to(
|
|
||||||
() => const SettingPage(),
|
|
||||||
transition: Transition.downToUp,
|
|
||||||
curve: Curves.easeInOutExpo,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
icon: Icons.settings),
|
icon: const Icon(Icons.person,
|
||||||
],
|
color: Colors.white),
|
||||||
)
|
),
|
||||||
: const SizedBox(), // Choose the desired overlay color
|
IconButton(
|
||||||
)),
|
onPressed: () {
|
||||||
|
Get.to(() => const SettingPage(),
|
||||||
|
transition: Transition.downToUp,
|
||||||
|
curve: Curves.easeInOutExpo);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.settings,
|
||||||
|
color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
// 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,
|
||||||
child: Column(
|
constraints: const BoxConstraints(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
maxWidth: 250), // Add max width constraint
|
||||||
children: [
|
|
||||||
IconMainPageMap(
|
|
||||||
onTap: () {
|
|
||||||
Get.to(() => const PassengerWallet());
|
|
||||||
},
|
|
||||||
title: 'My Wallet'.tr,
|
|
||||||
icon: Icons.wallet,
|
|
||||||
),
|
|
||||||
IconMainPageMap(
|
|
||||||
onTap: () async {
|
|
||||||
Get.to(() => const OrderHistory());
|
|
||||||
},
|
|
||||||
title: 'Order History'.tr,
|
|
||||||
icon: Icons.history,
|
|
||||||
),
|
|
||||||
IconMainPageMap(
|
|
||||||
onTap: () {
|
|
||||||
Get.to(() => ContactUsPage());
|
|
||||||
},
|
|
||||||
title: "Contact Us".tr,
|
|
||||||
icon: Icons.contact_page,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Positioned(
|
|
||||||
left: 5,
|
|
||||||
top: 80,
|
|
||||||
child: AnimatedContainer(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
decoration: AppStyle.boxDecoration1,
|
|
||||||
width: controller.widthMenu,
|
|
||||||
height: Get.height * .3,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
IconMainPageMap(
|
|
||||||
onTap: () async {
|
|
||||||
final String driverAppUrl;
|
|
||||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
|
||||||
driverAppUrl =
|
|
||||||
'https://play.google.com/store/apps/details?id=com.sefer_driver&pli=1'; // Replace with your driver app's Play Store URL
|
|
||||||
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
|
|
||||||
driverAppUrl =
|
|
||||||
'https://apps.apple.com/app/sefer-driver/id6502189302'; // Replace with your driver app's App Store ID
|
|
||||||
} else {
|
|
||||||
// Handle other platforms or unknown platform (optional)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await canLaunchUrl(Uri.parse(driverAppUrl))) {
|
child: ClipRRect(
|
||||||
await launchUrl(Uri.parse(driverAppUrl));
|
borderRadius: BorderRadius.circular(15),
|
||||||
} else {
|
child: Material(
|
||||||
throw 'Could not launch app store URL';
|
color: Colors.white, // Background color of the drawer
|
||||||
}
|
child: Column(
|
||||||
},
|
mainAxisSize: MainAxisSize.min,
|
||||||
title: 'Driver'.tr,
|
children: [
|
||||||
icon: WeatherIcons.wi_moon_14,
|
IconMainPageMap(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => const PassengerWallet());
|
||||||
|
},
|
||||||
|
title: 'My Wallet'.tr,
|
||||||
|
icon: Icons.wallet,
|
||||||
|
),
|
||||||
|
IconMainPageMap(
|
||||||
|
onTap: () async {
|
||||||
|
Get.to(() => const OrderHistory());
|
||||||
|
},
|
||||||
|
title: 'Order History'.tr,
|
||||||
|
icon: Icons.history,
|
||||||
|
),
|
||||||
|
IconMainPageMap(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => ContactUsPage());
|
||||||
|
},
|
||||||
|
title: "Contact Us".tr,
|
||||||
|
icon: Icons.contact_page,
|
||||||
|
),
|
||||||
|
IconMainPageMap(
|
||||||
|
onTap: () async {
|
||||||
|
final String driverAppUrl;
|
||||||
|
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||||
|
driverAppUrl =
|
||||||
|
'https://play.google.com/store/apps/details?id=your_android_driver_app_id'; // Replace with your driver app's Play Store URL
|
||||||
|
} else if (defaultTargetPlatform ==
|
||||||
|
TargetPlatform.iOS) {
|
||||||
|
driverAppUrl =
|
||||||
|
'https://apps.apple.com/app/your_ios_driver_app_id'; // Replace with your driver app's App Store ID
|
||||||
|
} else {
|
||||||
|
// Handle other platforms or unknown platform (optional)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Uri url = Uri.parse(driverAppUrl);
|
||||||
|
if (await canLaunchUrl(url)) {
|
||||||
|
await launchUrl(url);
|
||||||
|
} else {
|
||||||
|
Get.snackbar(
|
||||||
|
'Error',
|
||||||
|
'Could not launch driver app store.',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error launching URL: $e');
|
||||||
|
Get.snackbar(
|
||||||
|
'Error',
|
||||||
|
'Could not open the link.',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: 'Driver'.tr,
|
||||||
|
icon: WeatherIcons.wi_moon_14,
|
||||||
|
),
|
||||||
|
IconMainPageMap(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => ComplaintPage());
|
||||||
|
},
|
||||||
|
title: 'Complaint'.tr,
|
||||||
|
icon: Icons.feedback,
|
||||||
|
),
|
||||||
|
IconMainPageMap(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => const PromosPassengerPage());
|
||||||
|
},
|
||||||
|
title: 'Promos'.tr,
|
||||||
|
icon: Icons.monetization_on,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
IconMainPageMap(
|
),
|
||||||
onTap: () {
|
|
||||||
Get.to(() => ComplaintPage());
|
|
||||||
},
|
|
||||||
title: 'Complaint'.tr,
|
|
||||||
icon: Icons.feedback,
|
|
||||||
),
|
|
||||||
IconMainPageMap(
|
|
||||||
onTap: () {
|
|
||||||
Get.to(() => const PromosPassengerPage());
|
|
||||||
},
|
|
||||||
title: 'Promos'.tr,
|
|
||||||
icon: Icons.monetization_on,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
))
|
),
|
||||||
]),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,29 +209,21 @@ class IconMainPageMap extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
return InkWell(
|
||||||
future: Future.delayed(const Duration(milliseconds: 400)),
|
onTap: onTap,
|
||||||
builder: (context, snapshot) {
|
child: Padding(
|
||||||
return GestureDetector(
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 1),
|
||||||
onTap: onTap,
|
child: Row(
|
||||||
child: SizedBox(
|
children: [
|
||||||
height: Get.height * .1,
|
Icon(icon, size: 24),
|
||||||
width: double.maxFinite,
|
const SizedBox(width: 16),
|
||||||
// decoration: AppStyle.boxDecoration,
|
Text(
|
||||||
child: Padding(
|
title.tr,
|
||||||
padding: const EdgeInsets.all(8.0),
|
style: AppStyle.subtitle,
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Icon(icon),
|
|
||||||
Text(
|
|
||||||
title.tr,
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
});
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
children: [
|
Expanded(
|
||||||
Container(
|
child: Column(
|
||||||
decoration: AppStyle.boxDecoration,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Text(
|
children: [
|
||||||
controller.driverName,
|
Text(controller.driverName, style: AppStyle.title),
|
||||||
style: AppStyle.title,
|
Row(
|
||||||
),
|
|
||||||
),
|
|
||||||
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(
|
|
||||||
children: <Widget>[
|
|
||||||
const Text(''),
|
|
||||||
Container(
|
|
||||||
decoration: AppStyle.boxDecoration,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 4),
|
|
||||||
child: Text(
|
|
||||||
controller.licensePlate,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Text(
|
||||||
decoration: AppStyle.boxDecoration,
|
controller.licensePlate,
|
||||||
child: Padding(
|
style: AppStyle.title.copyWith(fontSize: 16),
|
||||||
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(
|
||||||
'Price of trip'.tr,
|
onTap: () => controller.getDialog(
|
||||||
'For Speed and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance'
|
'Price of trip'.tr,
|
||||||
.tr, () {
|
'For Speed and Delivery trips, the price is calculated dynamically. For Comfort trips, the price is based on time and distance'
|
||||||
Get.back();
|
.tr,
|
||||||
});
|
() => 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
|
onPressed: () async {
|
||||||
? IconButton(
|
if (audioController.isRecording == false) {
|
||||||
onPressed: () async {
|
await audioController.startRecording();
|
||||||
await audioController.startRecording();
|
Toast.show(context, 'Start Record'.tr,
|
||||||
Toast.show(context, 'Start Record'.tr,
|
AppColor.greenColor);
|
||||||
AppColor.greenColor);
|
} else {
|
||||||
},
|
await audioController.stopRecording();
|
||||||
icon: const Icon(
|
Toast.show(context, 'Record saved'.tr,
|
||||||
Icons.play_circle_fill_outlined,
|
AppColor.greenColor);
|
||||||
color: AppColor.greenColor,
|
}
|
||||||
),
|
},
|
||||||
tooltip:
|
icon: Icon(
|
||||||
' Add Note', // Optional tooltip for clarity
|
audioController.isRecording == false
|
||||||
)
|
? Icons.mic_none
|
||||||
: IconButton(
|
: Icons.mic_off,
|
||||||
onPressed: () async {
|
color: AppColor.greenColor,
|
||||||
await audioController.stopRecording();
|
),
|
||||||
Toast.show(context, 'Record saved'.tr,
|
tooltip: audioController.isRecording == false
|
||||||
AppColor.greenColor);
|
? 'Start Recording'
|
||||||
},
|
: 'Stop Recording',
|
||||||
icon: const Icon(
|
),
|
||||||
Icons.stop_circle,
|
|
||||||
color: AppColor.greenColor,
|
|
||||||
),
|
|
||||||
tooltip:
|
|
||||||
' Add Note', // Optional tooltip for clarity
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
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.copyWith(fontSize: 14),
|
||||||
style: AppStyle.title,
|
),
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
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: [
|
||||||
onPressed: () async {
|
IconButton(
|
||||||
if (box.read(BoxName.sosPhonePassenger) == null) {
|
onPressed: () async {
|
||||||
{
|
if (box.read(BoxName.sosPhonePassenger) ==
|
||||||
await profileController.updatField(
|
null) {
|
||||||
'sosPhone', TextInputType.phone);
|
await profileController.updatField(
|
||||||
box.write(BoxName.sosPhonePassenger,
|
'sosPhone', TextInputType.phone);
|
||||||
profileController.prfoileData['sosPhone']);
|
box.write(
|
||||||
}
|
BoxName.sosPhonePassenger,
|
||||||
} else {
|
profileController
|
||||||
makePhoneCall('122');
|
.prfoileData['sosPhone']);
|
||||||
// box.read(BoxName.sosPhonePassenger));
|
} else {
|
||||||
}
|
makePhoneCall('122');
|
||||||
},
|
}
|
||||||
icon: const Icon(
|
},
|
||||||
Icons.sos_rounded,
|
icon: const Icon(Icons.sos_rounded,
|
||||||
color: AppColor.redColor,
|
color: AppColor.redColor),
|
||||||
),
|
),
|
||||||
|
Text('SOS', style: AppStyle.title),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
SizedBox(
|
||||||
decoration: AppStyle.boxDecoration,
|
width: Get.width * 0.18,
|
||||||
width: Get.width * .15,
|
child: Column(
|
||||||
child: IconButton(
|
children: [
|
||||||
onPressed: () async {
|
IconButton(
|
||||||
if (box.read(BoxName.sosPhonePassenger) == null ||
|
onPressed: () async {
|
||||||
box.read(BoxName.sosPhonePassenger) == 'sos') {
|
if (box.read(BoxName.sosPhonePassenger) ==
|
||||||
{
|
null ||
|
||||||
await profileController.updatField(
|
box.read(BoxName.sosPhonePassenger) ==
|
||||||
'sosPhone', TextInputType.phone);
|
'sos') {
|
||||||
box.write(BoxName.sosPhonePassenger,
|
await profileController.updatField(
|
||||||
profileController.prfoileData['sosPhone']);
|
'sosPhone', TextInputType.phone);
|
||||||
}
|
box.write(
|
||||||
} else {
|
BoxName.sosPhonePassenger,
|
||||||
String phoneNumber = box
|
profileController
|
||||||
.read(BoxName.sosPhonePassenger)
|
.prfoileData['sosPhone']);
|
||||||
.toString();
|
} else {
|
||||||
// phoneNumber = phoneNumber.replaceAll('0', '');
|
final phoneNumber = box
|
||||||
var phone = box.read(BoxName.countryCode) ==
|
.read(BoxName.sosPhonePassenger)
|
||||||
'Egypt'
|
.toString();
|
||||||
? '+2${box.read(BoxName.sosPhonePassenger)}'
|
final phone =
|
||||||
: '+962${box.read(BoxName.sosPhonePassenger)}';
|
box.read(BoxName.countryCode) == 'Egypt'
|
||||||
controller.sendWhatsapp(phone);
|
? '+2$phoneNumber'
|
||||||
}
|
: '+962$phoneNumber';
|
||||||
},
|
controller.sendWhatsapp(phone);
|
||||||
icon: const Icon(
|
}
|
||||||
FontAwesome.whatsapp,
|
},
|
||||||
color: AppColor.greenColor,
|
icon: const Icon(FontAwesome.whatsapp,
|
||||||
),
|
color: AppColor.greenColor),
|
||||||
|
),
|
||||||
|
Text('WhatsApp', style: AppStyle.title),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
SizedBox(
|
||||||
decoration: AppStyle.boxDecoration,
|
width: Get.width * 0.18,
|
||||||
width: Get.width * .15,
|
child: Column(
|
||||||
child: IconButton(
|
children: [
|
||||||
onPressed: () async {
|
IconButton(
|
||||||
await controller.getTokenForParent();
|
onPressed: () async {
|
||||||
},
|
await controller.getTokenForParent();
|
||||||
icon: const Icon(
|
},
|
||||||
Foundation.video,
|
icon: const Icon(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);
|
||||||
|
|
||||||
|
|||||||
@@ -21,35 +21,83 @@ 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(
|
||||||
child: Column(
|
color: Theme.of(context)
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
.scaffoldBackgroundColor, // Use theme color
|
||||||
// Use Stack for overlapping widgets
|
borderRadius: const BorderRadius.only(
|
||||||
children: [
|
topLeft: Radius.circular(20),
|
||||||
// Text elements
|
topRight: Radius.circular(20),
|
||||||
|
),
|
||||||
SizedBox(
|
boxShadow: [
|
||||||
width: Get.width * .7,
|
BoxShadow(
|
||||||
child: const LinearProgressIndicator(
|
color: Colors.black.withOpacity(0.1),
|
||||||
minHeight: 6,
|
blurRadius: 10,
|
||||||
backgroundColor: AppColor.yellowColor,
|
offset: const Offset(0, -5),
|
||||||
color: AppColor.secondaryColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min, // Fit content
|
||||||
|
children: [
|
||||||
Text(
|
Text(
|
||||||
mapPassengerController.driversStatusForSearchWindow,
|
mapPassengerController.driversStatusForSearchWindow,
|
||||||
style: AppStyle.title,
|
style: AppStyle.title.copyWith(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
// Text(
|
const SizedBox(height: 12),
|
||||||
// "We are searching for the nearest driver to you".tr,
|
|
||||||
// style: AppStyle.title,
|
|
||||||
// ),
|
|
||||||
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,
|
||||||
_buildTimer(mapPassengerController),
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
SizedBox(
|
||||||
|
width: Get.width * 0.8,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
minHeight: 8,
|
||||||
|
backgroundColor:
|
||||||
|
AppColor.accentColor.withOpacity(0.3),
|
||||||
|
color: AppColor.primaryColor,
|
||||||
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
|
AppColor.primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.timer_outlined,
|
||||||
|
size: 16, color: Colors.grey),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
_buildTimer(mapPassengerController),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// const SizedBox(height: 8),
|
||||||
|
// ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// // Add logic to cancel the search if needed
|
||||||
|
// // mapPassengerController.cancelSearch();
|
||||||
|
// Get.back(); // Example: go back to the previous screen
|
||||||
|
// },
|
||||||
|
// style: ElevatedButton.styleFrom(
|
||||||
|
// backgroundColor: Colors.grey.shade300,
|
||||||
|
// foregroundColor: Colors.black87,
|
||||||
|
// elevation: 0,
|
||||||
|
// shape: RoundedRectangleBorder(
|
||||||
|
// borderRadius: BorderRadius.circular(8),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// child: Text('Cancel Search'.tr),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -60,6 +108,22 @@ class SearchingCaptainWindow extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget _buildTimer(MapPassengerController mapPassengerController) {
|
||||||
|
// return Obx(() {
|
||||||
|
// final remainingSeconds = mapPassengerController.searchingDuration.value;
|
||||||
|
// final minutes = (remainingSeconds ~/ 60).toString().padLeft(2, '0');
|
||||||
|
// final seconds = (remainingSeconds % 60).toString().padLeft(2, '0');
|
||||||
|
// return Text(
|
||||||
|
// '$minutes:$seconds',
|
||||||
|
// style: const TextStyle(
|
||||||
|
// fontSize: 16,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// color: Colors.grey,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
Widget _buildTimer(MapPassengerController mapPassengerController) {
|
Widget _buildTimer(MapPassengerController mapPassengerController) {
|
||||||
// Start timer at 0
|
// Start timer at 0
|
||||||
Timer? timer;
|
Timer? timer;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user