This commit is contained in:
Hamza-Ayed
2024-12-24 17:35:15 +03:00
parent 1e0e4a5b48
commit 1cbf0183d1
56 changed files with 3081 additions and 2560 deletions

View File

@@ -6,7 +6,6 @@ import 'package:SEFER/controller/firebase/firbase_messge.dart';
import 'package:SEFER/controller/functions/add_error.dart';
import 'package:SEFER/views/auth/login_page.dart';
import 'package:SEFER/views/auth/sms_verfy_page.dart';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:SEFER/constant/box_name.dart';

View File

@@ -7,7 +7,6 @@ import 'package:SEFER/controller/auth/login_controller.dart';
import 'package:SEFER/controller/functions/add_error.dart';
import 'package:SEFER/controller/local/phone_intel/phone_number.dart';
import 'package:SEFER/views/home/map_page_passenger.dart';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:SEFER/constant/links.dart';
@@ -20,6 +19,7 @@ import '../../constant/box_name.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/auth/verify_email_page.dart';
import '../../views/widgets/mydialoug.dart';
import '../functions/sms_controller.dart';
class RegisterController extends GetxController {

View File

@@ -1,6 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
@@ -136,8 +135,8 @@ class FirebaseMessagesController extends GetxController {
var myList = jsonDecode(passengerList) as List<dynamic>;
driverID = myList[0].toString();
Get.find<MapPassengerController>().driverToken = myList[2].toString();
Get.find<MapPassengerController>().statusRide == 'Apply';
Get.find<MapPassengerController>().isSearchingWindow == false;
Get.find<MapPassengerController>().statusRide = 'Apply';
Get.find<MapPassengerController>().isSearchingWindow = false;
Get.find<MapPassengerController>().update();
Get.find<MapPassengerController>().rideAppliedFromDriver(true);

View File

@@ -27,8 +27,8 @@ class NotificationController extends GetxController {
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
onDidReceiveLocalNotification:
(int id, String? title, String? body, String? payload) async {},
// onDidReceiveLocalNotification:
// (int id, String? title, String? body, String? payload) async {},
);
InitializationSettings initializationSettings =
InitializationSettings(android: android, iOS: ios);

View File

@@ -1,13 +1,12 @@
import 'dart:convert';
import 'dart:io';
import 'package:SEFER/constant/links.dart';
import 'package:SEFER/controller/functions/crud.dart';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../constant/box_name.dart';
import '../../constant/info.dart';
import '../../constant/colors.dart';
import '../../main.dart';
Future<void> checkForUpdate(BuildContext context) async {
@@ -42,38 +41,120 @@ checkForBounusInvitation() {
void showUpdateDialog(BuildContext context) {
final String storeUrl = Platform.isAndroid
? 'https://play.google.com/store/apps/details?id=com.mobileapp.store.ride'
: 'https://apps.apple.com/ae/app/sefer/id6458734951';
showCupertinoDialog(
? 'https://play.google.com/store/apps/details?id=com.sefer_driver'
: 'https://apps.apple.com/ae/app/sefer-driver/id6502189302';
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

@@ -5,14 +5,12 @@ import 'dart:math' as math;
import 'dart:ui';
import 'package:SEFER/constant/univeries_polygon.dart';
import 'package:SEFER/controller/firebase/local_notification.dart';
import 'package:SEFER/views/widgets/mysnakbar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_confetti/flutter_confetti.dart';
import 'package:vector_math/vector_math.dart' show radians, degrees;
import 'package:SEFER/controller/functions/tts.dart';
import 'package:SEFER/views/home/map_page_passenger.dart';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:SEFER/views/widgets/my_textField.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
@@ -34,9 +32,12 @@ import '../../main.dart';
import '../../models/model/locations.dart';
import '../../models/model/painter_copoun.dart';
import '../../print.dart';
import '../../views/home/map_widget.dart/cancel_raide_page.dart';
import '../../views/home/map_widget.dart/car_details_widget_to_go.dart';
import '../../views/home/map_widget.dart/select_driver_mishwari.dart';
import '../../views/widgets/elevated_btn.dart';
import '../../views/widgets/error_snakbar.dart';
import '../../views/widgets/mydialoug.dart';
import '../firebase/firbase_messge.dart';
import '../functions/audio_record1.dart';
import '../functions/crud.dart';
@@ -565,8 +566,7 @@ class MapPassengerController extends GetxController {
}
void changeCancelRidePageShow() {
// rideConfirm == true
// ?
showCancelRideBottomSheet();
isCancelRidePageShown = !isCancelRidePageShown;
// : cancelRide();
update();
@@ -1791,16 +1791,17 @@ class MapPassengerController extends GetxController {
return;
}
driversStatusForSearchWindow = 'Your order is being prepared'.tr;
Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}');
Log.print('driversStatusForSearchWindow: $driversStatusForSearchWindow');
update();
await postRideDetailsToServer();
driversStatusForSearchWindow = 'Your order sent to drivers'.tr;
delayAndFetchRideStatusForAllDriverAvailable(rideId);
await notifyAvailableDrivers();
driversStatusForSearchWindow = 'The drivers are reviewing your request'.tr;
Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}');
Log.print('driversStatusForSearchWindow: $driversStatusForSearchWindow');
update();
delayAndFetchRideStatusForAllDriverAvailable(rideId);
// update();
}
@@ -1829,9 +1830,9 @@ class MapPassengerController extends GetxController {
}
// await postRideDetailsToServer();
await notifyAvailableDrivers();
delayAndFetchRideStatusForAllDriverAvailable(rideId);
update();
// update();
await notifyAvailableDrivers();
}
bool isDriversDataValid() {
@@ -2023,7 +2024,7 @@ class MapPassengerController extends GetxController {
tick = 0;
await addRideToNotificationDriverAvailable();
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (attemptCounter >= maxAttempts || isApplied) {
if (attemptCounter >= maxAttempts || isApplied == true) {
timer.cancel();
_rideStatusStreamController.close(); // Close the stream when done
return;
@@ -2034,9 +2035,9 @@ class MapPassengerController extends GetxController {
try {
var res = await getRideStatus(rideId);
Log.print('res:2022 ${res}');
Log.print('res:2022 $res');
String rideStatusDelayed = res.toString();
Log.print('rideStatusDelayed: ${rideStatusDelayed}');
Log.print('rideStatusDelayed: $rideStatusDelayed');
_rideStatusStreamController
.add(rideStatusDelayed); // Emit the ride status
@@ -2051,6 +2052,7 @@ class MapPassengerController extends GetxController {
//
} else if (rideStatusDelayed == 'Apply' ||
rideStatusDelayed == 'Applied') {
isApplied = true;
rideAppliedFromDriver(isApplied);
timer.cancel();
// Close stream after applying
@@ -2525,7 +2527,7 @@ class MapPassengerController extends GetxController {
noCarString = false;
dataCarsLocationByPassenger = jsonDecode(res);
Log.print(
'dataCarsLocationByPassenger:getCarsLocationByPassengerAndReloadMarker ${dataCarsLocationByPassenger}');
'dataCarsLocationByPassenger:getCarsLocationByPassengerAndReloadMarker $dataCarsLocationByPassenger');
// Check if 'message' is present and not null
if (dataCarsLocationByPassenger != null &&
@@ -3084,7 +3086,7 @@ class MapPassengerController extends GetxController {
changeCancelRidePageShow();
if (rideId != 'yet') {
Log.print('cancelRide: 1');
FirebaseMessagesController().sendNotificationToDriverMAP(
await FirebaseMessagesController().sendNotificationToDriverMAP(
'Cancel Trip'.tr,
'Trip Cancelled'.tr,
driverToken.toString(),
@@ -3698,6 +3700,11 @@ class MapPassengerController extends GetxController {
controller.animateCamera(
CameraUpdate.newLatLng(passengerLocation),
);
// Future.delayed(const Duration(milliseconds: 500), () {
// markers.forEach((marker) {
// controller.showMarkerInfoWindow(marker.markerId);
// });
// });
update();
}
@@ -4011,7 +4018,7 @@ class MapPassengerController extends GetxController {
late String startNameAddress = '';
late String endNameAddress = '';
getMap(String origin, destination) async {
getDirectionMap(String origin, destination) async {
isLoading = true;
update();
remainingTime = 25; //to make cancel every call
@@ -4043,22 +4050,7 @@ class MapPassengerController extends GetxController {
isLoading = false;
newStartPointLocation = LatLng(
data[0]["start_location"]['lat'], data[0]["start_location"]['lng']);
markers.add(
Marker(
markerId: const MarkerId('start'),
position: newStartPointLocation,
icon: startIcon,
),
);
markers.add(
Marker(
markerId: const MarkerId('end'),
position: LatLng(
data[0]["end_location"]['lat'], data[0]["end_location"]['lng']),
icon: endIcon,
),
);
update();
durationToRide = data[0]['duration']['value'];
final points =
decodePolyline(response["routes"][0]["overview_polyline"]["points"]);
@@ -4081,31 +4073,176 @@ class MapPassengerController extends GetxController {
LatLngBounds(northeast: northeast, southwest: southwest);
// Fit the camera to the bounds
var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 160);
var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 100);
mapController!.animateCamera(cameraUpdate);
// getDistanceFromText(data[0]['distance']['text']);
double distanceOfTrip = (data[0]['distance']['value']) / 1000;
distance = distanceOfTrip;
durationToAdd = Duration(seconds: durationToRide);
hours = durationToAdd.inHours;
minutes = (durationToAdd.inMinutes % 60).round();
// updateCameraForDistanceAfterGetMap();
markers.clear();
update();
markers.add(
Marker(
markerId: const MarkerId('start'),
position: newStartPointLocation,
icon: startIcon,
infoWindow: InfoWindow(
title: startNameAddress,
snippet: '',
),
),
);
// Add end marker
markers.add(
Marker(
markerId: const MarkerId('end'),
position: LatLng(
data[0]["end_location"]['lat'], data[0]["end_location"]['lng']),
icon: endIcon,
infoWindow: InfoWindow(
title: endNameAddress,
snippet:
'$distance ${'KM'.tr}${hours > 0 ? '${'Your Ride Duration is '.tr}$hours ${'H and'.tr} $minutes ${'m'.tr}' : '${'Your Ride Duration is '.tr} $minutes ${'m'.tr}'}'),
),
);
// // Show info windows automatically
// Future.delayed(const Duration(milliseconds: 500), () {
// mapController?.showMarkerInfoWindow(const MarkerId('start'));
// });
Future.delayed(const Duration(milliseconds: 500), () {
mapController?.showMarkerInfoWindow(const MarkerId('end'));
});
update();
if (polyLines.isNotEmpty) {
clearPolyline();
} else {
var polyline = Polyline(
polylineId: PolylineId(response["routes"][0]["summary"]),
points: polylineCoordinates,
width: 10,
color: Colors.blue,
);
polyLines.add(polyline);
_animatePolyline(polylineCoordinates);
rideConfirm = false;
isMarkersShown = true;
update();
}
}
Future<void> _animatePolyline(List<LatLng> coordinates) async {
// Initial animation
polyLines.clear();
List<LatLng> animatedPoints = [];
// Draw initial polyline
for (int i = 0; i < coordinates.length; i++) {
animatedPoints.add(coordinates[i]);
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: List<LatLng>.from(animatedPoints),
width: 4,
color: AppColor.primaryColor,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 1));
}
// Color change animations
for (int cycle = 0; cycle < 6; cycle++) {
// Change to green
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: coordinates,
width: 4,
color: AppColor.bronze,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 500));
// Change back to primary color
polyLines.clear();
polyLines.add(
Polyline(
polylineId: const PolylineId('animated_route'),
points: coordinates,
width: 4,
color: AppColor.writeColor,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
geodesic: true,
),
);
update();
await Future.delayed(const Duration(milliseconds: 500));
}
}
// Add this method to your controller class
// Future<void> _animatePolyline(List<LatLng> coordinates) async {
// // Clear existing polylines
// polyLines.clear();
// // Create segments for animation
// List<LatLng> animatedPoints = [];
// // Calculate step size for smoother animation
// int stepSize = (coordinates.length / 20).round();
// stepSize = stepSize < 1 ? 1 : stepSize;
// for (int i = 0; i < coordinates.length; i += stepSize) {
// // Add points gradually
// animatedPoints.add(coordinates[i]);
// if (animatedPoints.length > 1) {
// // Remove previous polyline
// if (polyLines.isNotEmpty) {
// polyLines.clear();
// }
// // Add new polyline segment
// polyLines.add(
// Polyline(
// polylineId: const PolylineId('animated_route'),
// points: List<LatLng>.from(animatedPoints),
// width: 4,
// color: Colors.blue,
// ),
// );
// // Update camera position to follow animation
// if (mapController != null) {
// final bounds = LatLngBounds(
// southwest: animatedPoints.reduce((value, element) => LatLng(
// min(value.latitude, element.latitude),
// min(value.longitude, element.longitude))),
// northeast: animatedPoints.reduce((value, element) => LatLng(
// max(value.latitude, element.latitude),
// max(value.longitude, element.longitude))),
// );
// mapController!.animateCamera(
// CameraUpdate.newLatLngBounds(bounds, 100),
// );
// }
// }
// update();
// await Future.delayed(const Duration(milliseconds: 50));
// }
// }
String shortenAddress(String fullAddress) {
// Split the address into parts
List<String> parts = fullAddress.split('،');
@@ -4871,7 +5008,7 @@ class MapPassengerController extends GetxController {
try {
var d = jsonDecode(res);
driversForMishwari = d['message'];
Log.print('driversForMishwari: ${driversForMishwari}');
Log.print('driversForMishwari: $driversForMishwari');
update();
} catch (e) {
// Handle invalid JSON format

View File

@@ -1,7 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
@@ -17,6 +16,7 @@ import 'package:mime/mime.dart';
import '../../../constant/api_key.dart';
import '../../../print.dart';
import '../../../views/widgets/mydialoug.dart';
class ComplaintController extends GetxController {
bool isLoading = false;

View File

@@ -5,16 +5,15 @@ import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/links.dart';
import 'package:SEFER/controller/functions/crud.dart';
import 'package:SEFER/controller/payment/payment_controller.dart';
import 'package:SEFER/views/widgets/mysnakbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/contact.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:get/get.dart';
import 'package:share/share.dart';
import '../../../main.dart';
import '../../../print.dart';
import '../../../views/widgets/my_dialog.dart';
import '../../../views/widgets/error_snakbar.dart';
import '../../../views/widgets/mydialoug.dart';
import '../../functions/launch.dart';
import '../../notification/notification_captain_controller.dart';

View File

@@ -13,112 +13,84 @@ import '../../onbording_page.dart';
import '../auth/login_controller.dart';
class SplashScreenController extends GetxController
with SingleGetTickerProviderMixin {
late AnimationController animationController;
late Animation<double> zoomInAnimation;
late Animation<double> zoomOutAnimation;
with GetTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> animation;
final progress = 0.0.obs;
Timer? _progressTimer;
String packageInfo = '';
late String version = '1.5.48';
Future<void> checkForUpdate() async {
final packageInfo = await PackageInfo.fromPlatform();
final currentVersion = packageInfo.buildNumber;
final version1 = packageInfo.version;
print('currentVersion is : $currentVersion');
// Fetch the latest version from your server
version = version1.toString();
print('version: ${version}');
Future<void> _getPackageInfo() async {
final info = await PackageInfo.fromPlatform();
packageInfo = info.version;
box.write(BoxName.packagInfo, packageInfo);
update();
}
StreamSubscription? _sub;
// Future<void> initUniLinks() async {
// // Handle initial URI if the app was launched from a link
// try {
// final initialUri = await getInitialUri();
// if (initialUri != null) {
// handleLink(initialUri);
// }
// } on PlatformException {
// // Handle exception by warning the user their action did not succeed
// print("Failed to get initial uri");
// }
@override
void onInit() {
super.onInit();
_getPackageInfo();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500), // Reduced duration
)..forward();
// // Listen to new links while the app is running
// _sub = uriLinkStream.listen((Uri? uri) {
// if (uri != null) {
// handleLink(uri);
// }
// }, onError: (Object err) {
// print('Error occurred: $err');
// });
// }
animation =
CurvedAnimation(parent: _animationController, curve: Curves.easeOut);
void handleLink(Uri uri) {
if (uri.host == 'sefer.live' && uri.path == '/tripmonitor') {
final rideId = uri.queryParameters['rideId'];
final driverId = uri.queryParameters['driverId'];
if (rideId != null && driverId != null) {
Get.toNamed('/tripmonitor', parameters: {
'rideId': rideId,
'driverId': driverId,
});
} else {
// Handle the case where rideId or driverId is null
print('Invalid parameters in the deep link');
// You might want to show an error message to the user or handle this case differently
}
}
startTimer();
_startProgressTimer();
}
@override
void onInit() async {
super.onInit();
checkForUpdate();
// initUniLinks();
animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 4),
);
void _startProgressTimer() {
const totalTime = 3000; // 5 seconds in milliseconds
const interval = 50; // Update every 50ms
int elapsed = 0;
zoomInAnimation = Tween<double>(begin: 1.0, end: 1.5).animate(
CurvedAnimation(
parent: animationController,
curve: Curves.easeInOut,
),
);
_progressTimer =
Timer.periodic(const Duration(milliseconds: interval), (timer) async {
elapsed += interval;
progress.value = (elapsed / totalTime).clamp(0.0, 1.0);
zoomOutAnimation = Tween<double>(begin: 1.5, end: 1.0).animate(
CurvedAnimation(
parent: animationController,
curve: Curves.easeInOut,
),
);
animationController.repeat(reverse: true);
startTimer();
if (elapsed >= totalTime) {
timer.cancel();
box.read(BoxName.onBoarding) == null
? Get.off(() => OnBoardingPage())
: box.read(BoxName.email) != null &&
box.read(BoxName.phone) != null &&
box.read(BoxName.isVerified) == '1'
// ? Get.off(() => const MapPagePassenger())
? await Get.put(LoginController()).loginUsingCredentials(
box.read(BoxName.passengerID).toString(),
box.read(BoxName.email).toString(),
)
: Get.off(() => LoginPage());
}
});
}
void startTimer() async {
Timer(const Duration(seconds: 5), () async {
box.read(BoxName.onBoarding) == null
? Get.off(() => OnBoardingPage())
: box.read(BoxName.email) != null &&
box.read(BoxName.phone) != null &&
box.read(BoxName.isVerified) == '1'
// ? Get.off(() => const MapPagePassenger())
? await Get.put(LoginController()).loginUsingCredentials(
box.read(BoxName.passengerID).toString(),
box.read(BoxName.email).toString(),
)
: Get.off(() => LoginPage());
// box.read(BoxName.onBoarding) == null
// ? Get.off(() => OnBoardingPage())
// : box.read(BoxName.email) != null &&
// box.read(BoxName.phone) != null &&
// box.read(BoxName.isVerified) == '1'
// // ? Get.off(() => const MapPagePassenger())
// ? await Get.put(LoginController()).loginUsingCredentials(
// box.read(BoxName.passengerID).toString(),
// box.read(BoxName.email).toString(),
// )
// : Get.off(() => LoginPage());
});
}
@override
void onClose() {
animationController.dispose();
_progressTimer?.cancel();
_animationController.dispose();
super.onClose();
}
}

View File

@@ -10,7 +10,6 @@ import 'package:SEFER/main.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:SEFER/views/widgets/my_scafold.dart';
import 'package:SEFER/views/widgets/mycircular.dart';
import 'package:SEFER/views/widgets/mysnakbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';

View File

@@ -8,73 +8,82 @@ import '../themes/themes.dart';
class LocaleController extends GetxController {
Locale? language;
String countryCode = '';
void restartApp() {
runApp(const 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 = themeArabic;
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);
appTheme = themeEnglish;
box.write(BoxName.lang, Get.deviceLocale!.languageCode);
appTheme = lightThemeEnglish;
break;
}
box.write(BoxName.lang, langcode);
Get.changeTheme(appTheme);
Get.updateLocale(locale);
restartApp();
update();
}
@@ -88,7 +97,94 @@ class LocaleController extends GetxController {
}
changeLang(storedLang);
super.onInit();
}
}
// class LocaleController extends GetxController {
// Locale? language;
// String countryCode = '';
// void restartApp() {
// runApp(const MyApp());
// }
// ThemeData appTheme = themeEnglish;
// changeLang(String langcode) {
// Locale locale;
// switch (langcode) {
// case "ar":
// locale = const Locale("ar");
// appTheme = themeArabic;
// break;
// case "en":
// locale = const Locale("en");
// appTheme = themeEnglish;
// break;
// case "tr":
// locale = const Locale("tr");
// appTheme = themeEnglish;
// break;
// case "fr":
// locale = const Locale("fr");
// appTheme = themeEnglish;
// break;
// case "it":
// locale = const Locale("it");
// appTheme = themeEnglish;
// break;
// case "de":
// locale = const Locale("de");
// appTheme = themeEnglish;
// break;
// case "el":
// locale = const Locale("el");
// appTheme = themeEnglish;
// break;
// case "es":
// locale = const Locale("es");
// appTheme = themeEnglish;
// break;
// case "fa":
// locale = const Locale("fa");
// appTheme = themeArabic;
// break;
// case "zh":
// locale = const Locale("zh");
// appTheme = themeEnglish;
// break;
// case "ru":
// locale = const Locale("ru");
// appTheme = themeEnglish;
// break;
// case "hi":
// locale = const Locale("hi");
// appTheme = themeEnglish;
// break;
// default:
// locale = Locale(Get.deviceLocale!.languageCode);
// appTheme = themeEnglish;
// break;
// }
// box.write(BoxName.lang, langcode);
// Get.changeTheme(appTheme);
// Get.updateLocale(locale);
// restartApp();
// update();
// }
// @override
// void onInit() {
// String? storedLang = box.read(BoxName.lang);
// if (storedLang == null) {
// // Use device language if no language is stored
// storedLang = Get.deviceLocale!.languageCode;
// box.write(BoxName.lang, storedLang);
// }
// changeLang(storedLang);
// super.onInit();
// }
// }

View File

@@ -4,11 +4,15 @@ class MyTranslation extends Translations {
@override
Map<String, Map<String, String>> get keys => {
"ar": {
"You should restart app to change language":
"يجب إعادة تشغيل التطبيق لتغيير اللغة",
"Home Page": "الصفحة الرئيسية",
"To change Language the App": "لتغيير لغة التطبيق",
"Learn more about our app and mission":
"تعرف على المزيد حول تطبيقنا ورسالتنا",
"Promos For Today": "عروض اليوم",
'Choose your ride': "اختر رحلتك",
"Your Journey Begins Here": "رحلتك تبدأ هنا",
'Bonus gift': 'بونص', "Pay": "ادفع",
"Get": "احصل على",
"Send to Driver Again": "إرسال إلى السائق مرة أخرى",
@@ -436,17 +440,74 @@ iOS [https://getapp.cc/app/6458734951]
"To : ": "إِلَى: ",
"Add Promo": "إضَافَة بَرُومُو",
"Confirm Selection": "تَأْكِيد الاخْتِيَار",
"distance is": "المَسَافَة",
"duration is": "المُدَّة",
"I don't need a ride anymore":
"لَسْتُ بِحَاجَة إِلَى رِحْلَة بَعْد الآن",
"I was just trying the application":
"كُنْتُ فَقَط أُجَرِّب التَّطْبِيق",
"No driver accepted my request": "لَمْ يَقْبَل أَيُّ سَائِق طَلَبِي",
"distance is": "المَسَافَة", "About Us": "عنّا",
"SEFER LLC": "شركة SEFER",
"Egypt's pioneering ride-sharing service, proudly developed by Arabian and local owners. We prioritize being near you both our valued passengers and our dedicated captains.":
"أول خدمة مشاركة ركوب في مصر، تم تطويرها بفخر من قبل مالكين عرب ومحليين. نحن نركز على أن نكون قريبين منك - سواء كنت راكبًا قيمًا أو قائدًا مخلصًا.",
"Why Choose SEFER?": "لماذا تختار SEFER؟",
"Closest to You": "الأقرب إليك",
"We connect you with the nearest drivers for faster pickups and quicker journeys.":
"نربطك بأقرب السائقين لضمان وصول سريع ورحلات أسرع.",
"Uncompromising Security": "أعلى مستويات الأمان",
"Lady Captains Available": "قائدات سيارات متاحات",
"Recorded Trips (Voice & AI Analysis)":
"الرحلات المسجلة (تحليل صوتي بالذكاء الاصطناعي)",
"Fastest Complaint Response": "أسرع استجابة للشكاوى",
"Our dedicated customer service team ensures swift resolution of any issues.":
"فريق خدمة العملاء لدينا يضمن حل أي مشكلة بسرعة.",
"Affordable for Everyone": "في متناول الجميع",
"Frequently Asked Questions": "الأسئلة الشائعة",
"Getting Started": "البدء",
"How do I request a ride?": "كيف يمكنني طلب رحلة؟",
"Simply open the Sefer app, enter your destination, and tap \"Request Ride\". The app will connect you with a nearby driver.":
"افتح تطبيق Sefer، وأدخل وجهتك، واضغط على \"طلب رحلة\". سيقوم التطبيق بتوصيلك بأقرب سائق.",
"Vehicle Options": "خيارات المركبات",
"What types of vehicles are available?":
"ما هي أنواع المركبات المتاحة؟",
"Sefer offers a variety of options including Economy, Comfort, and Luxury to suit your needs and budget.":
"يوفر Sefer مجموعة متنوعة من الخيارات بما في ذلك الاقتصادية، المريحة، والفاخرة لتلبية احتياجاتك وميزانيتك.",
"Payments": "المدفوعات",
"How can I pay for my ride?": "كيف يمكنني دفع تكلفة رحلتي؟",
"You can pay for your ride using cash or credit/debit card. You can select your preferred payment method before confirming your ride.":
"يمكنك دفع تكلفة رحلتك نقدًا أو باستخدام بطاقة ائتمان/خصم. يمكنك اختيار طريقة الدفع المفضلة قبل تأكيد الرحلة.",
"Ride Management": "إدارة الرحلات",
"Can I cancel my ride?": "هل يمكنني إلغاء رحلتي؟",
"Yes, you can cancel your ride, but please note that cancellation fees may apply depending on how far in advance you cancel.":
"نعم، يمكنك إلغاء رحلتك، ولكن يرجى ملاحظة أن رسوم الإلغاء قد تنطبق اعتمادًا على توقيت الإلغاء.",
"For Drivers": "للسائقين",
"Driver Registration & Requirements": "التسجيل ومتطلبات السائقين",
"Driver Registration": "تسجيل السائق",
"To register as a driver or learn about the requirements, please visit our website or contact Sefer support directly.":
"لتسجيل نفسك كسائق أو لمعرفة المتطلبات، يرجى زيارة موقعنا الإلكتروني أو الاتصال بدعم Sefer مباشرة.",
"Visit Website/Contact Support": "زيارة الموقع/الاتصال بالدعم",
"Close": "إغلاق",
"Communication": "التواصل",
"How do I communicate with the other party (passenger/driver)?":
"كيف يمكنني التواصل مع الطرف الآخر (الراكب/السائق)؟",
"You can communicate with your driver or passenger through the in-app chat feature once a ride is confirmed.":
"يمكنك التواصل مع السائق أو الراكب من خلال ميزة الدردشة داخل التطبيق بمجرد تأكيد الرحلة.",
"Safety & Security": "الأمان والحماية",
"What safety measures does Sefer offer?":
"ما هي تدابير الأمان التي يوفرها Sefer؟",
"Sefer offers various safety features including driver verification, in-app trip tracking, emergency contact options, and the ability to share your trip status with trusted contacts.":
"يوفر Sefer ميزات أمان مختلفة بما في ذلك التحقق من السائق، تتبع الرحلة داخل التطبيق، خيارات الاتصال في حالات الطوارئ، والقدرة على مشاركة حالة رحلتك مع جهات اتصال موثوقة.",
"Enjoy competitive prices across all trip options, making travel accessible.":
"استمتع بأسعار تنافسية لجميع خيارات الرحلات، مما يجعل السفر متاحًا.",
"Variety of Trip Choices": "خيارات رحلات متنوعة",
"Choose the trip option that perfectly suits your needs and preferences.":
"اختر خيار الرحلة الذي يناسب احتياجاتك وتفضيلاتك.",
"Your Choice, Our Priority": "اختيارك هو أولويتنا",
"Because we are near, you have the flexibility to choose the ride that works best for you.":
"لأننا قريبون، لديك المرونة لاختيار الرحلة التي تناسبك.",
"duration is": "المُدَّة", "Setting": "الإعدادات",
"Find answers to common questions": "اعثر على إجابات للأسئلة الشائعة",
"I don't need a ride anymore": "لا أحتاج إلى رحلة بعد الآن",
"I was just trying the application": "كنت أجرب التطبيق فقط",
"No driver accepted my request": "لم يقبل أي سائق طلبي",
"I added the wrong pick-up/drop-off location":
"أَضَفْتُ مَوْقِع الالْتِقَاط/التَّسْلِيم الخَاطِئ",
"I don't have a reason": "لَيْسَ لَدَيَّ سَبَب",
"Other": "آخَر",
"أضفت موقع استلام/توصيل خاطئ",
"I don't have a reason": "ليس لدي سبب",
"Other": "أخرى",
"Can we know why you want to cancel Ride ?":
"هَل يُمْكِنُنَا مَعْرِفَة سَبَب رَغْبَتِكَ فِي إلْغَاء الرِّحْلَة؟",
"Cancel Ride": "إلْغَاء الرِّحْلَة",

View File

@@ -1,12 +1,12 @@
import 'dart:convert';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:get/get.dart';
import 'package:SEFER/controller/firebase/firbase_messge.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../views/widgets/mydialoug.dart';
import '../functions/crud.dart';
class PassengerNotificationController extends GetxController {

View File

@@ -1,31 +1,42 @@
import 'dart:convert';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:get/get.dart';
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/constant/links.dart';
import 'package:SEFER/controller/functions/crud.dart';
import 'package:SEFER/main.dart';
import '../../views/widgets/mydialoug.dart';
class PassengerWalletHistoryController extends GetxController {
bool isLoading = false;
List archive = [];
getArchivePayment() async {
isLoading = true;
update();
var res = await CRUD().get(
link: AppLink.getPassengerWalletArchive,
payload: {'passenger_id': box.read(BoxName.passengerID)});
if (res != 'failure') {
archive = jsonDecode(res)['message'];
isLoading = false;
Future<void> getArchivePayment() async {
try {
isLoading = true;
update();
} else {
MyDialog().getDialog('No wallet record found'.tr, '', () {
Get.back();
var res = await CRUD().get(
link: AppLink.getPassengerWalletArchive,
payload: {'passenger_id': box.read(BoxName.passengerID)},
);
if (res != 'failure') {
archive = jsonDecode(res)['message'];
} else {
MyDialog().getDialog('No wallet record found'.tr, '', () {
Get.back();
Get.back();
});
}
} catch (e) {
MyDialog().getDialog('An error occurred'.tr, e.toString(), () {
Get.back();
});
} finally {
isLoading = false;
update();
}
}

View File

@@ -3,19 +3,21 @@ import 'package:SEFER/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 +27,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: "Cairo",
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,
),
);