This commit is contained in:
Hamza-Ayed
2024-08-27 10:49:43 +03:00
parent 2bc71355c3
commit d23020188e
48 changed files with 1872 additions and 432 deletions

View File

@@ -4,10 +4,12 @@ class BoxName {
static const String googlaMapApp = "googlaMapApp";
static const String lang = "lang";
static const String isvibrate = "isvibrate";
static const String myListString = "myListString";
static const String myList = "myList";
static const String bodyOrder = "bodyOrder";
static const String gender = "gender";
static const String IsSavedPhones = "IsSavedPhones";
static const String carType = "carType";
static const String isFirstTime = "isFirstTime";
static const String deviceInfo = "deviceInfo";
@@ -68,6 +70,7 @@ class BoxName {
static const String stripePublishableKey = 'stripe_publishableKe';
static const String apiKeyRun = 'apiKeyRun';
static const String serverAPI = 'serverAPI';
static const String serverChosen = 'serverChosen';
static const String secretKey = 'secretKey';
static const String basicAuthCredentials = 'basicAuthCredentials';
static const String mapAPIKEY = 'mapAPIKEY';

View File

@@ -1,23 +1,39 @@
import 'package:SEFER/constant/api_key.dart';
import 'package:SEFER/env/env.dart';
import '../main.dart';
import 'box_name.dart';
class AppLink {
static final String server = Env.serverPHP;
static final String seferPaymentServer0 = Env.seferPaymentServer;
static final String seferPaymentServer = '${Env.seferCairoServer}/ride';
static final String seferAlexandriaServer = Env.seferAlexandriaServer;
static final String seferCairoServer = Env.seferCairoServer;
static final String seferGizaServer = Env.seferGizaServer;
static final String endPoint = box.read(BoxName.serverChosen);
static final String server = Env.seferCairoServer;
// static final String server = Env.serverPHP;
static String googleMapsLink = 'https://maps.googleapis.com/maps/api/';
static String llama = 'https://api.llama-api.com/chat/completions';
static String gemini =
'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText';
static String test = "$server/test.php";
//===============firebase==========================
//===============contact==========================
static String savePhones = "$server/ride/egyptPhones/add.php";
static String getPhones = "$server/ride/egyptPhones/get.php";
////===============firebase==========================
static String getTokens = "$server/ride/firebase/get.php";
static String getDriverToken = "$server/ride/firebase/getDriverToken.php";
static String addTokens = "$server/ride/firebase/add.php";
static String addTokensDriver = "$server/ride/firebase/addDriver.php";
//=======================Wallet===================
static String wallet = '$server/ride/passengerWallet';
static String walletDriver = '$server/ride/driverWallet';
static String wallet = '$seferPaymentServer/passengerWallet';
static String walletDriver = '$seferPaymentServer/driverWallet';
static String getAllPassengerTransaction =
"$wallet/getAllPassengerTransaction.php";
static String getWalletByPassenger = "$wallet/getWalletByPassenger.php";
@@ -49,10 +65,13 @@ class AppLink {
////=======================cancelRide===================
static String ride = '$server/ride';
static String addCancelRideFromPassenger = "$server/ride/cancelRide/add.php";
static String addCancelTripFromDriverAfterApplied =
"$server/ride/cancelRide/addCancelTripFromDriverAfterApplied.php";
static String cancelRide = "$server/ride/cancelRide/get.php";
//-----------------ridessss------------------
static String addRides = "$ride/rides/add.php";
static String getRides = "$ride/rides/get.php";
static String getTripCountByCaptain = "$ride/rides/getTripCountByCaptain.php";
static String getRideOrderID = "$ride/rides/getRideOrderID.php";
static String getRideStatus = "$ride/rides/getRideStatus.php";
static String getapiKey = "$ride/apiKey/get.php";
@@ -74,21 +93,26 @@ class AppLink {
static String addKazanPercent = "$ride/kazan/add.php";
////-----------------DriverPayment------------------
static String addDrivePayment = "$ride/payment/add.php";
static String updatePaymetToPaid = "$ride/payment/updatePaymetToPaid.php";
static String addDrivePayment = "$seferPaymentServer/payment/add.php";
static String updatePaymetToPaid =
"$seferPaymentServer/payment/updatePaymetToPaid.php";
static String addSeferWallet = "$ride/seferWallet/add.php";
static String getSeferWallet = "$ride/seferWallet/get.php";
static String addDriverPaymentPoints = "$ride/driverPayment/add.php";
static String addSeferWallet = "$seferPaymentServer/seferWallet/add.php";
static String getSeferWallet = "$seferPaymentServer/seferWallet/get.php";
static String addDriverPaymentPoints =
"$seferPaymentServer/driverPayment/add.php";
static String addPaymentTokenDriver =
"$ride/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php
"$seferPaymentServer/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php
static String addPaymentTokenPassenger =
"$ride/passengerWallet/addPaymentTokenPassenger.php";
static String getDriverPaymentPoints = "$ride/driverWallet/get.php";
static String getDriverPaymentToday = "$ride/payment/get.php";
static String getCountRide = "$ride/payment/getCountRide.php";
static String getAllPaymentFromRide = "$ride/payment/getAllPayment.php";
static String getAllPaymentVisa = "$ride/payment/getAllPaymentVisa.php";
"$seferPaymentServer/passengerWallet/addPaymentTokenPassenger.php";
static String getDriverPaymentPoints =
"$seferPaymentServer/driverWallet/get.php";
static String getDriverPaymentToday = "$seferPaymentServer/payment/get.php";
static String getCountRide = "$server/ride/payment/getCountRide.php";
static String getAllPaymentFromRide =
"$seferPaymentServer/payment/getAllPayment.php";
static String getAllPaymentVisa =
"$seferPaymentServer/payment/getAllPaymentVisa.php";
//-----------------Passenger NotificationCaptain------------------
static String addNotificationPassenger =
@@ -143,8 +167,9 @@ class AppLink {
static String updateLicense = "$ride/license/updateFeedBack.php";
//-----------------RegisrationCar------------------
static String addRegisrationCar = "$ride/RegisrationCar/add.php";
static String getRegisrationCar = "$ride/RegisrationCar/get.php";
static String updateRegisrationCar = "$ride/RegisrationCar/update.php";
static String getRegisrationCar = "$endPoint/ride/RegisrationCar/get.php";
static String updateRegisrationCar =
"$endPoint/ride/RegisrationCar/update.php";
//-----------------DriverOrder------------------
@@ -165,7 +190,8 @@ class AppLink {
static String sendEmailToPassengerForTripDetails =
"$ride/rides/emailToPassengerTripDetail.php";
static String sendEmailToDrivertransaction =
"https://api.sefer.live/sefer/Admin/sendEmailToDrivertransaction.php";
"$seferPaymentServer0/Admin/sendEmailToDrivertransaction.php";
// "https://api.sefer.live/sefer/Admin/sendEmailToDrivertransaction.php";
// ===========================================
static String pathImage = "$server/upload/types/";
static String uploadImage = "$server/uploadImage.php";
@@ -180,11 +206,18 @@ class AppLink {
//==================certifcate==========
static String location = '$server/ride/location';
static String getCarsLocationByPassenger = "$location/get.php";
static String addpassengerLocation = "$location/addpassengerLocation.php";
static String getLatestLocationPassenger =
"$location/getLatestLocationPassenger.php";
static String getFemalDriverLocationByPassenger =
"$location/getFemalDriver.php";
static String getDriverCarsLocationToPassengerAfterApplied =
"$location/getDriverCarsLocationToPassengerAfterApplied.php";
static String addCarsLocationByPassenger = "$location/add.php";
static String addCarsLocationGizaEndpoint =
"https://sefergiza.site/archive%20(1)/add.php";
static String addCarsLocationAlexandriaEndpoint = "$location/add.php";
static String addCarsLocationCairoEndpoint = "$location/add.php";
static String deleteCarsLocationByPassenger = "$location/delete.php";
static String updateCarsLocationByPassenger = "$location/update.php";
static String getTotalDriverDuration = "$location/getTotalDriverDuration.php";

View File

@@ -35,44 +35,64 @@ class InviteController extends GetxController {
var data = jsonDecode(response);
driverInvitationData = data['message'];
update();
// print('driverInitationData: $driverInitationData');
}
} catch (e) {
print('Error fetching driver stats: $e');
} catch (e) {}
}
void selectPhone(String phone) {
if (box.read(BoxName.countryCode) == 'Egypt') {
invitePhoneController.text = phone;
update();
Get.back();
}
}
Future<void> pickContact() async {
Future<void> saveContactsToServer() async {
try {
// TODO: Implement the actual server upload logic here
// Simulating a server request
await Future.delayed(Duration(seconds: 2));
Get.snackbar('Success'.tr,
'${selectedContacts.length} contacts saved to server'.tr);
} catch (e) {
Get.snackbar('Error'.tr,
'An error occurred while saving contacts to server: $e'.tr);
}
}
List<Contact> contacts = <Contact>[];
List<Contact> selectedContacts = <Contact>[];
RxList<Map<String, dynamic>> contactMaps = <Map<String, dynamic>>[].obs;
Future<void> pickContacts() async {
try {
print('Requesting contact permission...');
if (await FlutterContacts.requestPermission(readonly: true)) {
print('Permission granted. Opening external contact picker...');
final Contact? contact = await FlutterContacts.openExternalPick();
if (contact != null) {
print('Contact picked: ${contact.displayName}');
if (contact.phones.isNotEmpty) {
print('Phone number found: ${contact.phones.first.number}');
invitePhoneController.text = contact.phones.first.number;
update();
} else {
print('Selected contact has no phone number.');
Get.snackbar('No phone number'.tr,
'The selected contact does not have a phone number.'.tr);
}
} else {
print('No contact selected or picker was cancelled.');
Get.snackbar('No contact selected'.tr, 'Please select a contact'.tr);
final List<Contact> fetchedContacts =
await FlutterContacts.getContacts(withProperties: true);
contacts = fetchedContacts;
// Convert contacts to a list of maps
contactMaps.value = fetchedContacts.map((contact) {
return {
'name': contact.displayName,
'phones':
contact.phones.map((phone) => phone.normalizedNumber).toList(),
'emails': contact.emails.map((email) => email.address).toList(),
};
}).toList();
update();
if (contacts.isEmpty) {
Get.snackbar('No contacts available'.tr,
'Please add contacts to your phone.'.tr);
}
} else {
print('Permission denied by user or system.');
Get.snackbar('Permission denied'.tr,
'Contact permission is required to pick a contact'.tr);
'Contact permission is required to pick contacts'.tr);
}
} catch (e) {
print('Error picking contact: $e');
print('Stack trace: ${StackTrace.current}');
Get.snackbar(
'Error'.tr, 'An error occurred while picking a contact: $e'.tr);
'Error'.tr, 'An error occurred while picking contacts: $e'.tr);
}
}
@@ -116,6 +136,33 @@ class InviteController extends GetxController {
);
}
savePhoneToServer() async {
for (var i = 0; i < contactMaps.length; i++) {
var phones = contactMaps[i]['phones'];
if (phones != null && phones.isNotEmpty && phones[0].isNotEmpty) {
var res = await CRUD().post(link: AppLink.savePhones, payload: {
"name": contactMaps[i]['name'] ?? 'none',
"phones": phones[0] ?? 'none',
"phones2": phones.join(', ') ??
'none', // Convert List<String> to a comma-separated string
});
if (res != 'failure') {}
} else {}
}
}
String formatPhoneNumber(String input) {
// Remove any non-digit characters
String digitsOnly = input.replaceAll(RegExp(r'\D'), '');
// Ensure the number starts with the country code
if (digitsOnly.startsWith('20')) {
digitsOnly = digitsOnly.substring(1);
}
return digitsOnly;
}
void sendInvite() async {
if (invitePhoneController.text.isEmpty) {
Get.snackbar('Error', 'Please enter an phone address'.tr);
@@ -123,11 +170,13 @@ class InviteController extends GetxController {
}
// try {
String phoneNumber = formatPhoneNumber(invitePhoneController.text);
var response = await CRUD().post(link: AppLink.addInviteDriver, payload: {
"driverId": box.read(BoxName.driverID),
"inviterDriverPhone": '+2${invitePhoneController.text}'
"inviterDriverPhone": phoneNumber
});
Log.print('response: ${response}');
if (response != 'failure') {
var d = jsonDecode(response);
Get.snackbar('Success', 'Invite sent successfully'.tr);
@@ -142,8 +191,7 @@ class InviteController extends GetxController {
'*Android:* https://play.google.com/store/apps/details?id=com.sefer_driver\n\n\n'
'*iOS:* https://apps.apple.com/ae/app/sefer-driver/id6502189302';
launchCommunication(
'whatsapp', '+2${invitePhoneController.text}', message);
launchCommunication('whatsapp', '+2$phoneNumber', message);
invitePhoneController.clear();
} else {
@@ -152,7 +200,6 @@ class InviteController extends GetxController {
duration: const Duration(seconds: 4));
}
// } catch (e) {
// print('Error sending invite: $e');
// Get.snackbar('Error', 'An error occurred'.tr);
// }
}

View File

@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/controller/functions/location_background_controller.dart';
import 'package:SEFER/print.dart';
import 'package:SEFER/views/auth/captin/cards/sms_signup.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:flutter/material.dart';
@@ -54,6 +55,7 @@ class LoginDriverController extends GetxController {
'email': email,
'id': driverID,
});
print(res);
if (res == 'failure') {
//Failure

View File

@@ -80,8 +80,8 @@ class RegisterCaptainController extends GetxController {
}
bool isValidEgyptianPhoneNumber(String phoneNumber) {
// Remove any whitespace from the phone number
phoneNumber = phoneNumber.replaceAll(RegExp(r'\s+'), '');
// Remove any non-digit characters (spaces, dashes, etc.)
phoneNumber = phoneNumber.replaceAll(RegExp(r'\D+'), '');
// Check if the phone number has exactly 11 digits
if (phoneNumber.length != 11) {
@@ -89,7 +89,7 @@ class RegisterCaptainController extends GetxController {
}
// Check if the phone number starts with 010, 011, 012, or 015
RegExp validPrefixes = RegExp(r'^01[0125]');
RegExp validPrefixes = RegExp(r'^01[0125]\d{8}$');
return validPrefixes.hasMatch(phoneNumber);
}

View File

@@ -86,18 +86,26 @@ class GoogleSignInHelper {
static Future<GoogleSignInAccount?> signInFromLogin() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser != null) {
await _handleSignUp(googleUser);
await Get.find<LoginDriverController>().loginUsingCredentials(
box.read(BoxName.driverID).toString(),
box.read(BoxName.emailDriver).toString(),
);
// Add detailed debug print statements
final driverID = box.read(BoxName.driverID)?.toString() ?? 'Unknown ID';
final emailDriver =
box.read(BoxName.emailDriver)?.toString() ?? 'Unknown Email';
// print('Driver ID: $driverID');
// print('Email Driver: $emailDriver');
await Get.find<LoginDriverController>()
.loginUsingCredentials(driverID, emailDriver);
}
return googleUser;
} catch (error) {
Get.snackbar('Google Sign-In error', '$error',
backgroundColor: AppColor.redColor);
// Log error details
print('Google Sign-In error: $error');
return null;
}

View File

@@ -136,6 +136,8 @@ class FirebaseMessagesController extends GetxController {
// 'Cancel Trip'.tr, 'Passenger Cancel Trip'.tr, 'cancel', '');
// }
cancelTripDialog();
} else if (message.notification!.title == 'Cancel') {
cancelTripDialog1();
} else if (message.notification!.title! == 'token change') {
// NotificationController()
// .showNotification('token change'.tr, 'token change', 'cancel');
@@ -316,6 +318,21 @@ class FirebaseMessagesController extends GetxController {
}));
}
Future<dynamic> cancelTripDialog1() {
return Get.defaultDialog(
barrierDismissible: false,
title: 'Passenger Cancel Trip'.tr,
middleText:
'Trip Cancelled. The cost of the trip will be added to your wallet.'
.tr,
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
box.write(BoxName.rideStatus, 'Cancel');
Get.offAll(HomeCaptain());
}));
}
// Future<dynamic> driverArrivePassengerDialoge() {
// return Get.defaultDialog(
// barrierDismissible: false,

View File

@@ -1,14 +1,15 @@
import 'dart:convert';
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/views/home/Captin/orderCaptin/order_request_page.dart';
import 'package:SEFER/views/home/my_wallet/walet_captain.dart';
import 'package:SEFER/views/home/Captin/orderCaptin/order_speed_request.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/notification/notification_captain.dart';
import '../home/captin/home_captain_controller.dart';
class NotificationController extends GetxController {
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
@@ -31,10 +32,10 @@ class NotificationController extends GetxController {
// Create a notification channel
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'order_channel', // Channel ID
'Order Notifications', // Channel name
'dynamic_channel', // Channel ID
'Dynamic Notifications', // Channel name
description:
'This channel is used for order notifications.', // Channel description
'This channel is used for various types of notifications.', // Channel description
importance: Importance.max,
);
@@ -56,7 +57,7 @@ class NotificationController extends GetxController {
);
AndroidNotificationDetails android =
AndroidNotificationDetails('order_channel', 'Order Notifications',
AndroidNotificationDetails('dynamic_channel', 'Dynamic Notifications',
importance: Importance.max,
priority: Priority.high,
styleInformation: bigTextStyleInformation,
@@ -68,6 +69,7 @@ class NotificationController extends GetxController {
color: AppColor.primaryColor,
showProgress: true,
showWhen: true,
timeoutAfter: title == 'Order' ? 14500 : 6000,
subText: message,
actions: [
AndroidNotificationAction(
@@ -83,42 +85,93 @@ class NotificationController extends GetxController {
NotificationDetails details = NotificationDetails(android: android);
await _flutterLocalNotificationsPlugin.show(0, title, message, details,
payload: payLoad);
// payload: 'order_page_payload');
payload: jsonEncode({'title': title, 'data': payLoad}));
}
// Callback when the notification is tapped
void onDidReceiveNotificationResponse(NotificationResponse response) {
// jsonDecode(response.payload);
_handleNotificationResponse(response);
}
// Callback when the notification is tapped while the app is in the background
void onDidReceiveBackgroundNotificationResponse(
NotificationResponse response) {
_handleNotificationResponse(response);
}
// Handle notification response for both foreground and background
void _handleNotificationResponse(NotificationResponse response) {
print('Notification tapped!');
Log.print('response.payload: ${response.payload}');
if (response.payload != null) {
print('Notification payload: ${response.payload}');
// if (response.payload != 'order_page_payload') {
// Log.print('arguments: ${box.read(BoxName.rideArguments)}');
closeOverLay();
Get.to(() => OrderRequestPage(),
arguments: {'myListString': response.payload});
// }
var payloadData = jsonDecode(response.payload.toString());
if (payloadData is Map<String, dynamic>) {
String title = payloadData['title'];
var data = payloadData['data'];
switch (title) {
case 'Order':
_handleOrderNotification(data);
break;
case 'OrderSpeed':
_handleOrderSpeedNotification(data);
break;
case 'ADS':
_handleADSNotification();
break;
default:
Log.print('Unknown notification type');
}
} else {
Log.print('Invalid payload format');
}
} else {
Log.print('Payload is null');
}
}
void _handleOrderNotification(dynamic data) {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
} else {
Log.print('Invalid order data');
}
} else {
Log.print('Invalid order payload');
}
}
void _handleOrderSpeedNotification(dynamic data) {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderSpeedRequest(), arguments: {'myListString': data});
} else {
Log.print('Invalid order data');
}
} else {
Log.print('Invalid order payload');
}
}
void _handleADSNotification() {
// var orderData = jsonDecode(data);
closeOverLay();
Get.to(
() => const NotificationCaptain(),
);
}
void onDidReceiveLocalNotification(
int id, String? title, String? body, String? payload) async {
// display a dialog with the notification details, tap ok to go to another page
}
// Callback when the notification is tapped while the app is in the background
void onDidReceiveBackgroundNotificationResponse(
NotificationResponse response) {
print('Notification tapped while app is in background!');
if (response.payload != null) {
print('Notification payload: ${response.payload}');
if (response.payload == 'order') {
Get.to(() => OrderRequestPage(),
arguments: box.read(BoxName.rideArguments));
closeOverLay();
Log.print('arguments: ${box.read(BoxName.rideArguments)}');
}
}
}
}

View File

@@ -29,9 +29,9 @@ class CRUD {
},
);
// if (response.statusCode == 200) {
// Log.print('response: ${response.request}');
// Log.print('response: ${response.body}');
// Log.print('response: ${payload}');
Log.print('response: ${response.request}');
Log.print('response: ${response.body}');
Log.print('response: ${payload}');
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
return response.body;
@@ -101,7 +101,9 @@ class CRUD {
var extractedString =
await arabicTextExtractByVisionAndAI(imagePath: imagePath);
var json = jsonDecode(extractedString);
var textValues = extractTextFromLines(json);
Log.print('textValues: ${textValues}');
// await Get.put(AI()).geminiAiExtraction(prompt, textValues);
await Get.put(AI()).anthropicAI(textValues, prompt, imagePath);
}
@@ -145,6 +147,8 @@ class CRUD {
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// Log.print(
// 'response.stream.bytesToString(): ${await response.stream.bytesToString()}');
return await response.stream.bytesToString();
} else {}
}
@@ -227,6 +231,8 @@ class CRUD {
);
Log.print('response: ${response.request}');
Log.print('response: ${response.body}');
Log.print('response: ${response.statusCode}');
Log.print('response: ${response.reasonPhrase}');
Log.print('response: ${payload}');
var jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {

View File

@@ -250,6 +250,39 @@ class AI extends GetxController {
}
}
String extractDOB(String nationalNumber) {
if (nationalNumber.length != 14) {
throw ArgumentError('National number must be 14 digits long.');
}
// Extract the first digit to determine the century
String firstDigit = nationalNumber[0];
// Extract year, month, and day parts
String yearPart = nationalNumber.substring(1, 3);
String monthPart = nationalNumber.substring(3, 5);
String dayPart = nationalNumber.substring(5, 7);
// Determine the year based on the first digit
int yearPrefix;
if (firstDigit == '2') {
yearPrefix = 1900;
} else if (firstDigit == '3') {
yearPrefix = 2000;
} else {
throw ArgumentError('Invalid first digit in national number.');
}
// Construct the full year
int year = yearPrefix + int.parse(yearPart);
// Format the date as YYYY-MM-DD
String dob =
'$year-${monthPart.padLeft(2, '0')}-${dayPart.padLeft(2, '0')}';
return dob;
}
Future<void> addDriverEgypt() async {
isLoading = true;
update();
@@ -295,7 +328,8 @@ class AI extends GetxController {
'religion':
responseIdEgyptBack['religion']?.toString() ?? 'Not specified',
'status': 'yet',
'birthdate': responseIdEgyptFront['dob']?.toString() ?? 'Not specified',
'birthdate': extractDOB(
responseIdEgyptDriverLicense['national_number'].toString()),
'maritalStatus':
responseIdEgyptBack['maritalStatus']?.toString() ?? 'Not specified',
'site': responseIdEgyptDriverLicense['address']?.toString() ??
@@ -321,6 +355,12 @@ class AI extends GetxController {
if (status1['status'] == 'success') {
isDriverSaved = true;
// CRUD().post(
// link: '${AppLink.seferGizaServer}/auth/captin/register.php',
// payload: payload);
// CRUD().post(
// link: '${AppLink.seferAlexandriaServer}/auth/captin/register.php',
// payload: payload);
Get.snackbar('Success', 'Driver data saved successfully',
backgroundColor: AppColor.greenColor);
} else {
@@ -376,6 +416,55 @@ class AI extends GetxController {
isCarSaved = true;
Get.snackbar('Success', 'message',
backgroundColor: AppColor.greenColor);
// CRUD().post(
// link:
// '${AppLink.seferAlexandriaServer}/ride/RegisrationCar/add.php',
// payload: {
// 'driverID': box.read(BoxName.driverID),
// 'vin': responseIdCardDriverEgyptBack['chassis'].toString(),
// 'car_plate':
// responseIdCardDriverEgyptFront['car_plate'].toString(),
// 'make': responseIdCardDriverEgyptBack['make'].toString(),
// 'model': responseIdCardDriverEgyptBack['model'],
// 'year': responseIdCardDriverEgyptBack['year'].toString(),
// 'expiration_date':
// responseIdCardDriverEgyptFront['LicenseExpirationDate']
// .toString(),
// 'color': responseIdCardDriverEgyptBack['color'],
// 'owner': responseIdCardDriverEgyptFront['owner'],
// 'color_hex':
// responseIdCardDriverEgyptBack['color_hex'].toString(),
// 'address': responseIdCardDriverEgyptFront['address'].toString(),
// 'displacement':
// responseIdCardDriverEgyptBack['engine'].toString(),
// 'fuel': responseIdCardDriverEgyptBack['fuel'].toString(),
// 'registration_date':
// '${responseIdCardDriverEgyptBack['inspection_date']}',
// });
// CRUD().post(
// link: '${AppLink.seferGizaServer}/ride/RegisrationCar/add.php',
// payload: {
// 'driverID': box.read(BoxName.driverID),
// 'vin': responseIdCardDriverEgyptBack['chassis'].toString(),
// 'car_plate':
// responseIdCardDriverEgyptFront['car_plate'].toString(),
// 'make': responseIdCardDriverEgyptBack['make'].toString(),
// 'model': responseIdCardDriverEgyptBack['model'],
// 'year': responseIdCardDriverEgyptBack['year'].toString(),
// 'expiration_date':
// responseIdCardDriverEgyptFront['LicenseExpirationDate']
// .toString(),
// 'color': responseIdCardDriverEgyptBack['color'],
// 'owner': responseIdCardDriverEgyptFront['owner'],
// 'color_hex':
// responseIdCardDriverEgyptBack['color_hex'].toString(),
// 'address': responseIdCardDriverEgyptFront['address'].toString(),
// 'displacement':
// responseIdCardDriverEgyptBack['engine'].toString(),
// 'fuel': responseIdCardDriverEgyptBack['fuel'].toString(),
// 'registration_date':
// '${responseIdCardDriverEgyptBack['inspection_date']}',
// });
}
} catch (e) {}
}

View File

@@ -26,9 +26,9 @@ class LocationBackgroundController extends GetxController {
Future<void> configureBackgroundLocation() async {
await BackgroundLocation.setAndroidNotification(
title: "Background Location",
message: "Tracking location...",
icon: "@mipmap/launcher_icon",
title: 'Location Tracking Active'.tr,
message: 'Your location is being tracked in the background.'.tr,
icon: '@mipmap/launcher_icon',
);
// Set the location update interval to 5 seconds

View File

@@ -10,6 +10,8 @@ import 'package:SEFER/controller/functions/crud.dart';
import 'package:SEFER/controller/home/payment/captain_wallet_controller.dart';
import 'package:SEFER/main.dart';
import '../../print.dart';
// LocationController.dart
class LocationController extends GetxController {
LocationData? _currentLocation;
@@ -40,6 +42,36 @@ class LocationController extends GetxController {
totalPoints = Get.put(CaptainWalletController()).totalPoints.toString();
// isActive = Get.put(HomeCaptainController()).isActive;
} // Function to determine which area the coordinates belong to
String getLocationArea(double latitude, double longitude) {
// Giza Boundary Check
if (latitude >= 29.904975 &&
latitude <= 30.143372 &&
longitude >= 30.787030 &&
longitude <= 31.238843) {
// box.write(BoxName.serverChosen, AppLink.seferGizaServer);
return 'Giza';
}
// Cairo Boundary Check
else if (latitude >= 29.918901 &&
latitude <= 30.198857 &&
longitude >= 31.215009 &&
longitude <= 31.532186) {
// box.write(BoxName.serverChosen, AppLink.seferCairoServer);
return 'Cairo';
}
// Alexandria Boundary Check
else if (latitude >= 30.396286 &&
latitude <= 31.654458 &&
longitude >= 29.041139 &&
longitude <= 32.626259) {
// box.write(BoxName.serverChosen, AppLink.seferAlexandriaServer);
return 'Alexandria';
}
// Return 'Unknown' if outside defined areas
return 'Unknown';
}
Future<void> startLocationUpdates() async {
@@ -53,53 +85,69 @@ class LocationController extends GetxController {
if (isActive) {
if (double.parse(totalPoints) > -3000) {
await getLocation();
String endpoint;
// if (box.read(BoxName.driverID) != null) {
await CRUD()
.post(link: AppLink.addCarsLocationByPassenger, payload: {
'driver_id': box.read(BoxName.driverID).toString(),
'latitude': myLocation.latitude.toString(),
'longitude': myLocation.longitude.toString(),
'heading': heading.toString(),
'speed': (speed * 3.6).toStringAsFixed(1),
'distance': totalDistance == 0
? '0'
: totalDistance < 1
? totalDistance.toStringAsFixed(3)
: totalDistance.toStringAsFixed(1),
'status': box.read(BoxName.statusDriverLocation).toString()
});
// Animate camera to user location (optional)
// if (Get.find<HomeCaptainController>().rideId == 'rideId') {
// Get.find<MapDriverController>()
// .mapController!
// .animateCamera(CameraUpdate.newLatLng(LatLng(
// Get.find<LocationController>().myLocation.latitude,
// Get.find<LocationController>().myLocation.longitude,
// )));
switch (
getLocationArea(myLocation.latitude, myLocation.longitude)) {
case 'Cairo':
endpoint = AppLink.addCarsLocationCairoEndpoint;
break;
case 'Giza':
endpoint = AppLink.addCarsLocationGizaEndpoint;
break;
case 'Alexandria':
endpoint = AppLink.addCarsLocationAlexandriaEndpoint;
break;
default:
print('Location outside Cairo, Giza, or Alexandria');
endpoint = AppLink.addCarsLocationByPassenger;
return;
}
if (box.read(BoxName.driverID) != null) {
await CRUD().post(link: endpoint, payload: {
'driver_id': box.read(BoxName.driverID).toString(),
'latitude': myLocation.latitude.toString(),
'longitude': myLocation.longitude.toString(),
'heading': heading.toString(),
'speed': (speed * 3.6).toStringAsFixed(1),
'distance': totalDistance == 0
? '0.0'
: totalDistance < 1
? totalDistance.toStringAsFixed(3)
: totalDistance.toStringAsFixed(1),
'status': box.read(BoxName.statusDriverLocation).toString()
});
// Animate camera to user location (optional)
// if (Get.find<HomeCaptainController>().rideId == 'rideId') {
// Get.find<MapDriverController>()
// .mapController!
// .animateCamera(CameraUpdate.newLatLng(LatLng(
// Get.find<LocationController>().myLocation.latitude,
// Get.find<LocationController>().myLocation.longitude,
// )));
}
Get.find<HomeCaptainController>()
.mapHomeCaptainController!
.animateCamera(CameraUpdate.newLatLng(LatLng(
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
)));
// if (Get.find<HomeCaptainController>().rideId == '0') {
// await sql.insertData({
// 'driver_id': box.read(BoxName.driverID),
// 'latitude': myLocation.latitude.toString(),
// 'longitude': myLocation.longitude.toString(),
// 'created_at': DateTime.now().toString(),
// }, TableName.carLocations);
// } else {
// await sql.insertData({
// 'order_id': Get.find<MapDriverController>().rideId,
// 'created_at': DateTime.now().toString(),
// 'lat': myLocation.latitude.toString(),
// 'lng': myLocation.longitude.toString(),
// }, TableName.rideLocation);
// }
}
Get.find<HomeCaptainController>()
.mapHomeCaptainController!
.animateCamera(CameraUpdate.newLatLng(LatLng(
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
)));
// if (Get.find<HomeCaptainController>().rideId == '0') {
// await sql.insertData({
// 'driver_id': box.read(BoxName.driverID),
// 'latitude': myLocation.latitude.toString(),
// 'longitude': myLocation.longitude.toString(),
// 'created_at': DateTime.now().toString(),
// }, TableName.carLocations);
// } else {
// await sql.insertData({
// 'order_id': Get.find<MapDriverController>().rideId,
// 'created_at': DateTime.now().toString(),
// 'lat': myLocation.latitude.toString(),
// 'lng': myLocation.longitude.toString(),
// }, TableName.rideLocation);
// }
// }
//
}
@@ -151,10 +199,13 @@ class LocationController extends GetxController {
(_locationData.latitude != null && _locationData.longitude != null
? LatLng(_locationData.latitude!, _locationData.longitude!)
: null)!;
getLocationArea(_locationData.latitude!, _locationData.longitude!);
speed = _locationData.speed!;
heading = _locationData.heading!;
// Calculate the distance between the current location and the previous location
if (Get.find<HomeCaptainController>().rideId == 'rideId') {
Log.print(
'Get.find<HomeCaptainController>().rideId: ${Get.find<HomeCaptainController>().rideId}');
if (previousTime > 0) {
double distance = calculateDistanceInKmPerHour(
previousTime, _locationData.time, speed);

View File

@@ -64,6 +64,12 @@ void showUpdateDialog(BuildContext context) {
Navigator.of(context).pop();
},
),
CupertinoDialogAction(
child: Text('Cancel'.tr),
onPressed: () async {
Navigator.of(context).pop();
},
),
],
);
},

View File

@@ -14,6 +14,7 @@ import 'package:path_provider/path_provider.dart' as path_provider;
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../main.dart';
import '../../print.dart';
class ImageController extends GetxController {
File? myImage;
@@ -138,6 +139,7 @@ class ImageController extends GetxController {
File compressedImage = await compressImage(processedImage);
print('link =$link');
Log.print('link: ${link}');
await uploadImage(
compressedImage,
@@ -238,7 +240,7 @@ class ImageController extends GetxController {
uploadImage(File file, Map data, String link) async {
var request = http.MultipartRequest(
'POST',
Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php'
Uri.parse(link),
);
var length = await file.length();
@@ -268,6 +270,7 @@ class ImageController extends GetxController {
var myrequest = await request.send();
var res = await http.Response.fromStream(myrequest);
if (res.statusCode == 200) {
Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
return jsonDecode(res.body);
} else {
throw Exception(

View File

@@ -0,0 +1,15 @@
import 'package:get/get.dart';
import '../../constant/box_name.dart';
import '../../main.dart';
class HomePageController extends GetxController {
late bool isVibrate = box.read(BoxName.isvibrate) ?? true;
void changeVibrateOption(bool value) {
isVibrate = box.read(BoxName.isvibrate) ?? true;
isVibrate = value;
box.write(BoxName.isvibrate, value);
update();
}
}

View File

@@ -0,0 +1,78 @@
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 '../../../constant/colors.dart';
import '../../functions/launch.dart';
class ContactUsController extends GetxController {
final String phone1 = '+201018805430';
final String phone2 = '+201080182934';
final TimeOfDay workStartTime = const TimeOfDay(hour: 12, minute: 0);
final TimeOfDay workEndTime = const TimeOfDay(hour: 19, minute: 0);
bool _isWithinWorkTime(TimeOfDay now) {
return (now.hour > workStartTime.hour ||
(now.hour == workStartTime.hour &&
now.minute >= workStartTime.minute)) &&
(now.hour < workEndTime.hour ||
(now.hour == workEndTime.hour && now.minute <= workEndTime.minute));
}
void showContactDialog(BuildContext context) {
TimeOfDay now = TimeOfDay.now();
showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
title: Text('Contact Us'.tr),
message: Text('Choose a contact option'.tr),
actions: <Widget>[
if (_isWithinWorkTime(now))
CupertinoActionSheetAction(
child: Text(phone1),
onPressed: () => makePhoneCall(
phone1,
),
),
if (_isWithinWorkTime(now))
CupertinoActionSheetAction(
child: Text(phone2),
onPressed: () => makePhoneCall(phone2),
),
if (!_isWithinWorkTime(now))
CupertinoActionSheetAction(
child: Text(
'Work time is from 12:00 - 19:00.\nYou can send a WhatsApp message or email.'
.tr),
onPressed: () => Navigator.pop(context),
),
CupertinoActionSheetAction(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
const Icon(
FontAwesome.whatsapp,
color: AppColor.greenColor,
),
Text('Send WhatsApp Message'.tr),
],
),
onPressed: () =>
launchCommunication('whatsapp', phone1, 'Hello'.tr),
),
CupertinoActionSheetAction(
child: Text('Send Email'.tr),
onPressed: () =>
launchCommunication('email', 'support@sefer.live', 'Hello'.tr),
),
],
cancelButton: CupertinoActionSheetAction(
child: Text('Cancel'.tr),
onPressed: () => Navigator.pop(context),
),
),
);
}
}

View File

@@ -0,0 +1,22 @@
import 'dart:convert';
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 'package:get/get.dart';
class MaintainCenterController extends GetxController {
bool isLoading = false;
Map tripCount = {};
Future getTripCountByCaptain() async {
var res = await CRUD().get(link: AppLink.getTripCountByCaptain, payload: {
"driver_id": box.read(BoxName.driverID).toString(),
});
if (res != 'failure') {
tripCount = jsonDecode(res)['message'];
update();
}
}
}

View File

@@ -219,12 +219,12 @@ class HomeCaptainController extends GetxController {
void onInit() async {
// await locationBackController.requestLocationPermission();
await addToken();
addToken();
await getlocation();
onButtonSelected();
await getDriverRate();
await getKazanPercent();
await getPaymentToday();
getDriverRate();
getKazanPercent();
getPaymentToday();
getCountRideToday();
getAllPayment();
startPeriodicExecution();

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:SEFER/controller/home/captin/home_captain_controller.dart';
import 'package:SEFER/controller/home/captin/order_request_controller.dart';
import 'package:SEFER/views/widgets/mydialoug.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
@@ -15,6 +16,7 @@ import '../../../constant/api_key.dart';
import '../../../constant/box_name.dart';
import '../../../constant/colors.dart';
import '../../../constant/links.dart';
import '../../../constant/table_names.dart';
import '../../../main.dart';
import '../../../views/Rate/rate_passenger.dart';
import '../../../views/home/Captin/home_captain/home_captin.dart';
@@ -169,15 +171,15 @@ class MapDriverController extends GetxController {
cancelTripFromDriverAfterApplied() async {
if (formKeyCancel.currentState!.validate()) {
await CRUD().post(link: AppLink.updateRides, payload: {
CRUD().post(link: AppLink.updateRides, payload: {
"id": rideId.toString(), // Convert to String
"status": 'CancelFromDriverAfterApply'
});
await CRUD().post(link: AppLink.addCancelRideFromPassenger, payload: {
"rideID": rideId.toString(),
"driverID": box.read(BoxName.driverID).toString(),
"passengerID": passengerId.toString(),
"note": cancelTripCotroller.text.toString()
CRUD().post(link: AppLink.addCancelTripFromDriverAfterApplied, payload: {
"order_id": rideId.toString(),
"driver_id": box.read(BoxName.driverID).toString(),
"status": 'reject After Applied',
"notes": cancelTripCotroller.text.toString()
});
FirebaseMessagesController().sendNotificationToDriverMAP(
"Cancel Trip from driver".tr,
@@ -187,6 +189,12 @@ class MapDriverController extends GetxController {
[],
'cancel.wav',
);
sql.insertData({
'order_id': rideId,
'created_at': DateTime.now().toString(),
'driver_id': box.read(BoxName.driverID).toString(),
}, TableName.driverOrdersRefuse);
Get.put(OrderRequestController()).getRefusedOrderByCaptain();
Get.offAll(HomeCaptain());
}
}
@@ -407,15 +415,29 @@ class MapDriverController extends GetxController {
updateLocation();
}
calculateDistanceBetweenDriverAndPassengerLocation() {
calculateDistanceBetweenDriverAndPassengerLocation() async {
Get.put(LocationController());
double distance2 = Geolocator.distanceBetween(
latLngPassengerLocation.latitude,
latLngPassengerLocation.longitude,
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
);
return distance2;
var res = await CRUD().get(
link: AppLink.getLatestLocationPassenger, payload: {'rideId': rideId});
if (res != 'failure') {
var passengerLatestLocationString = jsonDecode(res)['message'];
double distance2 = Geolocator.distanceBetween(
double.parse(passengerLatestLocationString[0]['lat'].toString()),
double.parse(passengerLatestLocationString[0]['lng'].toString()),
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
);
return distance2;
} else {
double distance2 = Geolocator.distanceBetween(
latLngPassengerLocation.latitude,
latLngPassengerLocation.longitude,
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
);
return distance2;
}
}
addWaitingTimeCostFromPassengerToDriverWallet() async {

View File

@@ -186,14 +186,14 @@ class OrderRequestController extends GetxController {
});
// applied = true;
if (box.read(BoxName.gender).toString() != 'Female') {
sql.insertData({
'order_id': orderID,
'created_at': DateTime.now().toString(),
'driver_id': box.read(BoxName.driverID).toString(),
}, TableName.driverOrdersRefuse);
getRefusedOrderByCaptain();
}
// if (box.read(BoxName.gender).toString() != 'Female') {
// sql.insertData({
// 'order_id': orderID,
// 'created_at': DateTime.now().toString(),
// 'driver_id': box.read(BoxName.driverID).toString(),
// }, TableName.driverOrdersRefuse);
// getRefusedOrderByCaptain();
// }
update();
// Get.back();
// Get.offAll(HomeCaptain());

View File

@@ -111,7 +111,7 @@ class CaptainWalletController extends GetxController {
// isLoading = false;
if (res != 'failure') {
walletDate = jsonDecode(res);
totalAmount = walletDate['message'][0]['total_amount'].toString();
totalAmount = walletDate['message'][0]['total_amount'] ?? '0';
update();
var res1 = await CRUD().get(
link: AppLink.getAllPaymentVisa,

View File

@@ -286,6 +286,134 @@ class MyTranslation extends Translations {
"is reviewing your order. They may need more information or a higher price.":
"يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.",
"FullName": "الاسم الكامل",
"Cancel Trip from driver": "إلغاء الرحلة من السائق",
"If you want order to another person": "إذا كنت تريد الطلب لشخص آخر",
"We will look for a new driver.\nPlease wait.":
"سنبحث عن سائق جديد.\nمن فضلك انتظر.",
"No, I want to cancel this trip": "لا، أريد إلغاء هذه الرحلة",
"Attention": "تنبيه",
'Trip Cancelled. The cost of the trip will be added to your wallet.':
"تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.",
"Trip Cancelled. The cost of the trip will be deducted from your wallet.":
"تم إلغاء الرحلة. سيتم خصم تكلفة الرحلة من محفظتك.",
"You will be charged for the cost of the driver coming to your location.":
"سيتم خصم تكلفة قدوم السائق إلى موقعك.",
"reject your order.": "رفض طلبك.",
"Location Tracking Active": "تعقب الموقع نشط",
"Your location is being tracked in the background.":
"يتم تتبع موقعك في الخلفية.",
"Maintenance Center": "‏مركز الصيانة",
"Order Under Review": "الطلب قيد المراجعة",
"When you complete 600 trips, you will be eligible to receive offers for maintenance of your car.":
"عندما تكمل 600 رحلة، ستكون مؤهلاً للحصول على عروض لصيانة سيارتك.",
"is reviewing your order. They may need more information or a higher price.":
"يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.",
"The driver canceled your ride.": "ألغى السائق رحلتك.",
"We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers.":
"لم نجد أي سائقين بعد. ضع في اعتبارك زيادة رسوم رحلتك لجعل عرضك أكثر جاذبية للسائقين.",
"Allow Location Access": "السماح بالوصول إلى الموقع",
"Show My Trip Count": "عرض عدد رحلاتي",
"SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.":
"سفر هو التطبيق الأكثر أمانًا لمشاركة الركوب الذي يقدم العديد من الميزات لكل من السائقين والركاب. نحن نقدم أقل عمولة بنسبة 8% فقط، مما يضمن حصولك على أفضل قيمة لرحلاتك. يتضمن تطبيقنا التأمين لأفضل السائقين، الصيانة المنتظمة للسيارات مع أفضل المهندسين، والخدمات على الطريق لضمان تجربة محترمة وعالية الجودة لجميع المستخدمين.",
"You can contact us during working hours from 12:00 - 19:00.":
"يمكنك الاتصال بنا خلال ساعات العمل من 12:00 - 7:00.",
"Show maintenance center near my location":
"أظهر مركز الصيانة بالقرب من موقعي",
"How do I request a ride?": "كيف أطلب رحلة؟",
"Step-by-step instructions on how to request a ride through the Sefer app.":
"تعليمات خطوة بخطوة حول كيفية طلب رحلة من خلال تطبيق Sefer.",
"What types of vehicles are available?":
"ما هي أنواع المركبات المتاحة؟",
"Sefer offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.":
"توفر Sefer مجموعة متنوعة من خيارات المركبات لتناسب احتياجاتك، بما في ذلك الاقتصادية والمريحة والفخمة. اختر الخيار الذي يناسب ميزانيتك وعدد الركاب.",
"How can I pay for my ride?": "كيف يمكنني الدفع لرحلتي؟",
"Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.":
"توفر Sefer طرق دفع متعددة لراحتك. اختر بين الدفع نقدًا أو بطاقة ائتمان/خصم أثناء تأكيد الرحلة.",
"Can I cancel my ride?": "هل يمكنني إلغاء رحلتي؟",
"Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.":
"نعم، يمكنك إلغاء رحلتك في ظل ظروف معينة (مثل قبل تعيين السائق). اطلع على سياسة الإلغاء في Sefer للحصول على التفاصيل.",
"Driver Registration & Requirements": "تسجيل السائقين والمتطلبات",
"How can I register as a driver?": "كيف يمكنني التسجيل كسائق؟",
"What are the requirements to become a driver?":
"ما هي المتطلبات للعمل كسائق؟",
'''Types of Trips in Sefer:
Comfort: For cars newer than 2017 with air conditioning.
Lady: For girl drivers.
Speed: For fixed salary and endpoints.
Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
Raih Gai: For same-day return trips longer than 50km.
''': '''
أنواع الرحلات في سيفر:
كمفورت: للسيارات الأحدث من 2017 والمكيفة.
ليدي: للسائقات النساء.
سبيد: للرحلات ذات الرواتب الثابتة والنقاط النهائية المحددة.
مشواري: للرحلات المرنة حيث يختار الركاب السيارة والسائق مسبقًا.
رايح جاي: للرحلات ذهاب وعودة في نفس اليوم لمسافات تزيد عن 50 كم.
''',
"What is Types of Trips in Sefer?": "أنواع الرحلات في سفر",
'''Sefer Wallet Features:
Transfer money multiple times.
Transfer to anyone.
Make purchases.
Charge your account.
Charge a friend's Sefer account.
Store your money with us and receive it in your bank as a monthly salary.''':
'''
مميزات محفظة سفر:
تحويل الأموال عدة مرات.
تحويل لأي شخص.
الشراء.
شحن حسابك.
شحن حساب صديقك في سفر.
الاحتفاظ بأموالك معنا واستلامها في حسابك البنكي كراتب شهري.
''',
"No Rides Available": "لا توجد رحلات متاحة حالياً",
"What are the order details we provide to you?":
"ما هي تفاصيل الطلب التي نقدمها لك؟",
"What is the feature of our wallet?": "ما هي ميزة محفظتنا؟",
"How to use SEFER": "كيف تستخدم SEFER",
"Visit our website or contact Sefer support for information on driver registration and requirements.":
"تفضل بزيارة موقعنا الإلكتروني أو اتصل بدعم Sefer للحصول على معلومات حول تسجيل السائقين والمتطلبات.",
"How do I communicate with the other party (passenger/driver)?":
"كيف أتواصل مع الطرف الآخر (الراكب/السائق)؟",
"Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.":
"توفر Sefer ميزة الدردشة داخل التطبيق لتتيح لك التواصل مع سائقك أو راكبك أثناء الرحلة.",
"What safety measures does Sefer offer?":
"ما هي تدابير السلامة التي تقدمها Sefer؟",
"Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.":
"تُولي Sefer أهمية كبيرة لسلامتك. نحن نقدم ميزات مثل التحقق من هوية السائق ، وتتبع الرحلات داخل التطبيق ، وخيارات الاتصال في حالات الطوارئ.",
'Frequently Questions': 'الأسئلة الشائعة',
"Contact Us": "اتصل بنا",
"You can change the vibration feedback for all buttons":
"يمكنك تغيير اهتزاز الرج لجميع الأزرار",
'About Us': "نبذة عنا",
"Most Secure Methods": "أساليب الأمان الأكثر فاعلية",
"In-App VOIP Calls": "مكالمات VOIP داخل التطبيق",
"Recorded Trips for Safety": "تسجيل الرحلات من أجل السلامة",
"\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.":
"\nكما أننا نضع توفير التكاليف في أولوية اهتماماتنا، ونقدم أسعاراً منافسة لجعل رحلاتك في متناول اليد.",
'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:':
"SEFER: تطبيق مشاركة الرحلات يضع سلامتك وادخارك في المقدمة SEFER هو تطبيق مشاركة رحلات مصمم مع وضع سلامتك وتوفيرك في الاعتبار. نربطك بسائقين موثوقين في منطقتك، ونضمن لك تجربة سفر مريحة وخالية من الضغوط.فيما يلي بعض الميزات الرئيسية التي تميزنا:",
"Choose a contact option": "اختر خيار الاتصال",
"Work time is from 12:00 - 19:00.\nYou can send a WhatsApp message or email.":
"وقت العمل من 12:00 - 7:00.\nيمكنك إرسال رسالة واتساب أو بريد إلكتروني.",
"Send WhatsApp Message": "إرسال رسالة واتساب",
"Send Email": "إرسال بريد إلكتروني",
"You should complete 600 trips": "يجب عليك إكمال 600 رحلة",
"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.":
"لدينا عروض صيانة لسيارتك. يمكنك استخدامها بعد إكمال 600 رحلة للحصول على خصم 20% على إصلاحات السيارة. استمتع باستخدام تطبيق SEFER وكن جزءًا من عائلتنا.",
"Enable Location Permission": "تمكين إذن الموقع",
'Allowing location access will help us display orders near you. Please enable it now.':
"سيساعدنا السماح بالوصول إلى الموقع في عرض الطلبات القريبة منك. يرجى تمكينه الآن.",

View File

@@ -19,7 +19,7 @@ class RideAvailableController extends GetxController {
update();
} else {
Get.defaultDialog(
title: 'No Rides now!'.tr,
title: "No Rides Available".tr,
middleText: '',
titleStyle: AppStyle.title,
confirm: MyElevatedButton(

View File

@@ -42,7 +42,7 @@ class DefaultFirebaseOptions {
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0',
appId: '1:594687661098:android:b7ce96c17eb928ca595f53',
appId: '1:594687661098:android:46557bd4f534b5bb595f53',
messagingSenderId: '594687661098',
projectId: 'ride-b1bd8',
storageBucket: 'ride-b1bd8.appspot.com',

View File

@@ -41,7 +41,8 @@ Future<void> backgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (Platform.isAndroid) {
if (message.notification != null && message.notification!.title != null) {
if (message.notification?.title == 'Order') {
if (message.notification?.title == 'Order' ||
message.notification?.title == 'OrderSpeed') {
var myListString = message.data['DriverList'] ?? '[]';
Log.print('myListString: $myListString');

View File

@@ -0,0 +1,101 @@
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/functions/launch.dart';
import 'package:SEFER/views/widgets/my_scafold.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 '../../../controller/functions/tts.dart';
import '../../../controller/home/captin/contact_us_controller.dart';
class ContactUsPage extends StatelessWidget {
ContactUsPage({super.key});
@override
Widget build(BuildContext context) {
Get.put(ContactUsController());
return GetBuilder<ContactUsController>(builder: (controller) {
return MyScafolld(
title: "Contact Us".tr,
body: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
decoration: AppStyle.boxDecoration1,
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.asset('assets/images/logo.gif')),
IconButton(
onPressed: () async {
Get.put(TextToSpeechController()).speakText(
'SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.'
.tr);
},
icon: const Icon(Icons.headphones),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.'
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
],
),
),
const SizedBox(
height: 30,
),
Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"You can contact us during working hours from 12:00 - 19:00."
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
InkWell(
onTap: () => controller.showContactDialog(context),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
Icons.phone,
color: AppColor.blueColor,
),
Icon(
FontAwesome.whatsapp,
color: AppColor.greenColor,
),
Icon(
Icons.email,
color: AppColor.redColor,
),
],
),
),
const SizedBox(
height: 30,
)
],
),
)
],
isleading: true);
});
}
}

View File

@@ -1,11 +1,15 @@
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/main.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:SEFER/views/widgets/my_textField.dart';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/contact.dart';
import 'package:get/get.dart';
import '../../../controller/auth/captin/invit_controller.dart';
import '../../../print.dart';
class InviteDriverScreen extends StatelessWidget {
final InviteController controller = Get.put(InviteController());
@@ -36,9 +40,43 @@ class InviteDriverScreen extends StatelessWidget {
),
),
IconButton(
icon: Icon(Icons.contacts),
icon: const Icon(Icons.contacts),
onPressed: () async {
await controller.pickContact();
await controller.pickContacts();
if (controller.contacts.isNotEmpty) {
if (box.read(BoxName.IsSavedPhones) == null) {
controller.savePhoneToServer();
box.write(BoxName.IsSavedPhones, true);
}
Get.defaultDialog(
title: 'Choose from contact'.tr,
content: Column(
children: [
SizedBox(
height: 300,
child: ListView.builder(
itemCount: controller.contactMaps.length,
itemBuilder: (context, index) {
final contact = controller.contactMaps[index];
return InkWell(
onTap: () {
controller.selectPhone(
contact['phones'].toString());
},
child: ListTile(
title: Text(contact['name'].toString()),
subtitle: Text(
controller.formatPhoneNumber(
contact['phones'][0].toString())),
),
);
},
),
),
],
),
);
}
},
),
],

View File

@@ -407,7 +407,7 @@ class LoginCaptin extends StatelessWidget {
style: AppStyle.title.copyWith(color: AppColor.greenColor),
),
MyElevatedButton(
title: 'Grant Location'.tr,
title: "Allow Location Access".tr,
onPressed: () async {
// await Get.put(LocationBackgroundController()); //////
box.write(BoxName.locationPermission, 'true');

View File

@@ -0,0 +1,101 @@
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/main.dart';
import 'package:SEFER/views/widgets/my_scafold.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class AboutPage extends StatelessWidget {
const AboutPage({super.key});
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'About Us'.tr,
body: [
// Company Logo (consider adding an image asset)
ListView(
children: [
Center(
child: Image.asset(
'assets/images/logo.png', // Replace with your logo image asset path
height: 100.0,
width: 100.0,
),
), // Company Name and Location
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'SEFER LLC\n${box.read(BoxName.countryCode).toString().tr}',
style: AppStyle.headTitle2,
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:'
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
), // Security Features List
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
children: [
Row(
children: [
const Icon(Icons.lock, color: Colors.blue),
const SizedBox(width: 8.0),
Text(
'Most Secure Methods'.tr,
style: AppStyle.title,
),
],
),
const SizedBox(height: 8.0),
Row(
children: [
const Icon(Icons.phone, color: Colors.blue),
const SizedBox(width: 8.0),
Text(
'In-App VOIP Calls'.tr,
style: AppStyle.title,
),
],
),
const SizedBox(height: 8.0),
Row(
children: [
const Icon(Icons.videocam, color: Colors.blue),
const SizedBox(width: 8.0),
Text(
'Recorded Trips for Safety'.tr,
style: AppStyle.title,
),
],
),
],
),
), // Affordability Highlight
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
'\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.'
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
],
),
// About Us Text
],
isleading: true);
}
}

View File

@@ -0,0 +1,145 @@
import 'package:SEFER/views/widgets/my_scafold.dart';
import 'package:SEFER/views/widgets/mydialoug.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../constant/style.dart';
class FrequentlyQuestionsPage extends StatelessWidget {
const FrequentlyQuestionsPage({super.key});
@override
Widget build(BuildContext context) {
String selectedPayment = 'cash'; // Replace with your initial selection
bool canCancelRide = false;
return MyScafolld(
title: 'Frequently Questions'.tr,
body: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: [
// Question 1: How do I request a ride?
ExpansionTile(
title: Text(
'How do I request a ride?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Step-by-step instructions on how to request a ride through the Sefer app.'
.tr,
style: AppStyle.title,
),
],
),
// Question 2: What types of vehicles are available?
ExpansionTile(
title: Text(
'What types of vehicles are available?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Sefer offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.'
.tr,
style: AppStyle.title,
),
],
),
// Question 3: How can I pay for my ride?
ExpansionTile(
title: Text(
'How can I pay for my ride?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
.tr,
style: AppStyle.title,
),
],
),
// Question 4: Can I cancel my ride? (if applicable)
ExpansionTile(
title: Text(
'Can I cancel my ride?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.'
.tr,
style: AppStyle.title,
),
],
),
// Question 5 & 6: Driver-specific questions
ExpansionTile(
title: Text(
'Driver Registration & Requirements'.tr,
style: AppStyle.title,
),
children: [
Text(
'${'How can I register as a driver?'.tr}\n${'What are the requirements to become a driver?'.tr}',
style: AppStyle.title,
),
InkWell(
onTap: () {
MyDialog().getDialog('title', 'midTitle', () {
; //todo add in this dialog papers for driver
});
},
child: Text(
'Visit our website or contact Sefer support for information on driver registration and requirements.'
.tr,
style: AppStyle.title,
),
),
],
),
// Question 7: How do I communicate with the other party?
ExpansionTile(
title: Text(
'How do I communicate with the other party (passenger/driver)?'
.tr,
style: AppStyle.title,
),
children: [
Text(
'Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
.tr,
style: AppStyle.title,
),
],
),
// Question 8: What safety measures does Sefer offer?
ExpansionTile(
title: Text(
'What safety measures does Sefer offer?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
.tr,
style: AppStyle.title,
),
],
),
],
),
)
],
isleading: true);
}
}

View File

@@ -8,7 +8,11 @@ import 'package:SEFER/constant/style.dart';
import 'package:SEFER/views/lang/languages.dart';
import 'package:SEFER/views/widgets/my_scafold.dart';
import '../../auth/country_widget.dart';
import '../../../../controller/functions/vibrate.dart';
import '../../../auth/country_widget.dart';
import 'about_us.dart';
import 'frequantly_question.dart';
import 'using_app_page.dart';
class SettingsCaptain extends StatelessWidget {
const SettingsCaptain({super.key});
@@ -16,6 +20,7 @@ class SettingsCaptain extends StatelessWidget {
@override
Widget build(BuildContext context) {
Get.put(SettingController());
Get.put(HomePageController());
return MyScafolld(
title: 'Settings'.tr,
body: [
@@ -67,6 +72,7 @@ class SettingsCaptain extends StatelessWidget {
GetBuilder<SettingController>(builder: (settingController) {
return CupertinoSwitch(
value: settingController.isGoogleMapsEnabled,
activeColor: AppColor.primaryColor,
onChanged: (bool value) {
settingController.onChangMapApp();
},
@@ -77,6 +83,73 @@ class SettingsCaptain extends StatelessWidget {
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()),
),
const Divider(
endIndent: 44,
indent: 44,
),
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()),
),
// ListTile(
// leading: const Icon(Icons.account_circle),
// title: const Text('Account'),

View File

@@ -0,0 +1,109 @@
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/views/widgets/my_scafold.dart';
import 'package:SEFER/views/widgets/mydialoug.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class UsingAppPage extends StatelessWidget {
const UsingAppPage({super.key});
@override
Widget build(BuildContext context) {
return MyScafolld(
title: "How to use SEFER".tr,
body: [
SizedBox(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: [
InkWell(
onTap: () {
MyDialogContent().getDialog(
"What are the order details we provide to you?".tr,
Image.network(
'https://api.sefer.live/sefer/imageForUsingApp/order_page.jpg',
height: 300,
width: 300,
fit: BoxFit.cover,
),
() {});
},
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"What are the order details we provide to you?".tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () {
MyDialog().getDialog(
"What are the order details we provide to you?".tr,
'''Sefer Wallet Features:
Transfer money multiple times.
Transfer to anyone.
Make purchases.
Charge your account.
Charge a friend's Sefer account.
Store your money with us and receive it in your bank as a monthly salary.'''
.tr,
() {});
},
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"What is the feature of our wallet?".tr,
style: AppStyle.title,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () {
MyDialog().getDialog(
"What are the order details we provide to you?".tr,
'''Types of Trips in Sefer:
Comfort: For cars newer than 2017 with air conditioning.
Lady: For girl drivers.
Speed: For fixed salary and endpoints.
Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
Raih Gai: For same-day return trips longer than 50km.
'''
.tr,
() {});
},
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"What is Types of Trips in Sefer?".tr,
style: AppStyle.title,
),
),
),
),
],
),
),
)
],
isleading: true,
);
}
}

View File

@@ -2,6 +2,7 @@ import 'package:SEFER/constant/api_key.dart';
import 'package:SEFER/constant/links.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/home/captin/home_captain_controller.dart';
import 'package:SEFER/views/auth/captin/contact_us_page.dart';
import 'package:SEFER/views/auth/captin/invite_driver_screen.dart';
import 'package:SEFER/views/notification/available_rides_page.dart';
import 'package:flutter/material.dart';
@@ -13,12 +14,13 @@ import 'package:SEFER/main.dart';
import 'package:SEFER/views/auth/captin/logout_captain.dart';
import 'package:SEFER/views/home/Captin/history/history_captain.dart';
import 'package:SEFER/views/home/Captin/home_captain/help_captain.dart';
import 'package:SEFER/views/home/Captin/settings_captain.dart';
import 'package:SEFER/views/home/Captin/About%20Us/settings_captain.dart';
import 'package:SEFER/views/home/my_wallet/walet_captain.dart';
import 'package:SEFER/views/home/profile/profile_captain.dart';
import 'package:SEFER/views/notification/notification_captain.dart';
import '../../../../controller/functions/upload_image.dart';
import '../maintain_center_page.dart';
class DrawerCaptain extends StatelessWidget {
ImageController imageController = Get.put(ImageController());
@@ -80,6 +82,20 @@ class DrawerCaptain extends StatelessWidget {
Get.to(() => InviteDriverScreen(), transition: Transition.size),
),
_buildDivider(),
_buildDrawerItem(
icon: Icons.car_repair_outlined,
text: "Maintenance Center".tr,
onTap: () =>
Get.to(() => MaintainCenterPage(), transition: Transition.size),
),
_buildDivider(),
_buildDrawerItem(
icon: Icons.contact_mail_rounded,
text: "Contact Us".tr,
onTap: () =>
Get.to(() => ContactUsPage(), transition: Transition.cupertino),
),
_buildDivider(),
_buildDrawerItem(
icon: Icons.settings,
text: 'Settings'.tr,

View File

@@ -1,17 +1,20 @@
import 'dart:io';
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/controller/home/captin/map_driver_controller.dart';
import 'package:SEFER/views/notification/available_rides_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:SEFER/views/home/Captin/home_captain/drawer_captain.dart';
import 'package:SEFER/views/widgets/mycircular.dart';
import 'package:bubble_head/bubble.dart';
import '../../../../constant/colors.dart';
import '../../../../constant/info.dart';
import '../../../../constant/style.dart';
import '../../../../constant/table_names.dart';
import '../../../../controller/functions/location_controller.dart';
import '../../../../controller/functions/overlay_permisssion.dart';
import '../../../../controller/functions/package_info.dart';
@@ -36,7 +39,7 @@ class HomeCaptain extends StatelessWidget {
Get.put(HomeCaptainController());
Get.put(CaptainWalletController());
WidgetsBinding.instance.addPostFrameCallback((_) {
// checkForUpdate(context);
checkForUpdate(context);
getPermissionOverlay();
_showFirstTimeOfferNotification(context);
});
@@ -245,65 +248,107 @@ class HomeCaptain extends StatelessWidget {
// ),
// ),
Positioned(
bottom: Get.height * .3,
bottom: Get.height * .2,
right: 6,
child: AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
Get.to(() => AvailableRidesPage());
},
icon: const Icon(
Icons.train_sharp,
size: 29,
color: AppColor.blueColor,
child: Column(
children: [
Platform.isAndroid
? AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () async {
// final Bubble _bubble = Bubble(showCloseButton: false);
// try {
// await _bubble.startBubbleHead(
// sendAppToBackground: false);
// } on PlatformException {
// print('Failed to call startBubbleHead');
// }
Bubble().startBubbleHead(sendAppToBackground: true);
},
icon: Image.asset(
'assets/images/logo1.png',
fit: BoxFit.cover,
width: 35,
height: 35,
),
),
)
: const SizedBox(),
const SizedBox(
height: 5,
),
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
Get.to(() => const AvailableRidesPage());
},
icon: const Icon(
Icons.train_sharp,
size: 29,
color: AppColor.blueColor,
),
),
),
const SizedBox(
height: 5,
),
box.read(BoxName.rideStatus) == 'Applied' ||
box.read(BoxName.rideStatus) == 'Begin'
? Positioned(
bottom: Get.height * .2,
right: 6,
child: AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
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()
};
},
icon: const Icon(
Icons.rice_bowl,
size: 29,
color: AppColor.blueColor,
),
),
),
)
: const SizedBox()
],
),
),
leftMainMenuCaptainIcons(),
box.read(BoxName.rideStatus) == 'Applied' ||
box.read(BoxName.rideStatus) == 'Begin'
? Positioned(
bottom: Get.height * .2,
right: 6,
child: AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
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()
};
},
icon: const Icon(
Icons.rice_bowl,
size: 29,
color: AppColor.blueColor,
),
),
),
)
: const SizedBox()
// callPage(),
// Positioned(

