This commit is contained in:
Hamza-Ayed
2024-12-22 16:06:07 +03:00
parent 2910750483
commit 0f16dd9293
22 changed files with 2531 additions and 1282 deletions

View File

@@ -10,30 +10,30 @@ class AppStyle {
fontSize: 36,
color: AppColor.accentColor,
fontFamily: box.read(BoxName.lang) == 'ar'
// ?GoogleFonts.notoNaskhArabic().fontFamily
? GoogleFonts.notoNaskhArabic().fontFamily
: GoogleFonts.roboto().fontFamily);
// ?GoogleFonts.markaziText().fontFamily
? GoogleFonts.markaziText().fontFamily
: GoogleFonts.inter().fontFamily);
static TextStyle headTitle2 = TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
color: AppColor.writeColor,
fontFamily: box.read(BoxName.lang) == 'ar'
? GoogleFonts.notoNaskhArabic().fontFamily
: GoogleFonts.roboto().fontFamily);
? GoogleFonts.markaziText().fontFamily
: GoogleFonts.inter().fontFamily);
static TextStyle title = TextStyle(
fontWeight: FontWeight.normal,
fontSize: 14,
fontSize: 16,
color: AppColor.writeColor,
fontFamily: box.read(BoxName.lang) == 'ar'
? GoogleFonts.notoNaskhArabic().fontFamily
: GoogleFonts.roboto().fontFamily);
? GoogleFonts.markaziText().fontFamily
: GoogleFonts.inter().fontFamily);
static TextStyle subtitle = TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12,
color: AppColor.writeColor,
fontFamily: box.read(BoxName.lang) == 'ar'
? GoogleFonts.notoNaskhArabic().fontFamily
: GoogleFonts.roboto().fontFamily);
? GoogleFonts.markaziText().fontFamily
: GoogleFonts.inter().fontFamily);
static TextStyle number = const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,

View File

@@ -1,6 +1,8 @@
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/links.dart';
import 'package:sefer_driver/controller/functions/crud.dart';
import 'package:flutter/cupertino.dart';
@@ -15,7 +17,7 @@ Future<void> checkForUpdate(BuildContext context) async {
final packageInfo = await PackageInfo.fromPlatform();
final currentVersion = packageInfo.buildNumber;
final version = packageInfo.version;
print('currentVersion is : $currentVersion');
// print('currentVersion is : $currentVersion');
// Fetch the latest version from your server
String latestVersion = await getPackageInfo();
box.write(BoxName.packagInfo, version);
@@ -41,36 +43,118 @@ void showUpdateDialog(BuildContext context) {
final String storeUrl = Platform.isAndroid
? 'https://play.google.com/store/apps/details?id=com.sefer_driver'
: 'https://apps.apple.com/ae/app/sefer-driver/id6502189302';
showCupertinoDialog(
showGeneralDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text('Update Available'.tr),
content: Text(
'A new version of the app is available. Please update to the latest version.'
.tr,
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (_, __, ___) {
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Center(
child: AlertDialog(
// Using AlertDialog for a more Material Design look
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(16)), // More rounded corners
elevation: 4, // Add a bit more elevation
contentPadding: EdgeInsets.zero, // Remove default content padding
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Image.asset(
'assets/images/logo.png',
height: 72, // Slightly larger logo
width: 72,
),
),
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'Update Available'.tr,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
// Use theme's title style
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: const EdgeInsets.all(24.0),
child: Text(
'A new version of the app is available. Please update to the latest version.'
.tr, // More encouraging message
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
// Use theme's body style
color: Colors.black87,
),
),
),
const Divider(height: 0),
Row(
children: [
Expanded(
child: TextButton(
// Using TextButton for "Cancel"
onPressed: () => Navigator.pop(context),
style: TextButton.styleFrom(
foregroundColor: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(16),
),
),
),
child: Text('Cancel'.tr),
),
),
const SizedBox(
height: 48,
child: VerticalDivider(width: 0), // Using VerticalDivider
),
Expanded(
child: ElevatedButton(
// Using ElevatedButton for "Update"
onPressed: () async {
if (await canLaunchUrl(Uri.parse(storeUrl))) {
await launchUrl(Uri.parse(storeUrl));
}
if (context.mounted) Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColor
.primaryColor, // Use theme's primary color
foregroundColor: Theme.of(context)
.colorScheme
.onPrimary, // Use theme's onPrimary color
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(16),
),
),
),
child: Text('Update'.tr),
),
),
],
),
],
),
),
),
actions: <Widget>[
CupertinoDialogAction(
child: Text('Update'.tr),
onPressed: () async {
if (await canLaunchUrl(Uri.parse(storeUrl))) {
await launchUrl(Uri.parse(storeUrl));
} else {
print('Could not launch $storeUrl');
}
Navigator.of(context).pop();
},
),
CupertinoDialogAction(
child: Text('Cancel'.tr),
onPressed: () async {
Navigator.of(context).pop();
},
),
],
);
},
transitionBuilder: (_, animation, __, child) {
return ScaleTransition(
scale: CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic, // More natural curve
),
child: child,
);
},
);

View File

@@ -1,94 +1,88 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/box_name.dart';
import '../../main.dart';
import '../themes/themes.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/main.dart';
import 'package:sefer_driver/controller/themes/themes.dart';
class LocaleController extends GetxController {
Locale? language;
String countryCode = '';
void restartApp() {
// Get.offAll(MyApp);
runApp(MyApp());
}
ThemeData appTheme = themeEnglish;
ThemeData appTheme = lightThemeEnglish;
changeLang(String langcode) {
void changeLang(String langcode) {
Locale locale;
switch (langcode) {
case "ar":
locale = const Locale("ar");
appTheme = themeArabic;
appTheme = lightThemeArabic;
box.write(BoxName.lang, 'ar');
break;
case "en":
locale = const Locale("en");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'en');
break;
case "tr":
locale = const Locale("tr");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'tr');
break;
case "fr":
locale = const Locale("fr");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'fr');
break;
case "it":
locale = const Locale("it");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'it');
break;
case "de":
locale = const Locale("de");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'de');
break;
case "el":
locale = const Locale("el");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'el');
break;
case "es":
locale = const Locale("es");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'es');
break;
case "fa":
locale = const Locale("fa");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'fa');
break;
case "zh":
locale = const Locale("zh");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'zh');
break;
case "ru":
locale = const Locale("ru");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'ru');
break;
case "hi":
locale = const Locale("hi");
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
box.write(BoxName.lang, 'hi');
break;
default:
locale = Locale(Get.deviceLocale!.languageCode);
box.write(BoxName.lang, Get.deviceLocale!.languageCode);
appTheme = themeEnglish;
appTheme = lightThemeEnglish;
break;
}
box.write(BoxName.lang, langcode);
Get.changeTheme(appTheme);
Get.updateLocale(locale);
restartApp();
update();
}

View File