View File

@@ -1,8 +1,9 @@
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/main.dart';
import 'package:SEFER/views/auth/captin/cards/egypt_card_a_i.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:bubble_head/bubble.dart';
import 'package:get/get.dart';
import 'package:SEFER/controller/home/captin/home_captain_controller.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
@@ -185,12 +186,12 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
// "114243034311436865474",
// "113172279072358305645",
// "hamza ayed",
// "c9kqjnLqu08yogitln6B1Y:APA91bHyFJ7E7zv6-HIikwr6FrlMbi4Hc8L1STMPE99iPKqK4Gddwv8r9qZOCadsz9qTEJZ6KLEE9ruTJI6N8dKfK4CXez5pme5WIs14-1QGo29s07fQOniZgIlJV5XFL3yqzPRSUmn3",
// "rlMbi4Hc8L1STMPE99iPKqK4Gddwv8r9qZOCadsz9qTEJZ6KLEE9ruTJI6N8dKfK4CXez5pme5WIs14-1QGo29s07fQOniZgIlJV5XFL3yqzPRSUmn3",
// "+201023248456",
// "1 min",
// "1 m",
// "false",
// "em3j-v3PQlecGsTKFNU1wc:APA91bFjHq8xHpzeQwUMoyUtZ0J3oR6yXKUavrB_gBl9npUZe-qZtax-Raq4QBbdKv0AmtLKm0BfBd6N_592HBv4CVa41ii4122W3hr-BCUKKzJhzZcK8m0YjbWbtpvgJRD8uD_nuMk9",
// "QwUMoyUtZ0J3oR6yXKUavrB_gBl9npUZe-qZtax-Raq4QBbdKv0AmtLKm0BfBd6N_592HBv4CVa41ii4122W3hr-BCUKKzJhzZcK8m0YjbWbtpvgJRD8uD_nuMk9",
// "0",
// "238",
// "false",
@@ -240,23 +241,23 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
// } catch (e) {
// print('Error showing overlay: $e');
// }
// // final Bubble _bubble = Bubble(showCloseButton: true);
// // try {
// // await _bubble.startBubbleHead(sendAppToBackground: false);
// // } on PlatformException {
// // print('Failed to call startBubbleHead');
// // }
//
// // Bubble().startBubbleHead(sendAppToBackground: true);
// // }
//
// // Future<void> stopBubbleHead() async {
// // try {
// // await _bubble.stopBubbleHead();
// // } on PlatformException {
// // print('Failed to call stopBubbleHead');
// // }
// // }
// final Bubble _bubble = Bubble(showCloseButton: true);
// try {
// await _bubble.startBubbleHead(sendAppToBackground: false);
// } on PlatformException {
// print('Failed to call startBubbleHead');
// }
// Bubble().startBubbleHead(sendAppToBackground: true);
// }
// Future<void> stopBubbleHead() async {
// try {
// await _bubble.stopBubbleHead();
// } on PlatformException {
// print('Failed to call stopBubbleHead');
// }
// }
//
// // // send data to ovelay
// },
@@ -278,8 +279,7 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
// child: Builder(builder: (context) {
// return IconButton(
// onPressed: () async {
// // Log.print('box: ${box.read(BoxName.rideStatus)}');
// Log.print('box: ${box.read(BoxName.tokenDriver)}');
// Get.to(() => EgyptCardAI());
// },
// icon: const Icon(
// FontAwesome5.closed_captioning,

View File

@@ -0,0 +1,111 @@
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/home/captin/help/maintain_center_controller.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:SEFER/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,
),
),
),
);
}
}

View File

@@ -23,11 +23,12 @@ class OrderRequestPage extends StatelessWidget {
OrderRequestPage({super.key});
OrderRequestController orderRequestController =
Get.put(OrderRequestController());
// res = orderRequestController.res;
@override
Widget build(BuildContext context) {
//TODO show order from start page from sql or api
final arguments = Get.arguments;
// String res = '';
final myListString = arguments['myListString'];
var myList;
@@ -38,6 +39,20 @@ class OrderRequestPage extends StatelessWidget {
myList = arguments['DriverList'];
}
// Future.delayed(const Duration(milliseconds: 500));
// if (res.toString() == 'Apply' || res.toString() == 'Finished') {
// WidgetsBinding.instance.addPostFrameCallback((_) {
// Get.defaultDialog(
// barrierDismissible: false,
// title: 'This trip is taken'.tr,
// middleText: '',
// confirm: MyElevatedButton(
// title: 'Ok'.tr,
// onPressed: () {
// Get.back();
// }));
// });
// }
// final pointsList = arguments['PolylineJson'];
// final body = arguments['body'];
Duration durationToAdd = Duration(seconds: int.parse(myList[4]));
@@ -507,4 +522,6 @@ class OrderRequestPage extends StatelessWidget {
],
isleading: false);
}
void checkRideStatus() async {}
}