@@ -925,10 +925,50 @@ Store your money with us and receive it in your bank as a monthly salary.''':
"You will get cost of your work for this trip":
"ستحصل على تكلفة عملك لهذه الرحلة",
"in your wallet": "في محفظتك",
"you gain": "تكسب",
"you gain": "تكسب", "Account": "الحساب",
"Wallet": "المحفظة", "Maintenance Offer": "عرض الصيانة",
"Enter your Question here": "أدخل سؤالك هنا",
"Ineligible for Offer": "غير مؤهل للحصول على العرض",
"You should complete 500 trips to unlock this feature.":
"يجب عليك إكمال 500 رحلة لتفعيل هذه الميزة.",
"Thank You!": "شكراً لك!",
"Your rating has been submitted.": "تم إرسال تقييمك.",
"General": "عام",
"Language": "اللغة",
"You can change the language of the app": "يمكنك تغيير لغة التطبيق",
"Change Country": "تغيير الدولة",
"Don't start trip if passenger not in your car":
"لا تبدأ الرحلة إذا لم يكن الراكب في سيارتك",
"You can change the Country to get all features":
"يمكنك تغيير الدولة للحصول على جميع الميزات",
"Slide to End Trip": "‏اسحب لإنهاء الرحلة",
"App Preferences": "تفضيلات التطبيق",
"Google Map App": "تطبيق خرائط جوجل",
"If you want to make Google Map App run directly when you apply order":
"إذا كنت تريد تشغيل تطبيق خرائط جوجل مباشرة عند تطبيق الطلب",
"Vibration": "الاهتزاز",
"Help & Support": "المساعدة والدعم",
"Please select a rating before submitting.":
"يرجى تحديد تقييم قبل الإرسال.",
"Please check back later for available rides.":
"يرجى التحقق مرة أخرى لاحقًا للحصول على الرحلات المتاحة.",
"Please enter your question": "يرجى إدخال سؤالك",
"Submit Question": "إرسال السؤال",
"Your Questions": "أسئلتك",
"No questions asked yet.": "لم يتم طرح أي أسئلة بعد.",
"Activities": "الأنشطة",
"History of Trip": "سجل الرحلات",
"Available for rides": "متاح للرحلات",
"Support": "الدعم",
"Helping Center": "مركز المساعدة",
"More": "المزيد",
"Order Cancelled": "الطلب ملغى",
"Order Cancelled by Passenger": "تم إلغاء الطلب من قبل الراكب",
"Success": "النجاح",
"Success": "‏تمام",
"Feedback data saved successfully": "تم حفظ بيانات التقييم بنجاح",
"No Promo for today .": "لا ترويج لليوم.",
"Select your destination": "اختر وجهتك",

View File

@@ -1,8 +1,10 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
import 'package:sefer_driver/views/widgets/mydialoug.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
@@ -20,16 +22,43 @@ class NotificationCaptainController extends GetxController {
link: AppLink.getNotificationCaptain,
payload: {'driverID': box.read(BoxName.driverID)});
if (res == "failure") {
Get.defaultDialog(
title: 'There is no notification yet'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Back',
// MyDialog().getDialog('There is no notification yet'.tr, '', () {
// Get.back();
// Get.back();
// });
Get.dialog(
CupertinoAlertDialog(
title: Column(
children: [
const Icon(
CupertinoIcons.bell_slash_fill,
color: CupertinoColors.systemGrey,
size: 40,
),
const SizedBox(height: 12),
Text(
'There is no notification yet'.tr,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
],
),
actions: [
CupertinoDialogAction(
onPressed: () {
Get.back();
Get.back();
}));
},
child: Text('Back'.tr),
),
],
),
barrierDismissible: true,
transitionCurve: Curves.easeOutBack,
transitionDuration: const Duration(milliseconds: 200),
);
}
notificationData = jsonDecode(res);
// sql.insertData(notificationData['message'], TableName.captainNotification);

View File

@@ -1,6 +1,8 @@
import 'dart:convert';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/functions/location_controller.dart';
import 'package:geolocator/geolocator.dart';
@@ -79,31 +81,98 @@ class RideAvailableController extends GetxController {
// }
getRideAvailable() async {
isLoading = true;
LatLngBounds bounds = calculateBounds(
Get.find<LocationController>().myLocation!.latitude,
Get.find<LocationController>().myLocation!.longitude,
4000);
var payload = {
// "carType": box.read(BoxName.carTypeOfDriver).toString(),
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
};
Log.print('payload: ${payload}');
var res = await CRUD().get(link: AppLink.getRideWaiting, payload: payload);
Log.print('res: ${res}');
try {
isLoading = true;
update();
if (res != 'failure') {
rideAvailableMap = jsonDecode(res);
LatLngBounds bounds = calculateBounds(
Get.find<LocationController>().myLocation!.latitude,
Get.find<LocationController>().myLocation!.longitude,
4000);
var payload = {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
};
var res =
await CRUD().get(link: AppLink.getRideWaiting, payload: payload);
if (res != 'failure') {
rideAvailableMap = jsonDecode(res);
isLoading = false;
update();
} else {
HapticFeedback.lightImpact();
Get.dialog(
CupertinoAlertDialog(
title: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
CupertinoIcons.car,
size: 44,
color: CupertinoColors.systemGrey,
),
const SizedBox(height: 12),
Text(
"No Rides Available".tr,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
],
),
content: Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"Please check back later for available rides.".tr,
style: const TextStyle(
fontSize: 13,
color: CupertinoColors.systemGrey,
),
),
),
actions: [
CupertinoDialogAction(
onPressed: () {
Get.back();
Get.back();
},
child: Text('OK'.tr),
),
],
),
barrierDismissible: true,
transitionCurve: Curves.easeOutBack,
transitionDuration: const Duration(milliseconds: 200),
);
}
} catch (e) {
isLoading = false;
update();
} else {
MyDialog().getDialog("No Rides Available".tr, '', () {
Get.back();
Get.back();
});
Get.dialog(
CupertinoAlertDialog(
title: const Icon(
CupertinoIcons.exclamationmark_triangle_fill,
color: CupertinoColors.systemRed,
size: 44,
),
content: Text(
"Error fetching rides. Please try again.".tr,
style: const TextStyle(fontSize: 14),
),
actions: [
CupertinoDialogAction(
onPressed: () => Get.back(),
child: Text('OK'.tr),
),
],
),
);
}
}

View File

@@ -1,21 +1,22 @@
import 'package:flutter/material.dart';
import 'package:sefer_driver/constant/style.dart';
import '../../constant/colors.dart';
ThemeData themeEnglish = ThemeData(
fontFamily: "PlayfairDisplay",
ThemeData lightThemeEnglish = ThemeData(
brightness: Brightness.light,
fontFamily: "SFPro",
textTheme: TextTheme(
displaySmall: AppStyle.title,
displayLarge: AppStyle.title,
displayMedium: AppStyle.title,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.title),
displaySmall: AppStyle.title,
displayLarge: AppStyle.headTitle,
displayMedium: AppStyle.headTitle2,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.subtitle,
),
primarySwatch: Colors.blue,
dialogTheme: DialogTheme(
backgroundColor: AppColor.secondaryColor,
contentTextStyle: AppStyle.title,
titleTextStyle: AppStyle.title,
titleTextStyle: AppStyle.headTitle2,
),
appBarTheme: AppBarTheme(
elevation: 0,
@@ -25,35 +26,122 @@ ThemeData themeEnglish = ThemeData(
color: AppColor.primaryColor,
),
toolbarTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2)
.bodyMedium,
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).bodyMedium,
titleTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2)
.titleLarge,
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).titleLarge,
),
);
ThemeData themeArabic = ThemeData(
fontFamily: 'mohanad',
textTheme: const TextTheme(
displayLarge: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: AppColor.primaryColor),
displayMedium: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26,
color: AppColor.primaryColor),
bodyLarge: TextStyle(
height: 2,
color: AppColor.accentColor,
fontWeight: FontWeight.bold,
fontSize: 14),
bodyMedium:
TextStyle(height: 2, color: AppColor.accentColor, fontSize: 14)),
ThemeData darkThemeEnglish = ThemeData(
brightness: Brightness.dark,
fontFamily: "SFPro",
textTheme: TextTheme(
displaySmall: AppStyle.title,
displayLarge: AppStyle.headTitle,
displayMedium: AppStyle.headTitle2,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.subtitle,
),
primarySwatch: Colors.blue,
dialogTheme: DialogTheme(
backgroundColor: AppColor.secondaryColor,
contentTextStyle: AppStyle.title,
titleTextStyle: AppStyle.headTitle2,
),
appBarTheme: AppBarTheme(
elevation: 0,
color: AppColor.secondaryColor,
centerTitle: true,
iconTheme: const IconThemeData(
color: AppColor.primaryColor,
),
toolbarTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).bodyMedium,
titleTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).titleLarge,
),
);
ThemeData lightThemeArabic = ThemeData(
brightness: Brightness.light,
fontFamily: 'SFArabic',
textTheme: TextTheme(
displaySmall: AppStyle.title,
displayLarge: AppStyle.headTitle,
displayMedium: AppStyle.headTitle2,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.subtitle,
),
primarySwatch: Colors.blue,
dialogTheme: DialogTheme(
backgroundColor: AppColor.secondaryColor,
contentTextStyle: AppStyle.title,
titleTextStyle: AppStyle.headTitle2,
),
appBarTheme: AppBarTheme(
elevation: 0,
color: AppColor.secondaryColor,
centerTitle: true,
iconTheme: const IconThemeData(
color: AppColor.primaryColor,
),
toolbarTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).bodyMedium,
titleTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).titleLarge,
),
);
ThemeData darkThemeArabic = ThemeData(
brightness: Brightness.dark,
fontFamily: 'SFArabic',
textTheme: TextTheme(
displaySmall: AppStyle.title,
displayLarge: AppStyle.headTitle,
displayMedium: AppStyle.headTitle2,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.subtitle,
),
primarySwatch: Colors.blue,
dialogTheme: DialogTheme(
backgroundColor: AppColor.secondaryColor,
contentTextStyle: AppStyle.title,
titleTextStyle: AppStyle.headTitle2,
),
appBarTheme: AppBarTheme(
elevation: 0,
color: AppColor.secondaryColor,
centerTitle: true,
iconTheme: const IconThemeData(
color: AppColor.primaryColor,
),
toolbarTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).bodyMedium,
titleTextStyle: TextTheme(
titleSmall: AppStyle.subtitle,
headlineSmall: AppStyle.title,
titleLarge: AppStyle.headTitle2,
).titleLarge,
),
);

View File

@@ -1,84 +1,142 @@
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
import 'package:sefer_driver/views/widgets/my_textField.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../controller/rate/rate_app_controller.dart';
class RatingScreen extends StatelessWidget {
// Initialize the RatingController using GetX for state management
final RatingController ratingController = Get.put(RatingController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Display title "Rate Our App", with .tr for localization support
title: Text("Rate Our App".tr),
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text(
"Rate Our App".tr,
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
body: Center(
child: Obx(() {
// Observe changes in userRating; when updated, rebuild the UI accordingly
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
// mainAxisAlignment:
// MainAxisAlignment.center, // Center content vertically
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.asset('assets/images/logo.gif')),
const SizedBox(height: 10),
// Text prompt asking the user to rate the app, with localization support
Text("How would you rate our app?".tr),
const SizedBox(height: 10), // Vertical spacing between elements
MyTextForm(
controller: ratingController.comment,
label: 'write comment here'.tr,
hint: 'write comment here'.tr,
type: TextInputType.name,
),
// Build and display the row of rating stars
_buildRatingStars(),
child: SafeArea(
child: SingleChildScrollView(
child: Center(
child: Obx(() {
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// App logo or visual
ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.asset(
'assets/images/logo.gif',
height: 120,
),
),
const SizedBox(height: 20),
const SizedBox(
height: 20), // Additional spacing before the button
// Rating Prompt
Text(
"How would you rate our app?".tr,
textAlign: TextAlign.center,
style: CupertinoTheme.of(context)
.textTheme
.navTitleTextStyle
.copyWith(fontSize: 18, fontWeight: FontWeight.w600),
),
const SizedBox(height: 20),
// Button to submit the selected rating
MyElevatedButton(
onPressed: () {
// Calls submitRating() method in the controller with the current rating value
ratingController
.submitRating(ratingController.userRating.value);
},
// Button text "Submit Rating" with localization support
title: "Submit Rating".tr,
// Comment Box
CupertinoTextField(
controller: ratingController.comment,
placeholder: 'Write your comment here'.tr,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemGrey4),
borderRadius: BorderRadius.circular(12),
color: CupertinoColors.white,
),
prefix: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Icon(CupertinoIcons.pencil_ellipsis_rectangle,
color: CupertinoColors.systemGrey),
),
),
const SizedBox(height: 20),
// Star Rating Section
_buildRatingStars(),
const SizedBox(height: 30),
// Submit Button
CupertinoButton(
padding: const EdgeInsets.symmetric(
horizontal: 24, vertical: 14),
borderRadius: BorderRadius.circular(12),
color: CupertinoColors.activeGreen,
onPressed: () {
if (ratingController.userRating.value > 0) {
ratingController
.submitRating(ratingController.userRating.value);
Get.snackbar(
"Thank You!".tr,
"Your rating has been submitted.".tr,
backgroundColor: CupertinoColors.systemGrey6,
snackPosition: SnackPosition.BOTTOM,
margin: const EdgeInsets.all(16),
borderRadius: 12,
);
} else {
Get.snackbar(
"Error".tr,
"Please select a rating before submitting.".tr,
backgroundColor: CupertinoColors.systemRed,
snackPosition: SnackPosition.BOTTOM,
margin: const EdgeInsets.all(16),
borderRadius: 12,
);
}
},
child: Text(
"Submit Rating".tr,
style: const TextStyle(
color: CupertinoColors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
);
}),
);
}),
),
),
),
);
}
// Widget function to display a row of clickable star icons for rating
// Widget for building rating stars with animations
Widget _buildRatingStars() {
return Row(
mainAxisAlignment:
MainAxisAlignment.center, // Center-aligns stars horizontally
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(5, (index) {
return IconButton(
// Display a star icon, filled if selected, otherwise grey
icon: Icon(
Icons.star,
color: index < ratingController.userRating.value
? Colors.orange // Orange for selected stars
: Colors.grey, // Grey for unselected stars
),
onPressed: () {
// Update user rating in the controller when a star is clicked
return GestureDetector(
onTap: () {
ratingController.userRating.value = index + 1;
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.symmetric(horizontal: 4),
child: Icon(
CupertinoIcons.star_fill,
size: 40,
color: index < ratingController.userRating.value
? CupertinoColors.systemYellow
: CupertinoColors.systemGrey3,
),
),
);
}),
);

View File

@@ -2,7 +2,6 @@ import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/controller/profile/setting_controller.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/views/lang/languages.dart';
@@ -25,140 +24,134 @@ class SettingsCaptain extends StatelessWidget {
title: 'Settings'.tr,
body: [
ListView(
physics: const BouncingScrollPhysics(),
children: <Widget>[
ListTile(
leading: const Icon(Icons.language),
title: Text(
'Language'.tr,
style: AppStyle.headTitle2,
),
subtitle: Text('You can change the language of the app'.tr),
onTap: () => Get.to(const Language()),
),
const Divider(
endIndent: 44,
indent: 44,
),
ListTile(
leading: const Icon(Icons.place_outlined),
title: Text(
'Change Country'.tr,
style: AppStyle.headTitle2,
),
subtitle:
Text('You can change the Country to get all features'.tr),
onTap: () => Get.to(MyScafolld(
title: 'Change Country'.tr,
body: [CountryPickerFromSetting()],
isleading: true)),
),
const Divider(
endIndent: 44,
indent: 44,
),
ListTile(
leading: const Icon(
MaterialCommunityIcons.map_marker_radius,
color: AppColor.redColor,
),
title: Text(
'Google Map App'.tr,
style: AppStyle.headTitle2,
),
subtitle: Text(
'If you want to make Google Map App run directly when you apply order'
.tr),
trailing:
GetBuilder<SettingController>(builder: (settingController) {
return CupertinoSwitch(
value: settingController.isGoogleMapsEnabled,
activeColor: AppColor.primaryColor,
onChanged: (bool value) {
settingController.onChangMapApp();
},
);
}),
),
const Divider(
endIndent: 44,
indent: 44,
),
ListTile(
leading: const Icon(Icons.question_answer),
title: Text(
'Frequently Questions'.tr,
style: AppStyle.headTitle2,
),
subtitle: Text(
'You can change the Country to get all features'.tr,
style: AppStyle.title,
),
onTap: () => Get.to(() => const FrequentlyQuestionsPage()),
),
const Divider(
endIndent: 44,
indent: 44,
),
ListTile(
leading: const Icon(Icons.vibration),
title: Text(
'Vibration'.tr,
style: AppStyle.headTitle2,
),
subtitle: Text(
"You can change the vibration feedback for all buttons".tr,
style: AppStyle.title,
),
trailing: GetBuilder<HomePageController>(
builder: (controller) => CupertinoSwitch(
value: controller.isVibrate,
onChanged: controller.changeVibrateOption,
activeColor: AppColor.primaryColor,
)),
onTap: () => print('3'),
),
const Divider(
endIndent: 44,
indent: 44,
),
ListTile(
leading: const Icon(Icons.help_outline),
title: Text(
"How to use SEFER".tr,
style: AppStyle.headTitle2,
),
subtitle: Text(
''.tr,
style: AppStyle.title,
),
onTap: () => Get.to(() => const UsingAppPage()),
// General Section
_buildSectionHeader('General'.tr),
CupertinoListSection(
margin: EdgeInsets.zero,
children: [
CupertinoListTile(
leading: const Icon(CupertinoIcons.globe),
title: Text('Language'.tr, style: AppStyle.headTitle2),
subtitle: Text('You can change the language of the app'.tr,
style: AppStyle.subtitle),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(const Language()),
),
CupertinoListTile(
leading: const Icon(CupertinoIcons.flag_fill),
title: Text('Change Country'.tr, style: AppStyle.headTitle2),
subtitle: Text(
'You can change the Country to get all features'.tr,
style: AppStyle.subtitle),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(
MyScafolld(
title: 'Change Country'.tr,
body: [CountryPickerFromSetting()],
isleading: true,
// isCupertino: true, // Indicate it's a Cupertino style page
),
),
),
],
),
const Divider(
endIndent: 44,
indent: 44,
// App Preferences Section
_buildSectionHeader('App Preferences'.tr),
CupertinoListSection(
margin: EdgeInsets.zero,
children: [
CupertinoListTile(
leading: Icon(
CupertinoIcons.map_pin_ellipse,
color: AppColor.redColor,
),
title: Text('Google Map App'.tr, style: AppStyle.headTitle2),
subtitle: Text(
'If you want to make Google Map App run directly when you apply order'
.tr,
style: AppStyle.subtitle,
),
trailing: GetBuilder<SettingController>(
builder: (settingController) {
return CupertinoSwitch(
value: settingController.isGoogleMapsEnabled,
activeTrackColor: AppColor.primaryColor,
onChanged: (bool value) {
settingController.onChangMapApp();
},
);
},
),
),
CupertinoListTile(
leading: Icon(Icons.vibration),
title: Text('Vibration'.tr, style: AppStyle.headTitle2),
subtitle: Text(
"You can change the vibration feedback for all buttons".tr,
style: AppStyle.subtitle,
),
trailing: GetBuilder<HomePageController>(
builder: (controller) => CupertinoSwitch(
value: controller.isVibrate,
onChanged: controller.changeVibrateOption,
activeTrackColor: AppColor.primaryColor,
),
),
onTap: () => print('3'),
),
],
),
ListTile(
leading: const Icon(Icons.account_balance_outlined),
title: Text(
'About Us'.tr,
style: AppStyle.headTitle2,
),
subtitle: Text(
'You can change the Country to get all features'.tr,
style: AppStyle.title,
),
onTap: () => Get.to(() => const AboutPage()),
// Help & Support Section
_buildSectionHeader('Help & Support'.tr),
CupertinoListSection(
margin: EdgeInsets.zero,
children: [
CupertinoListTile(
leading: const Icon(CupertinoIcons.question_circle_fill),
title: Text('Frequently Questions'.tr,
style: AppStyle.headTitle2),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(() => const FrequentlyQuestionsPage()),
),
CupertinoListTile(
leading: const Icon(CupertinoIcons.hand_raised_fill),
title:
Text("How to use SEFER".tr, style: AppStyle.headTitle2),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(() => const UsingAppPage()),
),
CupertinoListTile(
leading: const Icon(CupertinoIcons.info_circle_fill),
title: Text('About Us'.tr, style: AppStyle.headTitle2),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(() => const AboutPage()),
),
],
),
// ListTile(
// leading: const Icon(Icons.account_circle),
// title: const Text('Account'),
// onTap: () => Navigator.pushNamed(context, '/account-settings'),
// ),
const SizedBox(height: 16),
],
),
],
isleading: true,
// isCupertino: true, // Indicate this screen is generally Cupertino style
);
}
Widget _buildSectionHeader(String title) {
return Padding(
padding: const EdgeInsets.only(left: 16.0, top: 20.0, bottom: 10.0),
child: Text(
title,
style: const TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: CupertinoColors.secondaryLabel,
),
),
);
}
}

View File

@@ -175,7 +175,7 @@ class AssuranceHealthPage extends StatelessWidget {
// .tr,
// backgroundColor:
// CupertinoColors.systemGrey);
mySnackbarSuccess(
mySnackeBarError(
"You have chosen not to proceed with health insurance."
.tr);
},

View File

@@ -1,5 +1,6 @@
import 'package:sefer_driver/constant/api_key.dart';
import 'package:sefer_driver/constant/links.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:sefer_driver/views/Rate/rate_app_page.dart';
import 'package:sefer_driver/views/auth/captin/contact_us_page.dart';
@@ -25,108 +26,304 @@ import '../assurance_health_page.dart';
import '../maintain_center_page.dart';
import 'package:flutter/cupertino.dart';
// class CupertinoDrawerCaptain extends StatelessWidget {
// final ImageController imageController = Get.put(ImageController());
// @override
// Widget build(BuildContext context) {
// return CupertinoPageScaffold(
// navigationBar: CupertinoNavigationBar(
// middle: Text('Menu'.tr),
// ),
// child: SafeArea(
// child: CustomScrollView(
// slivers: [
// const SliverToBoxAdapter(child: const UserAccountHeader()),
// SliverList(
// delegate: SliverChildListDelegate([
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.money_dollar,
// text: 'Wallet'.tr,
// onTap: () => Get.to(() => WalletCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.person,
// text: 'Profile'.tr,
// onTap: () => Get.to(() => ProfileCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.clock,
// text: 'History of Trip'.tr,
// onTap: () => Get.to(() => const HistoryCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.car_detailed,
// text: 'Available for rides'.tr,
// onTap: () => Get.to(() => const AvailableRidesPage()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.bell,
// text: 'Notifications'.tr,
// onTap: () => Get.to(() => const NotificationCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.question_circle,
// text: 'Helping Center'.tr,
// onTap: () => Get.to(() => HelpCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.share,
// text: 'Share App'.tr,
// onTap: () => Get.to(() => InviteScreen()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.wrench,
// text: "Maintenance Center".tr,
// onTap: () => Get.to(() => MaintainCenterPage()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon:
// CupertinoIcons.heart, // Updated icon to represent health
// text: "Health Insurance".tr, // Updated English text
// onTap: () => Get.to(() => AssuranceHealthPage()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.mail,
// text: "Contact Us".tr,
// onTap: () => Get.to(() => ContactUsPage()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon:
// Icons.play_circle_filled, // Icon representing video play
// text: 'Videos Tutorials'.tr,
// onTap: () => Get.to(() => VideoListPage()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: Icons.star, // Another option with a filled star icon
// text: "Rate Our App".tr,
// onTap: () => Get.to(() => RatingScreen()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.settings,
// text: 'Settings'.tr,
// onTap: () => Get.to(() => const SettingsCaptain()),
// ),
// _buildDivider(),
// _buildDrawerItem(
// icon: CupertinoIcons.square_arrow_right,
// text: 'Sign Out'.tr,
// onTap: () => Get.to(() => const LogoutCaptain()),
// ),
// _buildDivider(),
// ]),
// ),
// ],
// ),
// ),
// );
// }
// Widget _buildDivider() {
// return const Divider(
// thickness: 1,
// height: 1,
// color: CupertinoColors.systemGrey4,
// );
// }
// Widget _buildDrawerItem({
// required IconData icon,
// required String text,
// required VoidCallback onTap,
// }) {
// return CupertinoButton(
// onPressed: onTap,
// child: Row(
// children: [
// Icon(icon, color: CupertinoColors.activeBlue),
// const SizedBox(width: 10),
// Text(text, style: const TextStyle(color: CupertinoColors.label)),
// const Spacer(),
// const Icon(CupertinoIcons.right_chevron,
// color: CupertinoColors.systemGrey),
// ],
// ),
// );
// }
// }
// class UserAccountHeader extends StatelessWidget {
// const UserAccountHeader({super.key});
// @override
// Widget build(BuildContext context) {
// return Container(
// padding: const EdgeInsets.all(16),
// decoration: const BoxDecoration(
// gradient: LinearGradient(
// colors: [AppColor.blueColor, AppColor.twitterColor],
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// ),
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// GetBuilder<ImageController>(
// builder: (imageController) {
// return Stack(
// children: [
// imageController.isloading
// ? const CupertinoActivityIndicator()
// : Container(
// width: 100,
// height: 100,
// decoration: BoxDecoration(
// shape: BoxShape.circle,
// image: DecorationImage(
// fit: BoxFit.cover,
// image: NetworkImage(
// '${AppLink.seferCairoServer}/portrate_captain_image/${box.read(BoxName.driverID)}.jpg',
// ),
// ),
// ),
// ),
// Positioned(
// right: 0,
// top: 0,
// child: CupertinoButton(
// onPressed: () {
// imageController.choosImagePicture(
// AppLink.uploadImage1, 'portrait');
// },
// child: const Icon(CupertinoIcons.pencil_circle_fill,
// color: CupertinoColors.white),
// ),
// ),
// ],
// );
// },
// ),
// const SizedBox(height: 10),
// Text(
// '${box.read(BoxName.nameDriver).toString().split(' ')[0]} ${box.read(BoxName.nameDriver).toString().split(' ')[1]}',
// style: const TextStyle(
// color: CupertinoColors.white,
// fontSize: 18,
// fontWeight: FontWeight.bold),
// ),
// const SizedBox(height: 5),
// Text(
// box.read(BoxName.emailDriver),
// style: const TextStyle(color: CupertinoColors.white, fontSize: 14),
// ),
// const SizedBox(height: 10),
// Row(
// children: [
// Text(
// Get.find<HomeCaptainController>().rating.toString(),
// style: const TextStyle(
// color: CupertinoColors.systemYellow, fontSize: 16),
// ),
// const SizedBox(width: 5),
// // You might want to replace this with a Cupertino-style rating widget
// // For now, we'll use text to represent stars
// // const Text('★★★★★',
// // style: TextStyle(color: CupertinoColors.systemYellow)),
// Container(
// padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
// color: AppColor.greenColor,
// child: RatingBar.builder(
// initialRating: double.parse(
// Get.find<HomeCaptainController>().rating.toString()),
// minRating: 1,
// direction: Axis.horizontal,
// itemCount: 5,
// itemSize: 20,
// itemPadding: const EdgeInsets.symmetric(horizontal: 2),
// itemBuilder: (context, _) => const Icon(
// Icons.star,
// color: Colors.amber,
// ),
// onRatingUpdate: (rating) {},
// ),
// ),
// ],
// ),
// ],
// ),
// );
// }
// }
class CupertinoDrawerCaptain extends StatelessWidget {
final ImageController imageController = Get.put(ImageController());
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
backgroundColor: CupertinoColors.systemGroupedBackground,
navigationBar: CupertinoNavigationBar(
middle: Text('Menu'.tr),
middle: Text('Menu'.tr,
style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600)),
backgroundColor: Colors.transparent,
border: null,
),
child: SafeArea(
child: CustomScrollView(
slivers: [
const SliverToBoxAdapter(child: const UserAccountHeader()),
const SliverToBoxAdapter(child: UserAccountHeader()),
SliverList(
delegate: SliverChildListDelegate([
_buildDivider(),
const SizedBox(height: 10),
_buildSectionHeader('Account'.tr),
_buildDrawerItem(
icon: CupertinoIcons.money_dollar,
icon: CupertinoIcons.money_dollar_circle_fill,
text: 'Wallet'.tr,
onTap: () => Get.to(() => WalletCaptain()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.person,
icon: CupertinoIcons.person_fill,
text: 'Profile'.tr,
onTap: () => Get.to(() => ProfileCaptain()),
),
_buildDivider(),
_buildSectionHeader('Activities'.tr),
_buildDrawerItem(
icon: CupertinoIcons.clock,
icon: CupertinoIcons.clock_fill,
text: 'History of Trip'.tr,
onTap: () => Get.to(() => const HistoryCaptain()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.car_detailed,
icon: CupertinoIcons.car_fill,
text: 'Available for rides'.tr,
onTap: () => Get.to(() => const AvailableRidesPage()),
),
_buildDivider(),
_buildSectionHeader('Support'.tr),
_buildDrawerItem(
icon: CupertinoIcons.bell,
icon: CupertinoIcons.bell_fill,
text: 'Notifications'.tr,
onTap: () => Get.to(() => const NotificationCaptain()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.question_circle,
icon: CupertinoIcons.question_circle_fill,
text: 'Helping Center'.tr,
onTap: () => Get.to(() => HelpCaptain()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.share,
text: 'Share App'.tr,
onTap: () => Get.to(() => InviteScreen()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.wrench,
text: "Maintenance Center".tr,
onTap: () => Get.to(() => MaintainCenterPage()),
),
_buildDivider(),
_buildDrawerItem(
icon:
CupertinoIcons.heart, // Updated icon to represent health
text: "Health Insurance".tr, // Updated English text
onTap: () => Get.to(() => AssuranceHealthPage()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.mail,
text: "Contact Us".tr,
onTap: () => Get.to(() => ContactUsPage()),
),
_buildDivider(),
_buildDrawerItem(
icon:
Icons.play_circle_filled, // Icon representing video play
text: 'Videos Tutorials'.tr,
onTap: () => Get.to(() => VideoListPage()),
),
_buildDivider(),
_buildDrawerItem(
icon: Icons.star, // Another option with a filled star icon
text: "Rate Our App".tr,
onTap: () => Get.to(() => RatingScreen()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.settings,
text: 'Settings'.tr,
onTap: () => Get.to(() => const SettingsCaptain()),
),
_buildDivider(),
_buildDrawerItem(
icon: CupertinoIcons.square_arrow_right,
text: 'Sign Out'.tr,
onTap: () => Get.to(() => const LogoutCaptain()),
),
_buildDivider(),
_buildSectionHeader('More'.tr),
...moreMenuItems(),
]),
),
],
@@ -135,11 +332,61 @@ class CupertinoDrawerCaptain extends StatelessWidget {
);
}
Widget _buildDivider() {
return const Divider(
thickness: 1,
height: 1,
color: CupertinoColors.systemGrey4,
List<Widget> moreMenuItems() => [
_buildDrawerItem(
icon: CupertinoIcons.share_up,
text: 'Share App'.tr,
onTap: () => Get.to(() => InviteScreen()),
),
_buildDrawerItem(
icon: CupertinoIcons.wrench_fill,
text: "Maintenance Center".tr,
onTap: () => Get.to(() => MaintainCenterPage()),
),
_buildDrawerItem(
icon: CupertinoIcons.heart_fill,
text: "Health Insurance".tr,
onTap: () => Get.to(() => AssuranceHealthPage()),
),
_buildDrawerItem(
icon: CupertinoIcons.mail_solid,
text: "Contact Us".tr,
onTap: () => Get.to(() => ContactUsPage()),
),
_buildDrawerItem(
icon: CupertinoIcons.play_circle_fill,
text: 'Videos Tutorials'.tr,
onTap: () => Get.to(() => VideoListPage()),
),
_buildDrawerItem(
icon: CupertinoIcons.star_fill,
text: "Rate Our App".tr,
onTap: () => Get.to(() => RatingScreen()),
),
_buildDrawerItem(
icon: CupertinoIcons.settings_solid,
text: 'Settings'.tr,
onTap: () => Get.to(() => const SettingsCaptain()),
),
_buildDrawerItem(
icon: CupertinoIcons.square_arrow_right,
text: 'Sign Out'.tr,
onTap: () => Get.to(() => const LogoutCaptain()),
isDestructive: true,
),
];
Widget _buildSectionHeader(String title) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
title,
style: const TextStyle(
color: CupertinoColors.systemGrey,
fontSize: 13,
fontWeight: FontWeight.w600,
),
),
);
}
@@ -147,18 +394,45 @@ class CupertinoDrawerCaptain extends StatelessWidget {
required IconData icon,
required String text,
required VoidCallback onTap,
bool isDestructive = false,
}) {
return CupertinoButton(
onPressed: onTap,
child: Row(
children: [
Icon(icon, color: CupertinoColors.activeBlue),
const SizedBox(width: 10),
Text(text, style: const TextStyle(color: CupertinoColors.label)),
const Spacer(),
const Icon(CupertinoIcons.right_chevron,
color: CupertinoColors.systemGrey),
],
return Container(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: CupertinoColors.white,
borderRadius: BorderRadius.circular(10),
),
child: CupertinoButton(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
onPressed: onTap,
child: Row(
children: [
Icon(
icon,
color: isDestructive
? CupertinoColors.destructiveRed
: CupertinoColors.activeBlue,
size: 22,
),
const SizedBox(width: 12),
Text(
text,
style: AppStyle.title,
// TextStyle(
// color: isDestructive
// ? CupertinoColors.destructiveRed
// : CupertinoColors.label,
// fontSize: 16,
// ),
),
const Spacer(),
Icon(
CupertinoIcons.chevron_right,
color: CupertinoColors.systemGrey3,
size: 18,
),
],
),
),
);
}
@@ -170,13 +444,20 @@ class UserAccountHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [AppColor.blueColor, AppColor.twitterColor],
padding: const EdgeInsets.fromLTRB(20, 20, 20, 24),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [AppColor.blueColor, Color(0xFF2196F3)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(10),
blurRadius: 10,
spreadRadius: 2,
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -185,83 +466,122 @@ class UserAccountHeader extends StatelessWidget {
builder: (imageController) {
return Stack(
children: [
imageController.isloading
? const CupertinoActivityIndicator()
: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 3),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 8,
spreadRadius: 2,
),
],
),
child: imageController.isloading
? const CupertinoActivityIndicator()
: ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.network(
'${AppLink.seferCairoServer}/portrate_captain_image/${box.read(BoxName.driverID)}.jpg',
fit: BoxFit.cover,
image: NetworkImage(
'${AppLink.seferCairoServer}/portrate_captain_image/${box.read(BoxName.driverID)}.jpg',
),
),
),
),
),
Positioned(
right: 0,
top: 0,
bottom: 0,
child: CupertinoButton(
padding: EdgeInsets.zero,
onPressed: () {
imageController.choosImagePicture(
AppLink.uploadImage1, 'portrait');
},
child: const Icon(CupertinoIcons.pencil_circle_fill,
color: CupertinoColors.white),
child: Container(
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: const Icon(
CupertinoIcons.camera_fill,
color: AppColor.blueColor,
size: 20,
),
),
),
),
],
);
},
),
const SizedBox(height: 10),
const SizedBox(height: 16),
Text(
'${box.read(BoxName.nameDriver).toString().split(' ')[0]} ${box.read(BoxName.nameDriver).toString().split(' ')[1]}',
style: const TextStyle(
color: CupertinoColors.white,
fontSize: 18,
fontWeight: FontWeight.bold),
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
shadows: [
Shadow(
color: Colors.black26,
blurRadius: 2,
offset: Offset(0, 1),
),
],
),
),
const SizedBox(height: 5),
const SizedBox(height: 4),
Text(
box.read(BoxName.emailDriver),
style: const TextStyle(color: CupertinoColors.white, fontSize: 14),
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 14,
),
),
const SizedBox(height: 10),
Row(
children: [
Text(
Get.find<HomeCaptainController>().rating.toString(),
style: const TextStyle(
color: CupertinoColors.systemYellow, fontSize: 16),
),
const SizedBox(width: 5),
// You might want to replace this with a Cupertino-style rating widget
// For now, we'll use text to represent stars
// const Text('★★★★★',
// style: TextStyle(color: CupertinoColors.systemYellow)),
Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
color: AppColor.greenColor,
child: RatingBar.builder(
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.15),
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// const Icon(
// CupertinoIcons.star_fill,
// color: CupertinoColors.systemYellow,
// size: 18,
// ),
// const SizedBox(width: 4),
Text(
Get.find<HomeCaptainController>().rating.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SizedBox(width: 8),
RatingBar.builder(
initialRating: double.parse(
Get.find<HomeCaptainController>().rating.toString()),
minRating: 1,
direction: Axis.horizontal,
itemCount: 5,
itemSize: 20,
itemPadding: const EdgeInsets.symmetric(horizontal: 2),
itemSize: 16,
ignoreGestures: true,
itemBuilder: (context, _) => const Icon(
Icons.star,
color: Colors.amber,
CupertinoIcons.star_fill,
color: CupertinoColors.systemYellow,
),
onRatingUpdate: (rating) {},
),
),
],
],
),
),
],
),

View File

@@ -4,6 +4,11 @@ import 'package:sefer_driver/controller/home/captin/help/help_controller.dart';
import 'package:sefer_driver/views/home/Captin/home_captain/help_details_replay_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/controller/home/captin/help/help_controller.dart';
import 'package:sefer_driver/views/home/Captin/home_captain/help_details_replay_page.dart';
class HelpCaptain extends StatelessWidget {
HelpCaptain({super.key});
@@ -13,116 +18,131 @@ class HelpCaptain extends StatelessWidget {
Get.put(HelpController());
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Helping Page'.tr),
middle: Text(
'Helping Page'.tr,
style: const TextStyle(fontWeight: FontWeight.bold),
),
leading: CupertinoButton(
padding: EdgeInsets.zero,
child: Icon(CupertinoIcons.back),
onPressed: () => Navigator.pop(context),
child: const Icon(CupertinoIcons.back),
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
padding: const EdgeInsets.all(
20.0), // Increased padding around the content
child: ListView(
// crossAxisAlignment:
// CrossAxisAlignment.stretch, // Stretch children to full width
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
border: Border.all(
color: CupertinoColors.systemGrey2,
),
),
child: Text(
'If you need any help or have questions, this is the right place to do that. You are welcome!'
.tr,
style: CupertinoTheme.of(context).textTheme.textStyle,
textAlign: TextAlign.center,
),
Container(
padding:
const EdgeInsets.all(18.0), // Slightly increased padding
decoration: BoxDecoration(
color:
CupertinoTheme.of(context).brightness == Brightness.light
? CupertinoColors.systemGrey6
: CupertinoColors.darkBackgroundGray,
borderRadius:
BorderRadius.circular(15.0), // More rounded corners
),
),
Card(
elevation: 3,
color: CupertinoColors.systemGrey6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: GetBuilder<HelpController>(
builder: (helpController) => Form(
key: helpController.formKey,
child: Column(
children: [
CupertinoTextField(
controller: helpController.helpQuestionController,
placeholder: 'Enter your Question here'.tr,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: CupertinoColors.systemGrey,
),
),
padding: const EdgeInsets.all(16),
clearButtonMode: OverlayVisibilityMode.editing,
child: Text(
'If you need any help or have questions, this is the right place to do that. You are welcome!'
.tr,
style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16, // Slightly larger font size
color: CupertinoColors.label.resolveFrom(
context), // Ensure text color adapts to theme
),
const SizedBox(height: 20),
helpController.isLoading
? const CupertinoActivityIndicator()
: CupertinoButton.filled(
onPressed: () {
if (helpController.formKey.currentState!
.validate()) {
helpController.addHelpQuestion();
// Clear the feedback form
helpController.formKey.currentState!
.reset();
}
},
child: Text('Submit Question'.tr),
),
],
),
),
),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 20),
CupertinoFormSection.insetGrouped(
// Using CupertinoFormSection for better styling
header: Text('Submit Your Question'.tr),
margin: EdgeInsets.zero,
children: [
GetBuilder<HelpController>(
builder: (helpController) => Form(
key: helpController.formKey,
child: CupertinoTextFormFieldRow(
controller: helpController.helpQuestionController,
placeholder: 'Enter your Question here'.tr,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your question'.tr;
}
return null;
},
prefix: const Icon(CupertinoIcons
.question_circle), // Added a prefix icon
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0, vertical: 10.0),
child: GetBuilder<HelpController>(
builder: (helpController) => helpController.isLoading
? const CupertinoActivityIndicator()
: CupertinoButton.filled(
onPressed: () {
if (helpController.formKey.currentState!
.validate()) {
helpController.addHelpQuestion();
helpController.helpQuestionController
.clear(); // Clear the text field
}
},
child: Text('Submit Question'.tr),
),
),
),
],
),
const SizedBox(height: 20),
Text(
'Your Questions'.tr,
style: CupertinoTheme.of(context)
.textTheme
.navTitleTextStyle
.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Expanded(
child: GetBuilder<HelpController>(
builder: (helpController) => Padding(
padding: const EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: CupertinoColors.systemGrey2,
),
borderRadius: BorderRadius.circular(12.0),
),
child: ListView.builder(
itemCount: helpController.helpQuestionDate['message'] !=
null
? helpController.helpQuestionDate['message'].length
: 0,
itemBuilder: (BuildContext context, int index) {
var list =
helpController.helpQuestionDate['message'][index];
return Padding(
padding: const EdgeInsets.all(3),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 16),
decoration: BoxDecoration(
border: Border.all(
color: CupertinoColors.activeGreen,
width: 2,
builder: (helpController) =>
CupertinoListSection.insetGrouped(
margin: EdgeInsets.zero,
children: helpController.helpQuestionDate['message'] != null
? List.generate(
helpController.helpQuestionDate['message'].length,
(index) {
var list = helpController
.helpQuestionDate['message'][index];
return CupertinoListTile(
title: Text(
list['helpQuestion'],
overflow: TextOverflow.ellipsis,
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
list['datecreated'],
style: CupertinoTheme.of(context)
.textTheme
.tabLabelTextStyle,
),
const Icon(CupertinoIcons.chevron_forward),
],
),
borderRadius: BorderRadius.circular(12),
),
child: GestureDetector(
onTap: () {
helpController.getIndex(
list['id'], list['helpQuestion']);
@@ -130,33 +150,14 @@ class HelpCaptain extends StatelessWidget {
.getHelpRepley(list['id'].toString());
Get.to(() => const HelpDetailsReplayPage());
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
list['helpQuestion'],
style: CupertinoTheme.of(context)
.textTheme
.textStyle,
overflow: TextOverflow.ellipsis,
),
),
Text(
list['datecreated'],
style: CupertinoTheme.of(context)
.textTheme
.tabLabelTextStyle,
),
],
),
),
);
},
)
: [
Center(
child: Text('No questions asked yet.'.tr),
),
);
},
),
),
],
),
),
),
@@ -167,3 +168,165 @@ class HelpCaptain extends StatelessWidget {
);
}
}
// class HelpCaptain extends StatelessWidget {
// HelpCaptain({super.key});
// @override
// Widget build(BuildContext context) {
// Get.put(HelpController());
// return CupertinoPageScaffold(
// navigationBar: CupertinoNavigationBar(
// middle: Text('Helping Page'.tr),
// leading: CupertinoButton(
// padding: EdgeInsets.zero,
// child: Icon(CupertinoIcons.back),
// onPressed: () => Navigator.pop(context),
// ),
// ),
// child: SafeArea(
// child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: Column(
// children: [
// Padding(
// padding: const EdgeInsets.symmetric(vertical: 12.0),
// child: Container(
// padding: const EdgeInsets.all(16.0),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12.0),
// border: Border.all(
// color: CupertinoColors.systemGrey2,
// ),
// ),
// child: Text(
// 'If you need any help or have questions, this is the right place to do that. You are welcome!'
// .tr,
// style: CupertinoTheme.of(context).textTheme.textStyle,
// textAlign: TextAlign.center,
// ),
// ),
// ),
// Card(
// elevation: 3,
// color: CupertinoColors.systemGrey6,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: GetBuilder<HelpController>(
// builder: (helpController) => Form(
// key: helpController.formKey,
// child: Column(
// children: [
// CupertinoTextField(
// controller: helpController.helpQuestionController,
// placeholder: 'Enter your Question here'.tr,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12),
// border: Border.all(
// color: CupertinoColors.systemGrey,
// ),
// ),
// padding: const EdgeInsets.all(16),
// clearButtonMode: OverlayVisibilityMode.editing,
// ),
// const SizedBox(height: 20),
// helpController.isLoading
// ? const CupertinoActivityIndicator()
// : CupertinoButton.filled(
// onPressed: () {
// if (helpController.formKey.currentState!
// .validate()) {
// helpController.addHelpQuestion();
// // Clear the feedback form
// helpController.formKey.currentState!
// .reset();
// }
// },
// child: Text('Submit Question'.tr),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
// const SizedBox(height: 20),
// Expanded(
// child: GetBuilder<HelpController>(
// builder: (helpController) => Padding(
// padding: const EdgeInsets.all(10),
// child: Container(
// decoration: BoxDecoration(
// border: Border.all(
// color: CupertinoColors.systemGrey2,
// ),
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: ListView.builder(
// itemCount: helpController.helpQuestionDate['message'] !=
// null
// ? helpController.helpQuestionDate['message'].length
// : 0,
// itemBuilder: (BuildContext context, int index) {
// var list =
// helpController.helpQuestionDate['message'][index];
// return Padding(
// padding: const EdgeInsets.all(3),
// child: Container(
// padding: const EdgeInsets.symmetric(
// vertical: 12, horizontal: 16),
// decoration: BoxDecoration(
// border: Border.all(
// color: CupertinoColors.activeGreen,
// width: 2,
// ),
// borderRadius: BorderRadius.circular(12),
// ),
// child: GestureDetector(
// onTap: () {
// helpController.getIndex(
// list['id'], list['helpQuestion']);
// helpController
// .getHelpRepley(list['id'].toString());
// Get.to(() => const HelpDetailsReplayPage());
// },
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment.spaceBetween,
// children: [
// Expanded(
// child: Text(
// list['helpQuestion'],
// style: CupertinoTheme.of(context)
// .textTheme
// .textStyle,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// Text(
// list['datecreated'],
// style: CupertinoTheme.of(context)
// .textTheme
// .tabLabelTextStyle,
// ),
// ],
// ),
// ),
// ),
// );
// },
// ),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// );
// }
// }

View File

@@ -47,22 +47,92 @@ class HomeCaptain extends StatelessWidget {
});
return Scaffold(
appBar: AppBar(
// backgroundColor: AppColor.accentColor,
elevation: 1,
title: Text(
'SEFER'.tr,
style: AppStyle.title.copyWith(fontSize: 22),
elevation: 2,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.grey.shade50],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 4,
),
],
),
),
title: Row(
children: [
Image.asset('assets/images/logo.png', height: 32),
const SizedBox(width: 8),
Text(
'SEFER'.tr,
style: AppStyle.title.copyWith(
fontSize: 22,
fontWeight: FontWeight.w600,
color: AppColor.blueColor,
),
),
],
),
actions: [
MyCircleContainer(
child: Text(
homeCaptainController.countRefuse.toString(),
style: AppStyle.title,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: MyCircleContainer(
child: Text(
homeCaptainController.countRefuse.toString(),
style: AppStyle.title,
),
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 4,
),
],
),
child: Row(
children: [
_MapControlButton(
icon: Icons.satellite_alt,
tooltip: 'Change Map Type'.tr,
onPressed: homeCaptainController.changeMapType,
),
_MapControlButton(
icon: Icons.streetview_sharp,
tooltip: 'Toggle Traffic'.tr,
onPressed: homeCaptainController.changeMapTraffic,
),
_MapControlButton(
icon: Icons.location_on,
tooltip: 'My Location'.tr,
onPressed: () {
homeCaptainController.mapHomeCaptainController!
.animateCamera(CameraUpdate.newLatLng(LatLng(
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
)));
},
),
],
),
),
const SizedBox(width: 8),
],
),
drawer: CupertinoDrawerCaptain(),
drawer:
CupertinoDrawerCaptain(), // Add this widget at the bottom of the file
body: Stack(
children: [
GetBuilder<HomeCaptainController>(builder: (homeCaptainController) {
@@ -419,28 +489,34 @@ class HomeCaptain extends StatelessWidget {
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
box.read(BoxName.rideStatus) == 'Applied'
? {
Get.to(() => PassengerLocationMapPage(),
arguments:
box.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.changeRideToBeginToPassenger()
}
: {
Get.to(() => PassengerLocationMapPage(),
arguments:
box.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.startRideFromStartApp()
};
child: GestureDetector(
onLongPress: () {
box.write(BoxName.rideStatus, 'delete');
homeCaptainController.update();
},
icon: const Icon(
Icons.rice_bowl,
size: 29,
color: AppColor.blueColor,
child: IconButton(
onPressed: () {
box.read(BoxName.rideStatus) == 'Applied'
? {
Get.to(() => PassengerLocationMapPage(),
arguments: box
.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.changeRideToBeginToPassenger()
}
: {
Get.to(() => PassengerLocationMapPage(),
arguments: box
.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.startRideFromStartApp()
};
},
icon: const Icon(
Icons.rice_bowl,
size: 29,
color: AppColor.blueColor,
),
),
),
),
@@ -599,3 +675,37 @@ bool _checkIfFirstTime() {
void _markAsNotFirstTime() {
box.write(BoxName.isFirstTime, 'false');
}
class _MapControlButton extends StatelessWidget {
final IconData icon;
final VoidCallback onPressed;
final String tooltip;
const _MapControlButton({
required this.icon,
required this.onPressed,
required this.tooltip,
});
@override
Widget build(BuildContext context) {
return Tooltip(
message: tooltip,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: onPressed,
child: Container(
padding: const EdgeInsets.all(8),
child: Icon(
icon,
size: 24,
color: AppColor.blueColor,
),
),
),
),
);
}
}

View File

@@ -1,18 +1,14 @@
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/firebase/local_notification.dart';
import 'package:sefer_driver/main.dart';
import 'package:sefer_driver/views/auth/captin/cards/egypt_card_a_i.dart';
import 'package:sefer_driver/views/home/Captin/orderCaptin/vip_order_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../../../../../constant/colors.dart';
import '../../../../Rate/ride_calculate_driver.dart';
import '../../../../../controller/functions/location_controller.dart';
import '../../../../widgets/mydialoug.dart';
GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
return GetBuilder<HomeCaptainController>(
@@ -21,113 +17,6 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
left: 6,
child: Column(
children: [
// AnimatedContainer(
// duration: const Duration(microseconds: 200),
// width: controller.widthMapTypeAndTraffic,
// decoration: BoxDecoration(
// border: Border.all(color: AppColor.blueColor),
// color: AppColor.secondaryColor,
// borderRadius: BorderRadius.circular(15)),
// child: IconButton(
// onPressed: () {
// // key.forEach((key, apiKey) {
// // Get.to(() => SmsSignupEgypt());
// // keys.forEach((key, apiKey) {
// String apikey = AK.secretKeyStripe;
// Log.print('apikey: ${apikey}');
// String encryptedApiKey = X.c(X.c(X.c(apikey, cs), cC), cn);
// Log.print('encryptedApiKey: ${encryptedApiKey}');
// String decryptedApiKey =
// X.r(X.r(X.r(encryptedApiKey, cn), cC), cs);
// Log.print('decryptedApiKey: ${decryptedApiKey}');
// // if (decryptedApiKey == retrievedStringS) {
// // } else {
// // }
// // }
// // );
// },
// icon: const Icon(
// FontAwesome.map_signs,
// size: 24,
// color: Colors.black,
// )),
// ),
// const SizedBox(
// height: 5,
// ),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
controller.changeMapType();
// Toast.show(context, 'This is a toast message!');
},
icon: const Icon(
Icons.satellite_alt,
size: 29,
color: AppColor.blueColor,
),
),
),
const SizedBox(
height: 5,
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
decoration: BoxDecoration(
color: AppColor.secondaryColor,
border: Border.all(color: AppColor.blueColor),
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
controller.changeMapTraffic();
// Toast.show(context, 'This is a toast message!');
},
icon: const Icon(
Icons.streetview_sharp,
size: 29,
color: AppColor.blueColor,
),
),
),
const SizedBox(
height: 5,
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
decoration: BoxDecoration(
color: AppColor.secondaryColor,
border: Border.all(color: AppColor.blueColor),
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
controller.mapHomeCaptainController!
.animateCamera(CameraUpdate.newLatLng(LatLng(
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
)));
},
icon: const Icon(
Icons.location_on,
size: 29,
color: AppColor.blueColor,
),
),
),
const SizedBox(
height: 5,
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
@@ -211,7 +100,7 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
// child: Builder(builder: (context) {
// return IconButton(
// onPressed: () async {
// Get.to(EgyptCardAI());
// MyCircularProgressIndicator();
// },
// icon: const Icon(
// FontAwesome5.grin_tears,

View File

@@ -6,93 +6,253 @@ import 'package:sefer_driver/views/widgets/my_scafold.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// class MaintainCenterPage extends StatelessWidget {
// MaintainCenterPage({super.key});
// MaintainCenterController maintainCenterController =
// Get.put(MaintainCenterController());
// @override
// Widget build(BuildContext context) {
// return MyScafolld(
// title: "Maintenance Center".tr,
// body: [
// GetBuilder<MaintainCenterController>(
// builder: (maintainCenterController) {
// return Padding(
// padding: const EdgeInsets.all(8.0),
// child: Column(
// children: [
// Text(
// "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car."
// .tr),
// const SizedBox(
// height: 10,
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: [
// MyElevatedButton(
// title: "Show My Trip Count".tr,
// onPressed: () async {
// maintainCenterController.getTripCountByCaptain();
// }),
// _buildPriceAvatar(
// maintainCenterController.tripCount['count'] == null
// ? '0'
// : maintainCenterController.tripCount['count']
// .toString())
// ],
// ),
// const SizedBox(
// height: 10,
// ),
// Container(
// decoration: AppStyle.boxDecoration,
// child: Padding(
// padding: const EdgeInsets.all(14),
// child: Text(
// "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
// .tr,
// style: AppStyle.title,
// ),
// ),
// ),
// const SizedBox(
// height: 10,
// ),
// MyElevatedButton(
// title: 'Show maintenance center near my location'.tr,
// onPressed: () {
// if (maintainCenterController.tripCount['count'] > 600) {
// } else {
// Get.snackbar("You should complete 600 trips".tr, '',
// backgroundColor: AppColor.yellowColor);
// }
// })
// ],
// ),
// );
// })
// ],
// isleading: true);
// }
// Widget _buildPriceAvatar(String count) {
// return Container(
// width: 80,
// height: 80,
// decoration: BoxDecoration(
// shape: BoxShape.circle,
// gradient: const RadialGradient(
// colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)],
// center: Alignment.center,
// radius: 0.8,
// ),
// boxShadow: [
// BoxShadow(
// color: Colors.black.withOpacity(0.2),
// blurRadius: 8,
// offset: const Offset(0, 4),
// ),
// ],
// ),
// child: Center(
// child: Text(
// count,
// style: const TextStyle(
// fontSize: 22,
// fontWeight: FontWeight.bold,
// color: Colors.white,
// ),
// ),
// ),
// );
// }
// }
class MaintainCenterPage extends StatelessWidget {
MaintainCenterPage({super.key});
MaintainCenterController maintainCenterController =
final MaintainCenterController maintainCenterController =
Get.put(MaintainCenterController());
@override
Widget build(BuildContext context) {
return MyScafolld(
title: "Maintenance Center".tr,
body: [
GetBuilder<MaintainCenterController>(
builder: (maintainCenterController) {
title: "Maintenance Center".tr,
body: [
GetBuilder<MaintainCenterController>(
builder: (controller) {
return Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Introduction Text with better styling
Text(
"When you complete 600 trips, you will be eligible to receive offers for maintenance of your car."
.tr),
const SizedBox(
height: 10,
"When you complete 600 trips, you will be eligible to receive offers for maintenance of your car."
.tr,
style: Theme.of(context).textTheme.titleMedium!.copyWith(
color: Colors.grey[700],
height: 1.4,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MyElevatedButton(
title: "Show My Trip Count".tr,
onPressed: () async {
maintainCenterController.getTripCountByCaptain();
}),
_buildPriceAvatar(
maintainCenterController.tripCount['count'] == null
? '0'
: maintainCenterController.tripCount['count']
.toString())
],
),
const SizedBox(
height: 10,
),
Container(
decoration: AppStyle.boxDecoration,
const SizedBox(height: 20),
// Trip Count Section in a Card
Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(14),
child: Text(
"We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
.tr,
style: AppStyle.title,
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: MyElevatedButton(
title: "Show My Trip Count".tr,
onPressed: () async {
controller.getTripCountByCaptain();
},
),
),
const SizedBox(width: 16),
_buildPriceAvatar(
controller.tripCount['count'] == null
? '0'
: controller.tripCount['count'].toString(),
),
],
),
),
),
const SizedBox(
height: 10,
const SizedBox(height: 20),
// Maintenance Offer Information in a Card
Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Maintenance Offer".tr,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
Text(
"We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
.tr,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Colors.grey[800],
height: 1.5,
),
),
],
),
),
),
MyElevatedButton(
const SizedBox(height: 20),
// Show Maintenance Center Button
SizedBox(
width: double.infinity,
child: MyElevatedButton(
title: 'Show maintenance center near my location'.tr,
onPressed: () {
if (maintainCenterController.tripCount['count'] > 600) {
if (controller.tripCount['count'] != null &&
controller.tripCount['count'] >= 600) {
// Implement navigation or action to show maintenance centers
// For now, let's print a message
print("Navigating to maintenance centers...");
} else {
Get.snackbar("You should complete 600 trips".tr, '',
backgroundColor: AppColor.yellowColor);
Get.snackbar(
"Ineligible for Offer".tr,
"You should complete 500 trips to unlock this feature."
.tr,
backgroundColor: AppColor.yellowColor,
colorText: Colors.black,
snackPosition: SnackPosition.BOTTOM,
);
}
})
},
),
),
],
),
);
})
],
isleading: true);
},
),
],
isleading: true,
);
}
Widget _buildPriceAvatar(String count) {
return Container(
width: 80,
height: 80,
width: 70, // Slightly reduced size
height: 70,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: const RadialGradient(
gradient: const LinearGradient(
// Changed to LinearGradient
colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)],
center: Alignment.center,
radius: 0.8,
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 8,
offset: const Offset(0, 4),
color: Colors.black.withOpacity(0.15), // Reduced opacity
blurRadius: 6, // Slightly reduced blur
offset: const Offset(0, 3),
),
],
),
@@ -100,7 +260,7 @@ class MaintainCenterPage extends StatelessWidget {
child: Text(
count,
style: const TextStyle(
fontSize: 22,
fontSize: 20, // Slightly reduced size
fontWeight: FontWeight.bold,
color: Colors.white,
),

View File

@@ -13,215 +13,249 @@ import '../../../widgets/elevated_btn.dart';
GetBuilder<MapDriverController> driverEndRideBar() {
return GetBuilder<MapDriverController>(
builder: (mapDriverController) => mapDriverController.isRideStarted
? Positioned(
left: 5,
top: 5,
right: 5,
child: Container(
decoration: AppStyle.boxDecoration1,
height: mapDriverController.remainingTimeTimerRideBegin < 60
? mapDriverController.driverEndPage = 190
: mapDriverController.carType == 'Mishwar Vip'
? 120
: 170,
// width: 240,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
mapDriverController.carType != 'Mishwar Vip'
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
const Icon(Icons.social_distance),
Text(
'${mapDriverController.distance} ${'KM'.tr}',
style: AppStyle.title,
),
],
),
Column(
children: [
const Icon(Icons.timelapse),
Text(
mapDriverController.hours > 1
? '${'${mapDriverController.hours}${' H and'.tr}'} ${mapDriverController.minutes} m'
: '${mapDriverController.minutes} ${'m'.tr}',
style: AppStyle.title),
],
),
Column(
children: [
const Icon(Icons.money_sharp),
Text(
'${mapDriverController.paymentAmount} ${'\$'.tr}',
style: AppStyle.title),
],
),
],
)
: const SizedBox(),
mapDriverController.carType != 'Speed' &&
mapDriverController.carType != 'Awfar Car' &&
mapDriverController.carType != 'Scooter'
? Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
width: Get.width * .2,
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(4),
child: Row(
children: [
const Icon(Icons.timer),
Text(
mapDriverController
.stringRemainingTimeRideBegin1,
style: AppStyle.number,
),
],
),
)),
Container(
width: Get.width * .2,
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(4),
child: Row(
children: [
const Icon(Icons.location_on),
Text(
'${mapDriverController.recentDistanceToDash.toStringAsFixed(0)} ${'KM'.tr}',
style: AppStyle.number,
),
],
),
),
),
Container(
width: Get.width * .2,
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Row(
children: [
const Icon(Icons.attach_money),
Text(
mapDriverController.price
.toStringAsFixed(2),
style: AppStyle.number,
),
],
),
),
),
],
)
: const SizedBox(),
// (mapDriverController.carType == 'Mashwari' ||
// mapDriverController.carType == 'Comfort' ||
// mapDriverController.carType == 'lady') &&
// mapDriverController.remainingTimeTimerRideBegin > 60
// ? Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: [
// MyElevatedButton(
// title: 'End Ride'.tr,
// onPressed: () {
// mapDriverController.finishRideFromDriver();
// },
// kolor: AppColor.redColor,
// ),
// Container(
// decoration: AppStyle.boxDecoration1,
// child: Text(
// mapDriverController.carType,
// style: AppStyle.title,
// ),
// )
// ],
// )
// :
builder: (mapDriverController) => mapDriverController.isRideStarted
? Positioned(
left: 5,
top: 5,
right: 5,
child: Container(
decoration: AppStyle.boxDecoration1.copyWith(
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
padding: const EdgeInsets.all(10),
height: mapDriverController.remainingTimeTimerRideBegin < 60
? mapDriverController.driverEndPage = 190
: mapDriverController.carType == 'Mishwar Vip'
? 120
: 170,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
if (mapDriverController.carType != 'Mishwar Vip')
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildInfoColumn(
icon: Icons.social_distance,
text: '${mapDriverController.distance} ${'KM'.tr}',
),
_buildInfoColumn(
icon: Icons.timelapse,
text: mapDriverController.hours > 1
? '${mapDriverController.hours} ${'H and'.tr} ${mapDriverController.minutes} m'
: '${mapDriverController.minutes} ${'m'.tr}',
),
_buildInfoColumn(
icon: Icons.money_sharp,
text:
'${mapDriverController.paymentAmount} ${'\$'.tr}',
),
],
),
if (mapDriverController.carType != 'Speed' &&
mapDriverController.carType != 'Awfar Car' &&
mapDriverController.carType != 'Scooter')
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// mapDriverController.remainingTimeTimerRideBegin <
// 60
// ?
SlideAction(
text: 'End Ride'.tr,
textStyle: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
outerColor: AppColor.redColor,
innerColor: Colors.white,
sliderButtonIcon: const Icon(
Icons.arrow_forward,
color: AppColor.redColor,
),
onSubmit: () {
mapDriverController.finishRideFromDriver();
},
_buildInfoBox(
icon: Icons.timer,
text:
mapDriverController.stringRemainingTimeRideBegin1,
),
_buildInfoBox(
icon: Icons.location_on,
text:
'${mapDriverController.recentDistanceToDash.toStringAsFixed(0)} ${'KM'.tr}',
),
_buildInfoBox(
icon: Icons.attach_money,
text: mapDriverController.price.toStringAsFixed(2),
),
// MyElevatedButton(
// title: 'End Ride'.tr,
// onPressed: () {
// mapDriverController.finishRideFromDriver();
// },
// kolor: AppColor.redColor,
// ),
// : const SizedBox(),
Container(
decoration: AppStyle.boxDecoration1,
child: Text(
mapDriverController.carType,
style: AppStyle.title,
),
)
],
),
mapDriverController.carType != 'Comfort' &&
mapDriverController.carType != 'Mishwar Vip' &&
mapDriverController.carType != 'Lady'
? Stack(
children: [
SizedBox(
width: Get.width * .9,
child: Center(
child: LinearProgressIndicator(
backgroundColor: AppColor.greyColor,
color: mapDriverController
.remainingTimeTimerRideBegin <
60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 25,
borderRadius: BorderRadius.circular(6),
value: mapDriverController
.progressTimerRideBegin
.toDouble(),
),
),
),
Center(
child: Text(
mapDriverController
.stringRemainingTimeRideBegin,
style: AppStyle.title,
),
)
],
)
: const SizedBox(),
],
_builtTimerAndCarType(),
Container(
width: Get.width * 0.8,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: AppColor.redColor.withOpacity(0.3),
blurRadius: 8,
offset: Offset(0, 4),
),
],
),
child: SlideAction(
height: 50,
borderRadius: 15,
elevation: 4,
text: 'Slide to End Trip'.tr,
textStyle: AppStyle.title.copyWith(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
outerColor: AppColor.redColor,
innerColor: Colors.white,
sliderButtonIcon: const Icon(
Icons.arrow_forward_ios,
color: AppColor.redColor,
size: 24,
),
sliderRotate: false,
onSubmit: () {
HapticFeedback.mediumImpact();
mapDriverController.finishRideFromDriver();
},
),
)
],
),
),
)
: const SizedBox(),
);
}
class _builtTimerAndCarType extends StatelessWidget {
const _builtTimerAndCarType({
super.key,
});
@override
Widget build(BuildContext context) {
final mapDriverController = Get.find<MapDriverController>();
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
decoration: AppStyle.boxDecoration1.copyWith(
boxShadow: [
BoxShadow(
color: AppColor.accentColor.withOpacity(0.2),
blurRadius: 8,
offset: Offset(0, 4),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text(
mapDriverController.carType,
style: AppStyle.title,
),
),
if (mapDriverController.carType != 'Comfort' &&
mapDriverController.carType != 'Mishwar Vip' &&
mapDriverController.carType != 'Lady')
Container(
width: Get.width * 0.6,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
gradient: LinearGradient(
colors: [
mapDriverController.remainingTimeTimerRideBegin < 60
? AppColor.redColor.withOpacity(0.8)
: AppColor.greenColor.withOpacity(0.8),
mapDriverController.remainingTimeTimerRideBegin < 60
? AppColor.redColor
: AppColor.greenColor,
],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
boxShadow: [
BoxShadow(
color: (mapDriverController.remainingTimeTimerRideBegin < 60
? AppColor.redColor
: AppColor.greenColor)
.withOpacity(0.3),
blurRadius: 8,
offset: Offset(0, 4),
),
))
: const SizedBox());
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Stack(
children: [
LinearProgressIndicator(
backgroundColor: Colors.white.withOpacity(0.2),
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white.withOpacity(0.5),
),
minHeight: 40,
value:
mapDriverController.progressTimerRideBegin.toDouble(),
),
Center(
child: AnimatedDefaultTextStyle(
duration: Duration(milliseconds: 300),
style: AppStyle.title.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize:
mapDriverController.remainingTimeTimerRideBegin < 60
? 18
: 16,
shadows: [
Shadow(
color: Colors.black26,
offset: Offset(0, 2),
blurRadius: 4,
),
],
),
child: Text(
mapDriverController.stringRemainingTimeRideBegin,
),
),
),
],
),
),
),
],
);
}
}
Widget _buildInfoColumn({required IconData icon, required String text}) {
return Column(
children: [
Icon(icon),
Text(
text,
style: AppStyle.title,
),
],
);
}
Widget _buildInfoBox({required IconData icon, required String text}) {
return Container(
width: Get.width * .2,
decoration: AppStyle.boxDecoration1,
padding: const EdgeInsets.all(4),
child: Row(
children: [
Icon(icon),
SizedBox(width: 4),
Text(
text,
style: AppStyle.number,
),
],
),
);
}
GetBuilder<MapDriverController> speedCircle() {

View File

@@ -452,9 +452,12 @@ class PassengerInfoWindow extends StatelessWidget {
kolor: AppColor.greenColor,
onPressed: () {
MyDialog().getDialog(
"Is the Passenger in your Car ?"
.tr,
"Don't start trip if not".tr,
"Is the Passenger in your Car?"
.tr, // "هل الراكب في سيارتك؟"
"Don't start trip if passenger not in your car"
.tr, // "لا تبدأ الرحلة إذا لم يكن الراكب في سيارتك"
() async {
await controller
.startRideFromDriver();

View File

@@ -1,9 +1,7 @@
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart';
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
import '../../controller/local/local_controller.dart';
class Language extends StatelessWidget {
@@ -11,203 +9,122 @@ class Language extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: GetBuilder<LocaleController>(
builder: (controller) => Center(
child: Container(
padding: const EdgeInsets.all(15),
child: ListView(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"Choose Language".tr,
style: Theme.of(context).textTheme.headlineLarge,
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Choose Language'.tr),
border: null,
),
child: SafeArea(
child: GetBuilder<LocaleController>(
builder: (controller) => Center(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
_buildHeader(),
const SizedBox(height: 20),
Expanded(
child: ListView(
physics: const BouncingScrollPhysics(),
children: [
_buildLanguageButton(
'العربية', 'ar', controller, context),
_buildLanguageButton(
'English', 'en', controller, context),
_buildLanguageButton(
'Türkçe', 'tr', controller, context),
_buildLanguageButton(
'Français', 'fr', controller, context),
_buildLanguageButton(
'Italiano', 'it', controller, context),
_buildLanguageButton(
'Deutsch', 'de', controller, context),
_buildLanguageButton(
'Ελληνικά', 'el', controller, context),
_buildLanguageButton(
'Español', 'es', controller, context),
_buildLanguageButton(
'فارسی', 'fa', controller, context),
_buildLanguageButton('中文', 'zh', controller, context),
_buildLanguageButton(
'Русский', 'ru', controller, context),
_buildLanguageButton(
'हिन्दी', 'hi', controller, context),
],
),
),
],
),
const SizedBox(height: 20),
MyElevatedButton(
title: 'العربية',
onPressed: () async {
await controller.changeLang("ar");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "English",
onPressed: () {
controller.changeLang("en");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Türkçe",
onPressed: () {
controller.changeLang("tr");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Français",
onPressed: () {
controller.changeLang("fr");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Italiano",
onPressed: () {
controller.changeLang("it");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Deutsch",
onPressed: () {
controller.changeLang("de");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Ελληνικά",
onPressed: () {
controller.changeLang("el");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Español",
onPressed: () {
controller.changeLang("es");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "فارسی",
onPressed: () {
controller.changeLang("fa");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "中文",
onPressed: () {
controller.changeLang("zh");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "Русский",
onPressed: () {
controller.changeLang("ru");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
MyElevatedButton(
title: "हिन्दी",
onPressed: () {
controller.changeLang("hi");
Get.defaultDialog(
title: 'You should restart app to change language'.tr,
titleStyle: AppStyle.title,
middleText: '',
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.offAll(() => HomeCaptain());
}));
},
),
],
),
),
),
),
));
);
}
Widget _buildHeader() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF2196F3), Color(0xFF1976D2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: CupertinoColors.systemBlue.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
const Icon(
CupertinoIcons.globe,
color: CupertinoColors.white,
size: 48,
),
const SizedBox(height: 16),
Text(
'Choose Language'.tr,
style: const TextStyle(
color: CupertinoColors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
],
),
);
}
Widget _buildLanguageButton(String title, String langCode,
LocaleController controller, BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: MyElevatedButton(
title: title,
onPressed: () async {
controller.changeLang(langCode);
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: Text('You should restart app to change language'.tr),
actions: [
CupertinoDialogAction(
child: Text('Ok'.tr),
onPressed: () {
Get.offAll(() => HomeCaptain());
},
),
],
),
);
},
));
}
}

View File

@@ -5,7 +5,9 @@ import 'package:sefer_driver/constant/style.dart';
import 'package:flutter/services.dart';
import 'package:vibration/vibration.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../main.dart';
class MyElevatedButton extends StatelessWidget {
final String title;
@@ -22,17 +24,25 @@ class MyElevatedButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
bool vibrate = box.read(BoxName.isvibrate) ?? true;
return ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(kolor),
backgroundColor: WidgetStateProperty.all(AppColor.blueColor),
shadowColor: WidgetStateProperty.all(Colors.transparent),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
onPressed: () async {
// Handle haptic feedback for both iOS and Android
if (Platform.isIOS) {
HapticFeedback.selectionClick();
} else {
Vibration.vibrate(duration: 100);
// Vibrate.vibrateWithPauses(pauses);
if (vibrate == true) {
if (Platform.isIOS) {
HapticFeedback.selectionClick();
} else if (Platform.isAndroid) {
await Vibration.vibrate(duration: vibrateDuration);
} else {}
}
// Ensure the onPressed callback is called after haptic feedback

View File

@@ -1,69 +1,123 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
class SnackbarConfig {
static const duration = Duration(seconds: 3);
static const animationDuration = Duration(milliseconds: 300);
static const margin = EdgeInsets.symmetric(horizontal: 16, vertical: 10);
static const borderRadius = 12.0;
static const elevation = 6.0;
static final BoxShadow shadow = BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 2),
);
}
SnackbarController mySnackeBarError(String message) {
// Trigger error haptic feedback
HapticFeedback.mediumImpact();
return Get.snackbar(
'Error'.tr,
message,
backgroundColor: AppColor.redColor.withOpacity(0.9),
backgroundColor: AppColor.redColor.withOpacity(0.95),
colorText: AppColor.secondaryColor,
icon: const Icon(Icons.error, color: AppColor.secondaryColor),
icon: const Icon(
Icons.error_outline_rounded,
color: AppColor.secondaryColor,
size: 28,
),
shouldIconPulse: true,
snackPosition: SnackPosition.TOP,
margin: const EdgeInsets.all(10),
borderRadius: 10,
animationDuration: const Duration(milliseconds: 500),
forwardAnimationCurve: Curves.easeOutBack,
reverseAnimationCurve: Curves.easeInBack,
margin: SnackbarConfig.margin,
borderRadius: SnackbarConfig.borderRadius,
duration: SnackbarConfig.duration,
animationDuration: SnackbarConfig.animationDuration,
forwardAnimationCurve: Curves.easeOutCirc,
reverseAnimationCurve: Curves.easeInCirc,
boxShadows: [SnackbarConfig.shadow],
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
titleText: Text(
'Error'.tr,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontWeight: FontWeight.w700,
color: Colors.white,
fontSize: 16,
letterSpacing: 0.2,
),
),
messageText: Text(
message,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
color: Colors.white.withOpacity(0.95),
fontSize: 14,
height: 1.3,
),
),
onTap: (_) {
HapticFeedback.lightImpact();
Get.closeCurrentSnackbar();
},
isDismissible: true,
dismissDirection: DismissDirection.horizontal,
overlayBlur: 0.8,
overlayColor: Colors.black12,
);
}
SnackbarController mySnackbarSuccess(String message) {
// Trigger success haptic feedback
HapticFeedback.lightImpact();
return Get.snackbar(
'Success'.tr,
message,
backgroundColor: AppColor.greenColor
.withOpacity(0.9), // Assuming green color for success
backgroundColor: AppColor.greenColor.withOpacity(0.95),
colorText: AppColor.secondaryColor,
icon: const Icon(Icons.check_circle, color: AppColor.secondaryColor),
icon: const Icon(
Icons.check_circle_outline_rounded,
color: AppColor.secondaryColor,
size: 28,
),
shouldIconPulse: true,
snackPosition: SnackPosition.TOP,
margin: const EdgeInsets.all(10),
borderRadius: 10,
animationDuration: const Duration(milliseconds: 500),
forwardAnimationCurve: Curves.easeOutBack,
reverseAnimationCurve: Curves.easeInBack,
margin: SnackbarConfig.margin,
borderRadius: SnackbarConfig.borderRadius,
duration: SnackbarConfig.duration,
animationDuration: SnackbarConfig.animationDuration,
forwardAnimationCurve: Curves.easeOutCirc,
reverseAnimationCurve: Curves.easeInCirc,
boxShadows: [SnackbarConfig.shadow],
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
titleText: Text(
'Success'.tr,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontWeight: FontWeight.w700,
color: Colors.white,
fontSize: 16,
letterSpacing: 0.2,
),
),
messageText: Text(
message,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
color: Colors.white.withOpacity(0.95),
fontSize: 14,
height: 1.3,
),
),
onTap: (_) {
HapticFeedback.lightImpact();
Get.closeCurrentSnackbar();
},
isDismissible: true,
dismissDirection: DismissDirection.horizontal,
overlayBlur: 0.8,
overlayColor: Colors.black12,
);
}

View File

@@ -1,36 +1,131 @@
import 'package:flutter/material.dart';
class MyCircularProgressIndicator extends StatelessWidget {
class MyCircularProgressIndicator extends StatefulWidget {
final Color backgroundColor;
final double size;
final Color progressColor;
final double strokeWidth;
const MyCircularProgressIndicator({
super.key,
this.backgroundColor = Colors.transparent,
this.size = 110,
this.progressColor = Colors.blue,
this.strokeWidth = 3.0,
});
@override
State<MyCircularProgressIndicator> createState() =>
_MyCircularProgressIndicatorState();
}
class _MyCircularProgressIndicatorState
extends State<MyCircularProgressIndicator>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnimation;
late Animation<double> _rotationAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
_scaleAnimation = Tween<double>(
begin: 0.95,
end: 1.05,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
_rotationAnimation = Tween<double>(
begin: 0,
end: 2,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.linear,
));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 110,
height: 110,
decoration: BoxDecoration(
color: backgroundColor,
shape: BoxShape.circle,
),
child: Stack(
children: [
const Center(child: CircularProgressIndicator()),
Column(
children: [
Align(
alignment: Alignment.center,
child: Image.asset('assets/images/logo.gif'),
),
],
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.scale(
scale: _scaleAnimation.value,
child: Container(
width: widget.size,
height: widget.size,
decoration: BoxDecoration(
color: widget.backgroundColor,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: widget.progressColor.withAlpha(30),
blurRadius: 12,
spreadRadius: 2,
),
],
),
child: Stack(
alignment: Alignment.center,
children: [
// Outer rotating progress indicator
Transform.rotate(
angle: _rotationAnimation.value * 3.14,
child: CircularProgressIndicator(
strokeWidth: widget.strokeWidth,
valueColor: AlwaysStoppedAnimation<Color>(
widget.progressColor,
),
),
),
// Inner static progress indicator
CircularProgressIndicator(
strokeWidth: widget.strokeWidth * 0.7,
valueColor: AlwaysStoppedAnimation<Color>(
widget.progressColor.withAlpha(150),
),
),
// Logo container with scale animation
ScaleTransition(
scale: Tween<double>(
begin: 0.9,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
)),
child: Container(
width: widget.size * 0.7,
height: widget.size * 0.7,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: widget.backgroundColor,
),
child: Image.asset(
'assets/images/logo.gif',
fit: BoxFit.contain,
),
),
),
],
),
),
],
),
);
},
),
);
}

View File

@@ -1,58 +1,139 @@
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/functions/tts.dart';
class DialogConfig {
static const Duration animationDuration = Duration(milliseconds: 200);
static const double blurStrength = 8.0;
static const double cornerRadius = 14.0;
static final BoxDecoration decoration = BoxDecoration(
borderRadius: BorderRadius.circular(cornerRadius),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(38), // 0.15 opacity
blurRadius: 16,
offset: const Offset(0, 8),
),
],
);
}
class MyDialog extends GetxController {
void getDialog(String title, String? midTitle, VoidCallback onPressed) {
final textToSpeechController = Get.put(TextToSpeechController());
HapticFeedback.mediumImpact();
Get.dialog(
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: CupertinoAlertDialog(
title: Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
TweenAnimationBuilder<double>(
duration: DialogConfig.animationDuration,
tween: Tween(begin: 0.0, end: 1.0),
builder: (context, value, child) {
return Transform.scale(
scale: 0.95 + (0.05 * value),
child: Opacity(opacity: value, child: child),
);
},
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: DialogConfig.blurStrength,
sigmaY: DialogConfig.blurStrength,
),
child: Theme(
data: ThemeData.light().copyWith(
dialogBackgroundColor: CupertinoColors.systemBackground,
),
child: CupertinoAlertDialog(
title: Column(
children: [
Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.w700,
letterSpacing: -0.5,
color: AppColor.primaryColor,
),
),
const SizedBox(height: 8),
],
),
content: Column(
children: [
CupertinoButton(
padding: const EdgeInsets.all(8),
onPressed: () async {
HapticFeedback.selectionClick();
await textToSpeechController.speakText(title);
await textToSpeechController.speakText(midTitle!);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color:
AppColor.primaryColor.withAlpha(26), // 0.1 opacity
borderRadius: BorderRadius.circular(8),
),
child: Icon(
CupertinoIcons.speaker_2_fill,
color: AppColor.primaryColor,
size: 24,
),
),
),
const SizedBox(height: 8),
Text(
midTitle!,
style: AppStyle.title.copyWith(
fontSize: 16,
height: 1.3,
color: Colors.black87,
),
textAlign: TextAlign.center,
),
],
),
actions: [
CupertinoDialogAction(
onPressed: () {
HapticFeedback.lightImpact();
Get.back();
},
child: Text(
'Cancel',
style: TextStyle(
color: AppColor.redColor,
fontWeight: FontWeight.w600,
fontSize: 17,
),
),
),
CupertinoDialogAction(
onPressed: () {
HapticFeedback.mediumImpact();
onPressed();
},
child: Text(
'OK'.tr,
style: TextStyle(
color: AppColor.greenColor,
fontWeight: FontWeight.w600,
fontSize: 17,
),
),
),
],
),
),
content: Column(
children: [
CupertinoButton(
onPressed: () async {
await textToSpeechController.speakText(title);
await textToSpeechController.speakText(midTitle!);
},
child: const Icon(CupertinoIcons.speaker_2,
color: AppColor.primaryColor),
),
Text(
midTitle!,
style: AppStyle.title.copyWith(fontSize: 16),
),
],
),
actions: [
CupertinoDialogAction(
child: const Text('Cancel',
style: TextStyle(color: AppColor.redColor)),
onPressed: () {
Get.back();
},
),
CupertinoDialogAction(
onPressed: onPressed,
child: Text('OK'.tr,
style: const TextStyle(color: AppColor.greenColor)),
),
],
),
),
barrierDismissible: false,
barrierDismissible: true,
barrierColor: Colors.black.withAlpha(102), // 0.4 opacity
);
}
}
@@ -61,46 +142,104 @@ class MyDialogContent extends GetxController {
void getDialog(String title, Widget? content, VoidCallback onPressed) {
final textToSpeechController = Get.put(TextToSpeechController());
HapticFeedback.mediumImpact();
Get.dialog(
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: CupertinoAlertDialog(
title: Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
TweenAnimationBuilder<double>(
duration: DialogConfig.animationDuration,
tween: Tween(begin: 0.0, end: 1.0),
builder: (context, value, child) {
return Transform.scale(
scale: 0.95 + (0.05 * value),
child: Opacity(opacity: value, child: child),
);
},
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: DialogConfig.blurStrength,
sigmaY: DialogConfig.blurStrength,
),
content: Column(
children: [
CupertinoButton(
onPressed: () async {
await textToSpeechController.speakText(title);
},
child: const Icon(CupertinoIcons.headphones,
color: AppColor.primaryColor),
child: Theme(
data: ThemeData.light().copyWith(
dialogBackgroundColor: CupertinoColors.systemBackground,
),
child: CupertinoAlertDialog(
title: Column(
children: [
Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.w700,
letterSpacing: -0.5,
color: AppColor.primaryColor,
),
),
const SizedBox(height: 8),
],
),
content!
],
content: Column(
children: [
CupertinoButton(
padding: const EdgeInsets.all(8),
onPressed: () async {
HapticFeedback.selectionClick();
await textToSpeechController.speakText(title);
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color:
AppColor.primaryColor.withAlpha(26), // 0.1 opacity
borderRadius: BorderRadius.circular(8),
),
child: Icon(
CupertinoIcons.headphones,
color: AppColor.primaryColor,
size: 24,
),
),
),
const SizedBox(height: 12),
content!,
],
),
actions: [
CupertinoDialogAction(
onPressed: () {
HapticFeedback.lightImpact();
Get.back();
},
child: Text(
'Cancel',
style: TextStyle(
color: AppColor.redColor,
fontWeight: FontWeight.w600,
fontSize: 17,
),
),
),
CupertinoDialogAction(
onPressed: () {
HapticFeedback.mediumImpact();
onPressed();
},
child: Text(
'OK'.tr,
style: TextStyle(
color: AppColor.greenColor,
fontWeight: FontWeight.w600,
fontSize: 17,
),
),
),
],
),
),
actions: [
CupertinoDialogAction(
child: const Text('Cancel',
style: TextStyle(color: AppColor.redColor)),
onPressed: () {
Get.back();
},
),
CupertinoDialogAction(
onPressed: onPressed,
child: Text('OK'.tr,
style: const TextStyle(color: AppColor.greenColor)),
),
],
),
),
barrierDismissible: false,
barrierDismissible: true,
barrierColor: Colors.black.withAlpha(102), // 0.4 opacity
);
}
}