View File

@@ -148,12 +148,16 @@ class CardSeferWalletDriver extends StatelessWidget {
},
child: Container(
width: Get.width * .85,
height: Get.height * .27,
height: Get.height * .2,
decoration: BoxDecoration(
color: AppColor.deepPurpleAccent,
borderRadius: const BorderRadius.all(Radius.circular(12)),
gradient: const LinearGradient(
colors: [AppColor.greyColor, AppColor.writeColor]),
gradient: const LinearGradient(colors: [
AppColor.greyColor,
AppColor.greyColor,
AppColor.secondaryColor,
AppColor.writeColor
]),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,

View File

@@ -19,6 +19,7 @@ import 'package:SEFER/views/widgets/my_textField.dart';
import 'package:SEFER/views/widgets/mycircular.dart';
import '../../../controller/payment/driver_payment_controller.dart';
import '../../../print.dart';
import '../../widgets/my_scafold.dart';
import 'card_wallet_widget.dart';
import 'points_captain.dart';
@@ -120,6 +121,8 @@ class WalletCaptain extends StatelessWidget {
color: AppColor.writeColor)),
child: GestureDetector(
onTap: () {
Log.print(
'captainWalletController.totalAmount: ${captainWalletController.totalAmount}');
Get.snackbar(
icon: InkWell(
onTap: () async {

View File

@@ -35,8 +35,11 @@ class WeeklyPaymentPage extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
controller.weeklyList[0]['totalAmount']
.toString(),
controller.weeklyList.isEmpty
? '0'
: controller.weeklyList[0]
['totalAmount']
.toString(),
style: AppStyle.number,
),
),
@@ -57,66 +60,76 @@ class WeeklyPaymentPage extends StatelessWidget {
horizontal: 10, vertical: 5),
child: SizedBox(
height: Get.height * .75,
child: ListView.builder(
itemCount: controller.weeklyList.length,
itemBuilder: (BuildContext context, int index) {
var list = controller.weeklyList[index];
return Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
children: [
Card(
elevation: 2,
color: list['paymentMethod'] == 'visa'
? AppColor.blueColor
: AppColor.secondaryColor,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
list['paymentMethod'] ==
'Remainder'
? 'Remainder'.tr
: list['paymentMethod'] ==
'fromBudget'
? 'fromBudget'.tr
: list['paymentMethod'],
style: AppStyle.title,
),
),
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Card(
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
list['amount'],
style: AppStyle.number,
child: controller.weeklyList.isNotEmpty
? ListView.builder(
itemCount: controller.weeklyList.length,
itemBuilder:
(BuildContext context, int index) {
var list = controller.weeklyList[index];
return Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
children: [
Card(
elevation: 2,
color: list['paymentMethod'] ==
'visa'
? AppColor.blueColor
: AppColor.secondaryColor,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
list['paymentMethod'] ==
'Remainder'
? 'Remainder'.tr
: list['paymentMethod'] ==
'fromBudget'
? 'fromBudget'.tr
: list[
'paymentMethod'],
style: AppStyle.title,
),
),
),
),
Text(
DateFormat('yyyy-MM-dd hh:mm a')
.format(DateTime.parse(
list['dateUpdated'])),
style: AppStyle.number,
),
],
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Card(
child: Padding(
padding:
const EdgeInsets.all(
8.0),
child: Text(
list['amount'],
style: AppStyle.number,
),
),
),
Text(
DateFormat(
'yyyy-MM-dd hh:mm a')
.format(DateTime.parse(
list[
'dateUpdated'])),
style: AppStyle.number,
),
],
),
],
),
),
],
),
),
),
);
},
),
),
);
},
)
: const SizedBox(),
),
),
],

View File

@@ -1,19 +1,17 @@
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import '../../constant/colors.dart';
import 'package:SEFER/constant/box_name.dart';
class MyTextForm extends StatelessWidget {
MyTextForm({
super.key,
const MyTextForm({
Key? key,
required this.controller,
required this.label,
required this.hint,
required this.type,
});
}) : super(key: key);
final TextEditingController controller;
final String label, hint;
final TextInputType type;
@@ -24,53 +22,73 @@ class MyTextForm extends StatelessWidget {
padding: const EdgeInsets.only(bottom: 10),
child: SizedBox(
width: Get.width * .8,
child: TextFormField(
keyboardType: type,
cursorColor: AppColor.accentColor,
controller: controller,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppColor.primaryColor,
width: 2.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label.tr,
style: TextStyle(
color: CupertinoColors.label,
fontSize: 16,
fontWeight: FontWeight.w600,
),
borderRadius: BorderRadius.circular(10),
),
focusColor: AppColor.accentColor,
fillColor: AppColor.accentColor,
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
labelText: label.tr,
hintText: hint.tr,
),
validator: (value) {
if (value!.isEmpty) {
return '${'Please enter'.tr} $label.'.tr;
}
if (label.contains("Insert card number".tr)) {
if (value.length != 16) {
return "Please enter a valid card 16-digit number.".tr;
}
}
if (type == TextInputType.emailAddress) {
if (!value.contains('@')) {
return 'Please enter a valid email.'.tr;
}
} else if (type == TextInputType.phone) {
if (box.read(BoxName.countryCode) == 'Egypt') {
if (value.length != 11) {
return 'Please enter a valid phone number.'.tr;
}
} else if (value.length != 10) {
return 'Please enter a valid phone number.'.tr;
}
}
return null;
},
const SizedBox(height: 8),
CupertinoTextField(
controller: controller,
keyboardType: type,
placeholder: hint.tr,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: CupertinoColors.systemBackground,
border: Border.all(color: CupertinoColors.systemGrey4),
borderRadius: BorderRadius.circular(8),
),
style: const TextStyle(color: CupertinoColors.label),
placeholderStyle:
const TextStyle(color: CupertinoColors.placeholderText),
),
const SizedBox(height: 4),
ValueListenableBuilder<TextEditingValue>(
valueListenable: controller,
builder: (context, value, child) {
String? errorText = _getErrorText(value.text);
return errorText != null
? Text(
errorText,
style: const TextStyle(
color: CupertinoColors.destructiveRed,
fontSize: 12),
)
: const SizedBox.shrink();
},
),
],
),
),
);
}
String? _getErrorText(String value) {
if (value.isEmpty) {
return '${'Please enter'.tr} $label'.tr;
}
if (type == TextInputType.emailAddress) {
if (!value.contains('@')) {
return 'Please enter a valid email.'.tr;
}
} else if (type == TextInputType.phone) {
final box = GetStorage();
if (box.read(BoxName.countryCode) == 'Egypt') {
if (value.length != 11) {
return 'Please enter a valid phone number.'.tr;
}
} else if (value.length != 10) {
return 'Please enter a valid phone number.'.tr;
}
}
return null;
}
}

View File

@@ -1,43 +1,103 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../controller/functions/tts.dart';
import 'elevated_btn.dart';
import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/functions/tts.dart';
class MyDialog extends GetxController {
void getDialog(String title, String? midTitle, VoidCallback onPressed) {
final textToSpeechController = Get.put(TextToSpeechController());
Get.defaultDialog(
title: title,
titleStyle: AppStyle.title,
middleTextStyle: AppStyle.title,
content: Column(
children: [
IconButton(
Get.dialog(
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: CupertinoAlertDialog(
title: Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
content: Column(
children: [
CupertinoButton(
onPressed: () async {
await textToSpeechController.speakText(title ?? midTitle!);
},
icon: const Icon(Icons.headphones)),
Text(
midTitle!,
style: AppStyle.title,
)
child: const Icon(CupertinoIcons.headphones,
color: AppColor.primaryColor),
),
Text(
midTitle!,
style: AppStyle.title.copyWith(fontSize: 16),
),
],
),
actions: [
CupertinoDialogAction(
child: Text('Cancel', style: TextStyle(color: AppColor.redColor)),
onPressed: () {
Get.back();
},
),
CupertinoDialogAction(
child:
Text('OK'.tr, style: TextStyle(color: AppColor.greenColor)),
onPressed: onPressed,
),
],
),
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: onPressed,
kolor: AppColor.greenColor,
),
cancel: MyElevatedButton(
title: 'Cancel',
kolor: AppColor.redColor,
onPressed: () {
Get.back();
}));
),
barrierDismissible: false,
);
}
}
class MyDialogContent extends GetxController {
void getDialog(String title, Widget? content, VoidCallback onPressed) {
final textToSpeechController = Get.put(TextToSpeechController());
Get.dialog(
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: CupertinoAlertDialog(
title: Text(
title,
style: AppStyle.title.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
content: Column(
children: [
CupertinoButton(
onPressed: () async {
await textToSpeechController.speakText(title);
},
child: const Icon(CupertinoIcons.headphones,
color: AppColor.primaryColor),
),
content!
],
),
actions: [
CupertinoDialogAction(
child: Text('Cancel', style: TextStyle(color: AppColor.redColor)),
onPressed: () {
Get.back();
},
),
CupertinoDialogAction(
child:
Text('OK'.tr, style: TextStyle(color: AppColor.greenColor)),
onPressed: onPressed,
),
],
),
),
barrierDismissible: false,
);
}
}