This commit is contained in:
Hamza-Ayed
2024-08-11 10:59:50 +03:00
parent 1c6748133d
commit 2468e6466f
205 changed files with 28509 additions and 0 deletions

19
lib/constant/api_key.dart Normal file
View File

@@ -0,0 +1,19 @@
import 'package:secure_string_operations/secure_string_operations.dart';
import '../env/env.dart';
import 'char_map.dart';
class AK {
static final String basicAuthCredentials =
X.r(X.r(X.r(Env.basicAuthCredentials, cn), cC), cs);
static final String visionApi = X.r(X.r(X.r(Env.visionApi, cn), cC), cs);
static final String smsPasswordEgypt =
X.r(X.r(X.r(Env.smsPasswordEgypt, cn), cC), cs);
static final String ocpApimSubscriptionKey = Env.ocpApimSubscriptionKey;
static final String anthropicAIkeySeferNew =
X.r(X.r(X.r(Env.anthropicAIkeySeferNew, cn), cC), cs);
static final String emailService = (Env.emailService);
///////////
static final String keyOfApp = X.r(X.r(X.r(Env.keyOfApp, cn), cC), cs);
}

View File

@@ -0,0 +1,78 @@
class BoxName {
static const String driverID = "driverID";
static const String countryCode = "countryCode";
static const String googlaMapApp = "googlaMapApp";
static const String tokenParent = "tokenParent";
static const String lang = "lang";
static const String gender = "gender";
static const String carType = "carType";
static const String carPlate = "carPlate";
static const String isVerified = '0';
static const String statusDriverLocation = "statusDriverLocation";
static const String password = "password";
static const String arrivalTime = "arrivalTime";
static const String passwordDriver = "passwordDriver";
static const String agreeTerms = "agreeTerms";
static const String addWork = 'addWork';
static const String addHome = 'addHome';
static const String tipPercentage = 'tipPercentage';
static const String accountIdStripeConnect = "accountIdStripeConnect";
static const String faceDetectTimes = "faceDetectTimes";
static const String sosPhonePassenger = "sosPhonePassenger";
static const String sosPhoneDriver = "sosPhoneDriver";
static const String passengerID = "pasengerID";
static const String phone = "phone";
static const String phoneDriver = "phoneDriver";
static const String dobDriver = "dobDriver";
static const String sexDriver = "sexDriver";
static const String lastNameDriver = "lastNameDriver";
static const String name = "name";
static const String locationPermission = "locationPermission";
static const String nameDriver = "nameDriver";
static const String driverPhotoUrl = "driverPhotoUrl";
static const String passengerPhotoUrl = "passengerPhotoUrl";
static const String email = "email";
static const String emailDriver = "emailDriver";
static const String tokens = "tokens";
static const String tokenFCM = "tokenFCM";
static const String tokenDriver = "tokenDriver";
static const String cardNumber = "cardNumber";
static const String cardNumberDriver = "cardNumberDriver";
static const String cardHolderName = "cardHolderName";
static const String cardHolderNameDriver = "cardHolderNameDriver";
static const String expiryDate = "expiryDate";
static const String expiryDateDriver = "expiryDateDriver";
static const String cvvCode = "cvvCode";
static const String cvvCodeDriver = "cvvCodeDriver";
static const String passengerWalletDetails = "passengerWalletDetails";
static const String passengerWalletTotal = "passengerWalletTotal";
static const String passengerWalletFound = "passengerWalletFound";
static const String periods = 'periods';
static const String onBoarding = 'onBoarding';
static const String stripePublishableKey = 'stripe_publishableKe';
static const String apiKeyRun = 'apiKeyRun';
static const String serverAPI = 'serverAPI';
static const String secretKey = 'secretKey';
static const String basicAuthCredentials = 'basicAuthCredentials';
static const String mapAPIKEY = 'mapAPIKEY';
static const String twilloRecoveryCode = 'twilloRecoveryCode';
static const String accountSIDTwillo = 'accountSIDTwillo';
static const String authTokenTwillo = 'authTokenTwillo';
static const String chatGPTkey = 'chatGPTkey';
static const String chatGPTkeySefer = 'chatGPTkeySefer';
static const String transactionCloude = 'transactionCloude';
static const String visionApi = 'visionApi';
static const String vin = "vin";
static const String isvibrate = "isvibrate";
static const String make = "make";
static const String model = "model";
static const String year = "year";
static const String expirationDate = "expirationDate";
static const String color = "color";
static const String owner = "owner";
static const String registrationDate = "registrationDate";
static const String recentLocations = 'recentLocations';
static const String tripData = 'tripData';
static const String parentTripSelected = 'parentTripSelected';
}

View File

@@ -0,0 +1,68 @@
Map<String, String> cn = {
"0": "3",
"1": "7",
"2": "1",
"3": "9",
"4": "0",
"5": "5",
"6": "2",
"7": "6",
"8": "4",
"9": "8"
};
Map<String, String> cs = {
"a": "q",
"b": "x",
"c": "f",
"d": "y",
"e": "j",
"f": "u",
"g": "k",
"h": "w",
"i": "o",
"j": "e",
"k": "g",
"l": "r",
"m": "n",
"n": "b",
"o": "i",
"p": "v",
"q": "a",
"r": "l",
"s": "z",
"t": "c",
"u": "h",
"v": "p",
"w": "t",
"x": "d",
"y": "s",
"z": "m"
};
Map<String, String> cC = {
"A": "Q",
"B": "X",
"C": "F",
"D": "Y",
"E": "J",
"F": "U",
"G": "K",
"H": "W",
"I": "O",
"J": "E",
"K": "G",
"L": "R",
"M": "N",
"N": "B",
"O": "I",
"P": "V",
"Q": "A",
"R": "L",
"S": "Z",
"T": "C",
"U": "H",
"V": "P",
"W": "T",
"X": "D",
"Y": "S",
"Z": "M"
};

20
lib/constant/colors.dart Normal file
View File

@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
class AppColor {
static const Color primaryColor = Color(0xFF1DA1F2);
static const Color writeColor = Color(0xff222359);
static const Color bronze = Color(0xFFCD7F32);
static const Color goldenBronze = Color(0xFFB87333); // Golden bronze color
static const Color gold = Color(0xFFD4AF37);
static const Color secondaryColor = Colors.white;
static const Color accentColor = Colors.grey;
static const Color twitterColor = Color(0xFF1DA1F2); // Twitter blue
static const Color greyColor = Colors.grey;
static const Color redColor = Color(0xFFEA4335); // Google Red
static const Color greenColor = Color(0xFF34A853); // Google Green
static const Color blueColor = Color(0xFF1DA1F2); // Google Blue
static const Color yellowColor = Color(0xFFFBBC05); // Google Yellow
static Color deepPurpleAccent =
const Color.fromARGB(255, 123, 76, 254).withOpacity(0.3);
}

View File

@@ -0,0 +1,141 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import '../main.dart';
import 'box_name.dart';
class AC {
gAK() async {
if (box.read(BoxName.apiKeyRun).toString() != 'run') {
// var res = await CRUD().get(link: AppLink.getApiKey, payload: {});
// var decod = jsonDecode(res);
// print(decod);
// Map<String, dynamic> jsonData = {};
// for (var i = 0; i < decod['message'].length; i++) {
// String h = decod['message'][i]['hashed_key'].toString();
// String retrievedString = r(r(r(h, cn), cC), cs);
// await storage.write(
// key: decod['message'][i]['name'].toString(),
// value: retrievedString.toString(),
// );
// //
// String name = decod['message'][i]['name'].toString();
// String value = decod['message'][i]['hashed_key'].toString();
// jsonData[name] = value;
// }
// String jsonString = json.encode(jsonData);
// print(jsonString);
// box.write(BoxName.apiKeyRun, 'run');
}
}
String q(String b, String c) {
final d = utf8.encode(c);
final e = utf8.encode(b);
final f = Hmac(sha256, d);
final g = f.convert(e);
final h = g.bytes;
final i = base64Url.encode(h);
return i;
}
String j(String k, String l) {
final m = utf8.encode(l);
final n = base64Url.decode(k);
final o = Hmac(sha256, m);
final p = o.convert(n);
final q = utf8.decode(p.bytes);
return q;
}
String a(String b, String c) {
int d = b.length;
int e = d ~/ 4;
List<String> f = [];
for (int g = 0; g < d; g += e) {
int h = g + e;
if (h > d) {
h = d;
}
String i = b.substring(g, h);
f.add(i);
}
print(f);
Map<String, String> j = {};
j['birinci'] = f[4];
j['ikinci'] = f[2];
j['üçüncü'] = c + f[1];
j['dördüncü'] = f[0];
j['beş'] = f[3];
String k = '';
j.forEach((l, m) {
k += m;
});
return k;
}
Map<String, String> n(String o, String c) {
String p = o.replaceAll(c, '');
Map<String, String> q = {};
q['birinci'] = p[p.length - 5] + p[p.length - 3];
q['ikinci'] = p[p.length - 1] + p[p.length - 15];
q['üçüncü'] = p[p.length - 9] + p[p.length - 12];
q['dördüncü'] = p[p.length - 11] + p[p.length - 6];
q['beş'] = p[p.length - 2] + p[p.length - 8];
return q;
}
String c(String a, Map<String, String> b) {
StringBuffer c = StringBuffer();
c.write(a);
String d = "Bl";
c.write(b[d] ?? d);
StringBuffer e = StringBuffer();
String f = c.toString();
for (int g = 0; g < f.length; g++) {
String h = f[g];
e.write(b[h] ?? h);
}
return e.toString();
}
String r(String a, Map<String, String> b) {
StringBuffer c = StringBuffer();
String d = "Bl";
int e = d.length;
for (int f = 0; f < a.length; f++) {
String g = a[f];
String h = b.keys.firstWhere(
(i) => b[i] == g,
orElse: () => g,
);
c.write(h);
}
String j = c.toString();
if (j.endsWith(d)) {
j = j.substring(0, j.length - e);
}
return j;
}
}

4470
lib/constant/info.dart Normal file

File diff suppressed because one or more lines are too long

55
lib/constant/links.dart Normal file
View File

@@ -0,0 +1,55 @@
import '../env/env.dart';
class AppLink {
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 getTokens = "$server/ride/firebase/get.php";
static String gemini =
'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText';
static String uploadEgypt = "$server/uploadEgypt.php";
static String auth = '$server/auth';
static String login = "$serviceApp/login.php";
static String signUp = "$auth/signup.php";
static String sendVerifyEmail = "$auth/sendVerifyEmail.php";
static String passengerRemovedAccountEmail =
"$auth/passengerRemovedAccountEmail.php";
static String verifyEmail = "$auth/verifyEmail.php";
static String getPromptDriverDocumentsEgypt =
"$server/auth/captin/getPromptDriverDocumentsEgypt.php";
//===================Auth Captin============
static String authCaptin = '$server/auth/captin';
static String loginCaptin = "$authCaptin/login.php";
static String signUpCaptin = "$authCaptin/register.php";
static String sendVerifyEmailCaptin = "$authCaptin/sendVerifyEmail.php";
static String verifyEmailCaptin = "$authCaptin/verifyEmail.php";
static String removeUser = "$authCaptin/removeAccount.php";
static String deletecaptainAccounr = "$authCaptin/deletecaptainAccounr.php";
static String updateAccountBank = "$authCaptin/updateAccountBank.php";
static String getAccount = "$authCaptin/getAccount.php";
static String test = "$server/test.php";
static String serviceApp = "$server/serviceApp";
static String getPassengersByPhone =
"$server/serviceApp/getPassengersByPhone.php";
static String getDriverByPhone = "$serviceApp/getDriverByPhone.php";
static String getNewDriverRegister = "$serviceApp/getNewDriverRegister.php";
static String addWelcomeDriverNote = "$serviceApp/addWelcomeDriverNote.php";
static String getDriverNotCompleteRegistration =
"$serviceApp/getDriverNotCompleteRegistration.php";
static String getPassengersNotCompleteRegistration =
"$serviceApp/getPassengersNotCompleteRegistration.php";
static String addNotesDriver = "$serviceApp/addNotesDriver.php";
static String getCarPlateNotEdit = "$serviceApp/getCarPlateNotEdit.php";
static String addNotesPassenger = "$serviceApp/addNotesPassenger.php";
static String editCarPlate = "$serviceApp/editCarPlate.php";
static String getComplaintAllData = "$serviceApp/getComplaintAllData.php";
static String getComplaintAllDataForDriver =
"$serviceApp/getComplaintAllDataForDriver.php";
static String addCriminalDocuments = "$authCaptin/addCriminalDocuments.php";
static String ride = '$server/ride';
static String addRegisrationCar = "$ride/RegisrationCar/add.php";
static String getRegisrationCar = "$ride/RegisrationCar/get.php";
static String updateRegisrationCar = "$ride/RegisrationCar/update.php";
}

61
lib/constant/style.dart Normal file
View File

@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import '../main.dart';
import 'box_name.dart';
import 'colors.dart';
class AppStyle {
static TextStyle headTitle = const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40,
color: AppColor.accentColor,
);
static TextStyle headTitle2 = const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26,
color: AppColor.writeColor,
);
static TextStyle title = TextStyle(
fontWeight: FontWeight.bold,
fontSize: box.read(BoxName.lang) == 'ar' ? 14 : 16,
color: AppColor.writeColor,
);
static TextStyle subtitle = const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 13,
color: AppColor.writeColor,
);
static TextStyle number = const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: AppColor.writeColor,
fontFamily: 'digit');
static BoxDecoration boxDecoration = const BoxDecoration(
boxShadow: [
BoxShadow(
color: AppColor.accentColor, blurRadius: 5, offset: Offset(2, 4)),
BoxShadow(
color: AppColor.accentColor, blurRadius: 5, offset: Offset(-2, -2))
],
color: AppColor.secondaryColor,
borderRadius: BorderRadius.all(
Radius.elliptical(15, 30),
));
static BoxDecoration boxDecoration1 = const BoxDecoration(
boxShadow: [
BoxShadow(
color: Color.fromARGB(255, 237, 230, 230),
blurRadius: 5,
offset: Offset(2, 4)),
BoxShadow(
color: Color.fromARGB(255, 242, 237, 237),
blurRadius: 5,
offset: Offset(-2, -2))
],
color: AppColor.secondaryColor,
borderRadius: BorderRadius.all(
Radius.elliptical(15, 30),
),
);
}

View File

@@ -0,0 +1,9 @@
class TableName {
static const String placesFavorite = "placesFavorite";
static const String recentLocations = "recentLocations";
static const String carLocations = "carLocations";
static const String driverOrdersRefuse = "driverOrdersRefuse";
static const String rideLocation = "rideLocation";
static const String faceDetectTimes = "faceDetectTimes";
static const String captainNotification = "captainNotification";
}

View File

@@ -0,0 +1,117 @@
import 'dart:convert';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import '../../constant/api_key.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../main.dart';
class FirebaseMessagesController extends GetxController {
final fcmToken = FirebaseMessaging.instance;
List<String> tokens = [];
List dataTokens = [];
late String driverID;
late String driverToken;
NotificationSettings? notificationSettings;
Future<void> getNotificationSettings() async {
// Get the current notification settings
NotificationSettings? notificationSettings =
await FirebaseMessaging.instance.getNotificationSettings();
'Notification authorization status: ${notificationSettings.authorizationStatus}';
// Call the update function if needed
update();
}
Future<void> requestFirebaseMessagingPermission() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
// Check if the platform is Android
if (Platform.isAndroid) {
// Request permission for Android
await messaging.requestPermission();
} else if (Platform.isIOS) {
// Request permission for iOS
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: true,
badge: true,
carPlay: true,
criticalAlert: true,
provisional: false,
sound: true,
);
messaging.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
}
Future getTokens() async {
String? basicAuthCredentials =
await storage.read(key: BoxName.basicAuthCredentials);
var res = await http.post(
Uri.parse(AppLink.getTokens),
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
body: {},
);
var jsonResponse = jsonDecode(res.body);
if (jsonResponse['status'] == 'success') {
dataTokens = jsonResponse['data'];
for (var i = 0; i < dataTokens.length; i++) {
tokens.add(jsonResponse['data'][i]['token']);
}
box.write(BoxName.tokens, tokens);
} else {
Get.defaultDialog(title: "Warning", middleText: "Server Error");
}
}
Future getToken() async {
fcmToken.getToken().then((token) {
box.write(BoxName.tokenFCM, token);
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
// If the app is in the background or terminated, show a system tray message
RemoteNotification? notification = message.notification;
AndroidNotification? android = notification?.android;
// if (notification != null && android != null) {
if (message.data.isNotEmpty && message.notification != null) {
fireBaseTitles(message);
}
});
FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {
// Handle background message
if (message.data.isNotEmpty && message.notification != null) {
fireBaseTitles(message);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
if (message.data.isNotEmpty && message.notification != null) {
fireBaseTitles(message);
}
});
}
void fireBaseTitles(RemoteMessage message) {
if (message.notification!.title! == 'Order'.tr) {
} else if (message.notification!.title! == 'Apply Ride'.tr) {
var passengerList = message.data['passengerList'];
var myList = jsonDecode(passengerList) as List<dynamic>;
driverID = myList[0].toString();
}
}
}

View File

@@ -0,0 +1,216 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../constant/api_key.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
class CRUD {
Future<dynamic> get({
required String link,
Map<String, dynamic>? payload,
}) async {
var url = Uri.parse(
link,
);
var response = await http.post(
url,
body: payload,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
},
);
Log.print('response: ${response.body}');
Log.print('response: ${response.request}');
Log.print('payload: $payload');
// if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
return response.body;
}
return jsonData['status'];
}
// }
Future<dynamic> arabicTextExtractByVisionAndAI({
required String imagePath,
required String driverID,
}) async {
var headers = {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': AK.ocpApimSubscriptionKey
};
String imagePathFull =
'${AppLink.server}/card_image/$imagePath-$driverID.jpg';
Log.print('imagePathFull: $imagePathFull');
var request = http.Request(
'POST',
Uri.parse(
'https://eastus.api.cognitive.microsoft.com/computervision/imageanalysis:analyze?features=caption,read&model-version=latest&language=en&api-version=2024-02-01'));
request.body = json.encode({"url": imagePathFull});
Log.print('request.body: ${request.body}');
request.headers.addAll(headers);
Log.print('request.headers: ${request.headers}');
http.StreamedResponse response = await request.send();
Log.print('response: ${response}');
if (response.statusCode == 200) {
return await response.stream.bytesToString();
} else {}
}
Future<dynamic> getAgoraToken({
required String channelName,
required String uid,
}) async {
var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver);
var res = await http.get(Uri.parse(
// 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'),
'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'),
// headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'});
headers: {'Authorization': 'Bearer '});
if (res.statusCode == 200) {
var response = jsonDecode(res.body);
return response['token'];
} else {}
}
Future<dynamic> getLlama({
required String link,
required String payload,
required String prompt,
}) async {
var url = Uri.parse(
link,
);
var headers = {
'Content-Type': 'application/json',
'Authorization':
'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy'
// 'Authorization': 'Bearer ${Env.llamaKey}'
};
var data = json.encode({
"model": "Llama-3-70b-Inst-FW",
// "model": "llama-13b-chat",
"messages": [
{
"role": "user",
"content":
"Extract the desired information from the following passage as json decoded like $prompt just in this:\n\n$payload"
}
],
"temperature": 0.9
});
var response = await http.post(
url,
body: data,
headers: headers,
);
if (response.statusCode == 200) {
return response.body;
}
return response.statusCode;
}
Future<dynamic> post({
required String link,
Map<String, dynamic>? payload,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse(
link,
);
var response = await http.post(
url,
body: payload,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
print(response.request);
print(response.body);
// print(response.statusCode);
var jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
if (jsonData['status'] == 'success') {
return response.body;
} else {
String errorMessage = jsonData['message'];
// Get.snackbar('Error'.tr, errorMessage.tr,
// backgroundColor: AppColor.redColor);
return (jsonData['status']);
}
} else {
return response.statusCode;
}
}
sendEmail(
String link,
Map<String, String>? payload,
) async {
var headers = {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
};
var request = http.Request('POST', Uri.parse(link));
request.bodyFields = payload!;
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
} else {}
}
Future<dynamic> update({
required String endpoint,
required Map<String, dynamic> data,
required String id,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse('$endpoint/$id');
var response = await http.put(
url,
body: json.encode(data),
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
return json.decode(response.body);
}
Future<dynamic> delete({
required String endpoint,
required String id,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse('$endpoint/$id');
var response = await http.delete(
url,
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
return json.decode(response.body);
}
extractTextFromLines(json) {}
}

View File

@@ -0,0 +1,335 @@
import 'dart:convert';
import 'dart:io';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:image/image.dart' as img;
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import '../../constant/api_key.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../main.dart';
class ImageController extends GetxController {
File? myImage;
bool isloading = false;
CroppedFile? croppedFile;
final picker = ImagePicker();
var image;
Future<img.Image> detectAndCropDocument(File imageFile) async {
img.Image? image = img.decodeImage(await imageFile.readAsBytes());
if (image == null) throw Exception('Unable to decode image');
int left = image.width, top = image.height, right = 0, bottom = 0;
// Threshold for considering a pixel as part of the document (adjust as needed)
const int threshold = 240;
for (int y = 0; y < image.height; y++) {
for (int x = 0; x < image.width; x++) {
final pixel = image.getPixel(x, y);
final luminance = img.getLuminance(pixel);
if (luminance < threshold) {
left = x < left ? x : left;
top = y < top ? y : top;
right = x > right ? x : right;
bottom = y > bottom ? y : bottom;
}
}
}
// Add a small padding
left = (left - 5).clamp(0, image.width);
top = (top - 5).clamp(0, image.height);
right = (right + 5).clamp(0, image.width);
bottom = (bottom + 5).clamp(0, image.height);
return img.copyCrop(image,
x: left, y: top, width: right - left, height: bottom - top);
}
Future<File> rotateImageIfNeeded(File imageFile) async {
img.Image croppedDoc = await detectAndCropDocument(imageFile);
// Check if the document is in portrait orientation
bool isPortrait = croppedDoc.height > croppedDoc.width;
img.Image processedImage;
if (isPortrait) {
// Rotate the image by 90 degrees clockwise
processedImage = img.copyRotate(croppedDoc, angle: 90);
} else {
processedImage = croppedDoc;
}
// Get temporary directory
final tempDir = await path_provider.getTemporaryDirectory();
final tempPath = tempDir.path;
// Create the processed image file
File processedFile = File('$tempPath/processed_image.jpg');
await processedFile.writeAsBytes(img.encodeJpg(processedImage));
return processedFile;
}
Future<File> rotateImage(File imageFile) async {
// Read the image file
img.Image? image = img.decodeImage(await imageFile.readAsBytes());
if (image == null) return imageFile;
// Rotate the image by 90 degrees clockwise
img.Image rotatedImage = img.copyRotate(image, angle: 90);
// Get temporary directory
final tempDir = await path_provider.getTemporaryDirectory();
final tempPath = tempDir.path;
// Create the rotated image file
File rotatedFile = File('$tempPath/rotated_image.jpg');
await rotatedFile.writeAsBytes(img.encodeJpg(rotatedImage));
return rotatedFile;
}
choosImage(String link, String driverId, String imageType) async {
final pickedImage = await picker.pickImage(
source: ImageSource.gallery,
);
if (pickedImage == null) return;
image = File(pickedImage.path);
croppedFile = await ImageCropper().cropImage(
sourcePath: image!.path,
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Cropper'.tr,
toolbarColor: AppColor.blueColor,
toolbarWidgetColor: AppColor.yellowColor,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
IOSUiSettings(
title: 'Cropper'.tr,
),
],
);
if (croppedFile == null) return;
myImage = File(croppedFile!.path);
isloading = true;
update();
// Rotate the compressed image
// File rotatedImage = await rotateImage(compressedImage);
File processedImage = await rotateImageIfNeeded(File(croppedFile!.path));
File compressedImage = await compressImage(processedImage);
print('link =$link');
try {
await uploadImage(
compressedImage,
{'driverID': driverId, 'imageType': imageType},
link,
);
} catch (e) {
Get.snackbar('Image Upload Failed'.tr, e.toString(),
backgroundColor: AppColor.redColor);
} finally {
isloading = false;
update();
}
}
choosFace(String link, String imageType) async {
final pickedImage = await picker.pickImage(
source: ImageSource.camera,
preferredCameraDevice: CameraDevice.front,
);
if (pickedImage != null) {
image = File(pickedImage.path);
isloading = true;
update();
// Compress the image
File compressedImage = await compressImage(File(pickedImage.path));
// Save the picked image directly
// File savedImage = File(pickedImage.path);
print('link =$link');
try {
await uploadImage(
compressedImage,
{
'driverID':
box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
'imageType': imageType
},
link,
);
} catch (e) {
Get.snackbar('Image Upload Failed'.tr, e.toString(),
backgroundColor: AppColor.redColor);
} finally {
isloading = false;
update();
}
}
}
uploadImage(File file, Map data, String link) async {
var request = http.MultipartRequest(
'POST',
Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php'
);
var length = await file.length();
var stream = http.ByteStream(file.openRead());
var multipartFile = http.MultipartFile(
'image',
stream,
length,
filename: basename(file.path),
);
request.headers.addAll({
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
});
// Set the file name to the driverID
request.files.add(
http.MultipartFile(
'image',
stream,
length,
filename: '${box.read(BoxName.driverID)}.jpg',
),
);
data.forEach((key, value) {
request.fields[key] = value;
});
var myrequest = await request.send();
var res = await http.Response.fromStream(myrequest);
if (res.statusCode == 200) {
return jsonDecode(res.body);
} else {
throw Exception(
'Failed to upload image: ${res.statusCode} - ${res.body}');
}
}
choosImagePicture(String link, String imageType) async {
final pickedImage = await picker.pickImage(
source: ImageSource.gallery,
// preferredCameraDevice: CameraDevice.rear,
// maxHeight: Get.height * .3,
// maxWidth: Get.width * .9,
// imageQuality: 100,
);
image = File(pickedImage!.path);
croppedFile = await ImageCropper().cropImage(
sourcePath: image!.path,
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Cropper'.tr,
toolbarColor: AppColor.blueColor,
toolbarWidgetColor: AppColor.yellowColor,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
IOSUiSettings(
title: 'Cropper'.tr,
),
],
);
myImage = File(pickedImage.path);
isloading = true;
update();
// Save the cropped image
// File savedCroppedImage = File(croppedFile!.path);
File compressedImage = await compressImage(File(croppedFile!.path));
print('link =$link');
try {
await uploadImage(
compressedImage,
{
'driverID':
box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
'imageType': imageType
},
link,
);
} catch (e) {
Get.snackbar('Image Upload Failed'.tr, e.toString(),
backgroundColor: AppColor.redColor);
} finally {
isloading = false;
update();
}
}
uploadImagePicture(File file, Map data, String link) async {
var request = http.MultipartRequest(
'POST',
Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php'
);
var length = await file.length();
var stream = http.ByteStream(file.openRead());
var multipartFile = http.MultipartFile(
'image',
stream,
length,
filename: basename(file.path),
);
request.headers.addAll({
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
});
// Set the file name to the driverID
request.files.add(
http.MultipartFile(
'image',
stream,
length,
filename: '${box.read(BoxName.driverID)}.jpg',
),
);
data.forEach((key, value) {
request.fields[key] = value;
});
var myrequest = await request.send();
var res = await http.Response.fromStream(myrequest);
if (res.statusCode == 200) {
return jsonDecode(res.body);
} else {
throw Exception(
'Failed to upload image: ${res.statusCode} - ${res.body}');
}
}
}
Future<File> compressImage(File file) async {
final dir = await path_provider.getTemporaryDirectory();
final targetPath = "${dir.absolute.path}/temp.jpg";
var result = await FlutterImageCompress.compressAndGetFile(
file.absolute.path,
targetPath,
quality: 70,
minWidth: 1024,
minHeight: 1024,
);
return File(result!.path);
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/api_key.dart';
import 'package:service/constant/box_name.dart';
import 'package:service/constant/links.dart';
import 'package:service/controller/functions/crud.dart';
import 'package:service/main.dart';
import '../views/home/main.dart';
class LoginController extends GetxController {
var email = TextEditingController();
var password = TextEditingController();
final formKey = GlobalKey<FormState>();
void login() async {
if (box.read(BoxName.email) == AK.emailService) {
Get.off(Main());
} else {
if (formKey.currentState!.validate()) {
var res = await CRUD().get(link: AppLink.login, payload: {
"email": email.text,
"password": password.text,
});
if (res != 'failure') {
var d = jsonDecode(res);
if (d['message'] == "Login successful") {
box.write(BoxName.email, email.text);
Get.off(() => Main());
}
}
}
}
}
}

View File

@@ -0,0 +1,268 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/colors.dart';
import 'package:service/constant/links.dart';
import 'package:service/controller/functions/crud.dart';
import 'package:service/controller/mainController/pages/driver_page.dart';
import 'package:service/views/widgets/my_dialog.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../print.dart';
import 'pages/passengers_page.dart';
class MainController extends GetxController {
final formKey = GlobalKey<FormState>();
bool isLoading = false;
final passengerPhoneController = TextEditingController();
final driverPhoneController = TextEditingController();
final notesController = TextEditingController();
final carplateController = TextEditingController();
Map passengerData = {};
Map driverData = {};
List filteredDrivers = [];
searchPassengerByPhone() async {
if (formKey.currentState!.validate()) {
await getPassengersByPhone();
Get.back();
Get.to(() => PassengersPage());
}
}
void searchDrivers(String query) {
if (query.isEmpty) {
filteredDrivers = driverNotCompleteRegistration;
update();
} else {
filteredDrivers = driverNotCompleteRegistration
.where((driver) => driver['phone_number']
.toString()
.toLowerCase()
.contains(query.toLowerCase()))
.toList();
update();
}
}
Future<void> makePhoneCall(String phoneNumber) async {
final Uri launchUri = Uri(
scheme: 'tel',
path: phoneNumber,
);
await launchUrl(launchUri);
}
void launchCommunication(
String method, String contactInfo, String message) async {
String url;
if (Platform.isIOS) {
switch (method) {
case 'phone':
url = 'tel:$contactInfo';
break;
case 'sms':
url = 'sms:$contactInfo?body=${Uri.encodeComponent(message)}';
break;
case 'whatsapp':
url =
'https://api.whatsapp.com/send?phone=$contactInfo&text=${Uri.encodeComponent(message)}';
break;
case 'email':
url =
'mailto:$contactInfo?subject=Subject&body=${Uri.encodeComponent(message)}';
break;
default:
return;
}
} else if (Platform.isAndroid) {
switch (method) {
case 'phone':
url = 'tel:$contactInfo';
break;
case 'sms':
url = 'sms:$contactInfo?body=${Uri.encodeComponent(message)}';
break;
case 'whatsapp':
// Check if WhatsApp is installed
final bool whatsappInstalled =
await canLaunchUrl(Uri.parse('whatsapp://'));
if (whatsappInstalled) {
url =
'whatsapp://send?phone=$contactInfo&text=${Uri.encodeComponent(message)}';
} else {
// Provide an alternative action, such as opening the WhatsApp Web API
url =
'https://api.whatsapp.com/send?phone=$contactInfo&text=${Uri.encodeComponent(message)}';
}
break;
case 'email':
url =
'mailto:$contactInfo?subject=Subject&body=${Uri.encodeComponent(message)}';
break;
default:
return;
}
} else {
return;
}
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
} else {}
}
List driverNotCompleteRegistration = [];
getDriverNotCompleteRegistration() async {
var res = await CRUD()
.get(link: AppLink.getDriverNotCompleteRegistration, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
driverNotCompleteRegistration = d;
filteredDrivers = driverNotCompleteRegistration;
update();
} else {
Get.snackbar(res, '');
}
}
List newDriverRegister = [];
getNewDriverRegister() async {
var res = await CRUD().get(link: AppLink.getNewDriverRegister, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
newDriverRegister = d;
update();
} else {
Get.snackbar(res, '');
}
}
addWelcomeCall(String driveId) async {
var res = await CRUD().post(link: AppLink.addWelcomeDriverNote, payload: {
"driverId": driveId,
"notes": notesController.text,
});
if (res != 'failue') {
Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor);
}
}
String selectedStatus = "I'm not ready yet".tr;
List passengerNotCompleteRegistration = [];
getPassengerNotCompleteRegistration() async {
var res = await CRUD()
.get(link: AppLink.getPassengersNotCompleteRegistration, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
passengerNotCompleteRegistration = d;
update();
} else {
Get.snackbar(res, '');
}
}
void setSelectedStatus(String status) {
selectedStatus = status;
update();
}
final List<String> statusOptions = [
"I'm not ready yet".tr,
"I don't have a suitable vehicle".tr,
"I'll register when the app is fully launched".tr,
"I need more help understanding the app".tr,
"My documents have expired".tr,
];
List carPlateNotEdit = [];
getCarPlateNotEdit() async {
var res = await CRUD().get(link: AppLink.getCarPlateNotEdit, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
carPlateNotEdit = d;
update();
} else {
MyDialog().getDialog('No Car found yet'.tr, 'thanks'.tr, const SizedBox(),
() {
Get.back();
});
}
}
editCarPlateNotEdit(String driverId, carPlate) async {
var res = await CRUD().post(link: AppLink.editCarPlate, payload: {
"driverId": driverId,
"carPlate": carPlate,
});
if (res != 'failure') {
Get.snackbar(res, '', backgroundColor: AppColor.greenColor);
carplateController.clear();
await getCarPlateNotEdit();
update();
} else {
Get.snackbar(res, '', backgroundColor: AppColor.redColor);
}
}
saveNoteForDriverNotCompleteRegistration(String phone, editor, note) async {
var res = await CRUD().post(
link: AppLink.addNotesDriver,
payload: {"phone": phone, "editor": editor, "note": note});
if (res != 'failure') {
Get.snackbar(res, '', backgroundColor: AppColor.greenColor);
notesController.clear();
} else {
Get.snackbar(res, '', backgroundColor: AppColor.redColor);
}
}
saveNoteForPassengerNotCompleteRegistration(
String phone, editor, note) async {
var res = await CRUD().post(
link: AppLink.addNotesPassenger,
payload: {"phone": phone, "editor": editor, "note": note});
if (res != 'failure') {
Get.snackbar(res, '', backgroundColor: AppColor.greenColor);
notesController.clear();
} else {
Get.snackbar(res, '', backgroundColor: AppColor.redColor);
}
}
searchDriverByPhone() async {
if (formKey.currentState!.validate()) {
await getDriverByPhone();
Get.back();
Get.to(() => DriverPage());
}
}
getPassengersByPhone() async {
var res = await CRUD().get(
link: AppLink.getPassengersByPhone,
payload: {"phone": '+2${passengerPhoneController.text}'});
if (res != 'failure') {
var d = jsonDecode(res);
passengerData = d;
update();
}
}
getDriverByPhone() async {
var res = await CRUD().get(
link: AppLink.getDriverByPhone,
payload: {"phone": '+2${driverPhoneController.text}'});
if (res != 'failure') {
var d = jsonDecode(res);
driverData = d;
update();
}
}
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/views/widgets/my_scafold.dart';
class Complaint extends StatelessWidget {
const Complaint({super.key});
@override
Widget build(BuildContext context) {
return MyScaffold(title: "View complaint".tr, isleading: true, body: []);
}
}

View File

@@ -0,0 +1,127 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/views/widgets/my_scafold.dart';
import '../main_controller.dart';
class DriverPage extends StatelessWidget {
DriverPage({super.key});
MainController mainController = MainController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: GetBuilder<MainController>(builder: (mainController) {
Map data = mainController.driverData['message'][0];
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('${data['first_name']} ${data['last_name']}'),
),
child: SafeArea(
child: CupertinoScrollbar(
child: ListView(
children: [
_buildDriverInfoSection(
mainController.driverData['message'][0]),
_buildStatisticsSection(
mainController.driverData['message'][0]),
_buildCarInfoSection(mainController.driverData['message'][0]),
_buildLicenseInfoSection(
mainController.driverData['message'][0]),
_buildBankInfoSection(
mainController.driverData['message'][0]),
// buildCarInfo(mainController.driverData['message'][0]),
],
),
),
),
);
}),
);
}
Widget _buildDriverInfoSection(Map<String, dynamic> data) {
return CupertinoListSection.insetGrouped(
header: Text('Driver Information'.tr),
children: [
_buildInfoRow('Name'.tr, data['name_arabic']),
_buildInfoRow('Name (English)'.tr, data['name_english']),
_buildInfoRow('Phone'.tr, data['phone']),
_buildInfoRow('Email'.tr, data['email']),
_buildInfoRow('Gender'.tr, data['gender']),
_buildInfoRow('Birthdate'.tr, data['birthdate']),
_buildInfoRow('National Number'.tr, data['national_number']),
_buildInfoRow('Religion'.tr, data['religion']),
_buildInfoRow('Occupation'.tr, data['occupation']),
_buildInfoRow('Education'.tr, data['education']),
],
);
}
Widget _buildStatisticsSection(Map<String, dynamic> data) {
return CupertinoListSection.insetGrouped(
header: Text('Driver Statistics'.tr),
children: [
_buildInfoRow('Total Rides'.tr, data['countRide'].toString()),
_buildInfoRow('Average Rating'.tr, data['rating'].toString()),
_buildInfoRow('Total Payments'.tr, '\$${data['totalPayment']}'),
_buildInfoRow('Wallet Balance'.tr, '\$${data['totalDriverWallet']}'),
_buildInfoRow('Complaints'.tr, data['countComplaint'].toString()),
_buildInfoRow('Scam Reports'.tr, data['countScam'].toString()),
_buildInfoRow(
'Passengers Rated'.tr, data['DRatingPassengersCount'].toString()),
_buildInfoRow(
'Avg Passenger Rating'.tr, data['avgDRatingPassenger'].toString()),
],
);
}
Widget _buildCarInfoSection(Map<String, dynamic> data) {
return CupertinoListSection.insetGrouped(
header: Text('Vehicle Information'.tr),
children: [
_buildInfoRow('VIN'.tr, data['vin']),
_buildInfoRow('Plate Number'.tr, data['car_plate']),
_buildInfoRow('Make'.tr, data['make']),
_buildInfoRow('Model'.tr, data['model']),
_buildInfoRow('Year'.tr, data['year']),
_buildInfoRow('Color'.tr, data['color']),
_buildInfoRow('Fuel Type'.tr, data['fuel']),
_buildInfoRow('Displacement'.tr, data['displacement']),
_buildInfoRow('Registration Date'.tr, data['registration_date']),
_buildInfoRow('Expiration Date'.tr, data['expiration_date']),
],
);
}
Widget _buildLicenseInfoSection(Map<String, dynamic> data) {
return CupertinoListSection.insetGrouped(
header: Text('License Information'.tr),
children: [
_buildInfoRow('License Type'.tr, data['license_type']),
_buildInfoRow('Card ID'.tr, data['card_id']),
_buildInfoRow('Issue Date'.tr, data['issue_date']),
_buildInfoRow('Expiry Date'.tr, data['expiry_date']),
_buildInfoRow('Categories'.tr, data['license_categories']),
],
);
}
Widget _buildBankInfoSection(Map<String, dynamic> data) {
return CupertinoListSection.insetGrouped(
header: Text('Bank Information'.tr),
children: [
_buildInfoRow('Account Number'.tr, data['accountBank']),
_buildInfoRow('Bank Code'.tr, data['bankCode']),
],
);
}
Widget _buildInfoRow(String label, String value) {
return CupertinoListTile(
title: Text(label),
trailing: Text(value,
style: const TextStyle(color: CupertinoColors.systemGrey)),
);
}
}

View File

@@ -0,0 +1,218 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/colors.dart';
import 'package:service/controller/mainController/main_controller.dart';
import 'package:service/views/widgets/my_scafold.dart';
import 'registration_captain_page.dart';
class DriversCantRegister extends StatelessWidget {
DriversCantRegister({super.key});
@override
Widget build(BuildContext context) {
Get.put(MainController());
return MyScaffold(
title: 'Drivers Cant Register'.tr,
isleading: true,
body: [
GetBuilder<MainController>(builder: (mainController) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: CupertinoSearchTextField(
keyboardType: TextInputType.phone,
onChanged: (value) => mainController.searchDrivers(value),
placeholder: 'Search by phone number'.tr,
),
),
Expanded(
child: ListView.builder(
itemCount: mainController.filteredDrivers.length,
itemBuilder: (context, index) {
final driver = mainController.filteredDrivers[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: driver['note'] == null
? AppColor.greenColor
: AppColor.greyColor,
child: CupertinoFormSection(
header: Text(
'Driver ID: ${driver['driverId']}',
),
children: [
InkWell(
onTap: () => mainController
.makePhoneCall(driver['phone_number']),
child: Container(
height: 40,
color: driver['note'] != null
? AppColor.greenColor
: AppColor.greyColor,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: [
Text(driver['phone_number']),
IconButton(
onPressed: () {
String message = "مرحباً،\n\n"
"نلاحظ أنك لم تكمل عملية التسجيل في خدمة سفر درايفر. نود تذكيرك بأن إكمال التسجيل يتيح لك فرصة الانضمام إلى فريق سفر والاستفادة من خدماتنا المتنوعة.\n\n"
"إذا كنت بحاجة إلى أي مساعدة أو لديك أي استفسارات، لا تتردد في الاتصال بنا. نحن هنا لمساعدتك.\n\n"
"للاتصال بنا، يرجى الاتصال على الرقم التالي: +20 101 880 5430\n\n"
"مع تحيات فريق سفر.";
mainController.launchCommunication(
'whatsapp',
'${driver['phone_number']}',
message);
},
icon: const Icon(
Icons.send_time_extension_sharp,
color: AppColor.secondaryColor,
),
),
IconButton(
onPressed: () {
Get.to(() => RegisterCaptain(),
arguments: {
"phone_number":
driver['phone_number']
.toString(),
'driverId': driver['driverId']
.toString(),
'email':
driver['email'].toString(),
});
},
icon: const Icon(
Icons.save,
color: AppColor.gold,
),
),
],
)
// CupertinoFormRow(
// prefix: Text('Phone Number'.tr),
// child: CupertinoTextFormFieldRow(
// initialValue: driver['phone_number'],
// readOnly: true,
// placeholder: 'Phone Number'.tr,
// ),
// ),
),
),
CupertinoFormRow(
prefix: Text('Created At'.tr),
child: CupertinoTextFormFieldRow(
initialValue: driver['created_at'],
readOnly: true,
placeholder: 'Created At',
),
),
CupertinoFormRow(
prefix: Text('Status'.tr),
child: GestureDetector(
onTap: () {
showCupertinoModalPopup<void>(
context: Get.context!,
builder: (BuildContext context) =>
Container(
height: 216,
padding: const EdgeInsets.only(top: 6.0),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context)
.viewInsets
.bottom,
),
color: CupertinoColors.systemBackground
.resolveFrom(context),
child: SafeArea(
top: false,
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
itemExtent: 32.0,
scrollController:
FixedExtentScrollController(
initialItem: mainController
.selectedStatus
.indexOf(mainController
.selectedStatus),
),
onSelectedItemChanged:
(int selectedItem) {
mainController.setSelectedStatus(
mainController
.statusOptions[selectedItem]
.tr);
},
children: List<Widget>.generate(
mainController.statusOptions
.length, (int index) {
return Center(
child: Text(mainController
.statusOptions[index].tr),
);
}),
),
),
),
);
},
child: CupertinoFormRow(
child: Text(
mainController.selectedStatus.tr,
style: TextStyle(
color: CupertinoColors.label
.resolveFrom(Get.context!)),
),
),
),
),
CupertinoFormRow(
prefix: Text('Notes'.tr),
child: CupertinoTextFormFieldRow(
cursorColor: AppColor.blueColor,
controller: mainController.notesController,
placeholder:
driver['note'] ?? "Additional comments".tr,
),
),
CupertinoButton(
child: Text('Save Notes'.tr),
onPressed: () {
// Save the notes for the driver
String notes =
mainController.notesController.text == ''
? mainController.selectedStatus
.toString()
: mainController.notesController.text;
mainController
.saveNoteForDriverNotCompleteRegistration(
driver['phone_number'],
'girls name',
notes);
print(
'Notes for driver ${driver['id']}: $notes');
},
),
],
),
),
);
},
),
),
],
);
}),
],
);
}
}

View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/colors.dart';
import 'package:service/constant/style.dart';
import 'package:service/views/widgets/my_scafold.dart';
import 'package:service/views/widgets/my_textField.dart';
import '../main_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class EditCarPlate extends StatelessWidget {
const EditCarPlate({super.key});
@override
Widget build(BuildContext context) {
Get.put(MainController());
return GetBuilder<MainController>(builder: (mainController) {
return MyScaffold(
title: 'Edit car plate'.tr,
isleading: true,
body: [
Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: mainController
.carPlateNotEdit.length, // 10 fields + 1 save button
itemBuilder: (context, index) {
var carData = mainController.carPlateNotEdit[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: AppStyle.boxDecoration1,
child: Column(
children: [
Image.network(
'https://api.sefer.live/sefer/card_image/car_front-${carData['driverID']}.jpg',
height: 200,
width: double.maxFinite,
fit: BoxFit.fill,
),
const SizedBox(
height: 9,
),
Form(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: () async {
await mainController.editCarPlateNotEdit(
carData['driverID'].toString(),
mainController.carplateController.text,
);
},
icon: const Icon(
Icons.upload_outlined,
color: AppColor.blueColor,
),
),
SizedBox(
width: Get.width * .6,
child: MyTextForm(
controller:
mainController.carplateController,
label: 'car plate'.tr,
hint: 'car plate'.tr,
type: TextInputType.name,
),
),
],
))
],
)),
);
}),
),
],
);
});
}
}

View File

@@ -0,0 +1,77 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/controller/mainController/main_controller.dart';
import 'package:service/views/widgets/my_scafold.dart';
class PassengersCantRegister extends StatelessWidget {
PassengersCantRegister({super.key});
@override
Widget build(BuildContext context) {
Get.put(MainController());
return MyScaffold(
title: 'Passengers Cant Register'.tr,
isleading: true,
body: [
GetBuilder<MainController>(builder: (mainController) {
return ListView.builder(
itemCount: mainController.passengerNotCompleteRegistration.length,
itemBuilder: (context, index) {
final passenger =
mainController.passengerNotCompleteRegistration[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: CupertinoFormSection(
header: Text('Passenger ID: ${passenger['id']}'),
children: [
InkWell(
onTap: () => mainController
.makePhoneCall(passenger['phone_number']),
child: CupertinoFormRow(
prefix: Text('Phone Number'.tr),
child: CupertinoTextFormFieldRow(
initialValue: passenger['phone_number'],
readOnly: true,
placeholder: 'Phone Number'.tr,
),
),
),
CupertinoFormRow(
prefix: Text('Created At'.tr),
child: CupertinoTextFormFieldRow(
initialValue: passenger['created_at'],
readOnly: true,
placeholder: 'Created At',
),
),
CupertinoFormRow(
prefix: Text('Notes'.tr),
child: CupertinoTextFormFieldRow(
controller: mainController.notesController,
placeholder:
passenger['note'] ?? 'Enter notes after call'.tr,
),
),
CupertinoButton(
child: Text('Save Notes'.tr),
onPressed: () {
// Save the notes for the Passenger
String notes = mainController.notesController.text;
mainController
.saveNoteForPassengerNotCompleteRegistration(
passenger['phone_number'], 'girls name', notes);
print('Notes for Passenger ${passenger['id']}: $notes');
},
),
],
),
);
},
);
}),
],
);
}
}

View File

@@ -0,0 +1,133 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/controller/mainController/main_controller.dart';
import 'package:service/views/widgets/my_scafold.dart';
class PassengersPage extends StatelessWidget {
PassengersPage({super.key});
final MainController mainController = MainController();
@override
Widget build(BuildContext context) {
return GetBuilder<MainController>(builder: (mainController) {
Map data = mainController.passengerData['message'][0];
return MyScaffold(
title: (data['first_name']?.toString() ?? '') +
' ' +
(data['last_name']?.toString() ?? ''),
isleading: true,
body: [
ListView(
children: [
_buildPersonalInfoCard(data),
_buildLatestRideCard(data),
_buildWalletInfoCard(data),
],
),
],
);
});
}
Widget _buildPersonalInfoCard(Map data) {
return Card(
margin: const EdgeInsets.all(16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Personal Information'.tr,
style:
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildInfoRow('Phone'.tr, data['phone']?.toString() ?? 'N/A'),
_buildInfoRow('Email'.tr, data['email']?.toString() ?? 'N/A'),
_buildInfoRow('Gender'.tr, data['gender']?.toString() ?? 'N/A'),
_buildInfoRow(
'Birthdate'.tr, data['birthdate']?.toString() ?? 'N/A'),
_buildInfoRow(
'Education'.tr, data['education']?.toString() ?? 'N/A'),
_buildInfoRow(
'Employment'.tr, data['employmentType']?.toString() ?? 'N/A'),
_buildInfoRow('Marital Status'.tr,
data['maritalStatus']?.toString() ?? 'N/A'),
],
),
),
);
}
Widget _buildLatestRideCard(Map data) {
return Card(
margin: const EdgeInsets.all(16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Latest Ride'.tr,
style:
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildInfoRow('Ride ID'.tr, data['ride_id']?.toString() ?? 'N/A'),
_buildInfoRow('Date'.tr, data['ride_date']?.toString() ?? 'N/A'),
_buildInfoRow(
'Start Time'.tr, data['ride_time']?.toString() ?? 'N/A'),
_buildInfoRow(
'End Time'.tr, data['ride_endtime']?.toString() ?? 'N/A'),
_buildInfoRow(
'Price'.tr, '\$${data['price']?.toString() ?? 'N/A'}'),
_buildInfoRow(
'Status'.tr, data['ride_status']?.toString() ?? 'N/A'),
_buildInfoRow('Payment Method'.tr,
data['ride_payment_method']?.toString() ?? 'N/A'),
_buildInfoRow('Car Type'.tr, data['car_type']?.toString() ?? 'N/A'),
_buildInfoRow(
'Distance'.tr,
data['distance'] != null
? '${data['distance'].toStringAsFixed(2)} km'
: 'N/A'),
],
),
),
);
}
Widget _buildWalletInfoCard(Map data) {
return Card(
margin: const EdgeInsets.all(16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Wallet Information'.tr,
style:
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildInfoRow('Wallet Balance'.tr,
'\$${data['passenger_wallet_balance']?.toString() ?? 'N/A'}'),
_buildInfoRow('Last Payment Amount'.tr,
'\$${data['passenger_payment_amount']?.toString() ?? 'N/A'}'),
_buildInfoRow('Last Payment Method'.tr,
data['passenger_payment_method']?.toString() ?? 'N/A'),
],
),
),
);
}
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
Text(value),
],
),
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:service/constant/colors.dart';
import 'package:service/constant/style.dart';
import 'package:service/views/widgets/elevated_btn.dart';
import 'package:service/views/widgets/my_scafold.dart';
import '../main_controller.dart';
class WelcomeCall extends StatelessWidget {
const WelcomeCall({super.key});
@override
Widget build(BuildContext context) {
Get.put(MainController());
return MyScaffold(
title: 'Welcome Drivers'.tr,
isleading: true,
body: [
GetBuilder<MainController>(builder: (mainController) {
return Expanded(
child: CupertinoScrollbar(
child: ListView.builder(
itemCount: mainController.newDriverRegister.length,
itemBuilder: (context, index) {
final driver = mainController.newDriverRegister[index];
return DriverCard(driver: driver);
},
),
),
);
}),
],
);
}
}
class DriverCard extends StatelessWidget {
final Map<String, dynamic> driver;
const DriverCard({super.key, required this.driver});
@override
Widget build(BuildContext context) {
return CupertinoCard(
margin: const EdgeInsets.all(16.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: AppStyle.boxDecoration1.copyWith(
color: driver['isCall'].toString() == '1'
? AppColor.greenColor
: AppColor.accentColor),
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 2),
child: Text(
'Driver Information'.tr,
style: CupertinoTheme.of(context).textTheme.navTitleTextStyle,
),
),
),
const SizedBox(height: 16),
InfoText('Name'.tr, driver['name_arabic'].toString()),
InfoText('Phone'.tr, driver['phone'].toString()),
InfoText('Email'.tr, driver['email'].toString()),
InfoText('License Type'.tr, driver['license_type'].toString()),
InfoText(
'License Categories'.tr, driver['license_categories'] ?? ''),
InfoText(
'National Number'.tr, driver['national_number'].toString()),
InfoText('Occupation'.tr, driver['occupation'].toString()),
const SizedBox(height: 16),
Text(
'Notes:'.tr,
style: CupertinoTheme.of(context).textTheme.navTitleTextStyle,
),
const SizedBox(height: 8),
CupertinoTextField(
controller: Get.find<MainController>().notesController,
placeholder: driver['notes'] ?? 'Enter notes here...'.tr,
maxLines: 3,
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemGrey),
borderRadius: BorderRadius.circular(8.0),
),
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: Get.width * .4,
child: MyElevatedButton(
title: 'Call Driver'.tr,
onPressed: () {
Get.find<MainController>()
.makePhoneCall(driver['phone'].toString());
})),
CupertinoButton(
onPressed: () async {
await Get.find<MainController>().addWelcomeCall(
driver['id'].toString(),
);
},
child: Text('Save Changes'.tr),
),
],
),
],
),
),
);
}
}
class InfoText extends StatelessWidget {
final String label;
final String value;
const InfoText(this.label, this.value, {super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Text(
'$label: $value',
style: CupertinoTheme.of(context).textTheme.textStyle,
),
);
}
}
class CupertinoCard extends StatelessWidget {
final Widget child;
final EdgeInsetsGeometry margin;
const CupertinoCard(
{super.key, required this.child, this.margin = EdgeInsets.zero});
@override
Widget build(BuildContext context) {
return Container(
margin: margin,
decoration: BoxDecoration(
color: CupertinoColors.systemBackground,
borderRadius: BorderRadius.circular(12.0),
boxShadow: [
BoxShadow(
color: CupertinoColors.systemGrey.withOpacity(0.2),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: child,
);
}
}

View File

@@ -0,0 +1,993 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:service/views/widgets/elevated_btn.dart';
import '../../constant/api_key.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/info.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../main.dart';
import '../../print.dart';
import '../functions/crud.dart';
import '../functions/image.dart';
enum DocumentType {
carLicenseFront,
carLicenseBack,
idCardFront,
idCardBack,
driverLicense,
unknown,
}
class RegisterCaptainController extends GetxController {
bool isDriverSaved = false;
bool isCarSaved = false;
Map<String, dynamic>? arguments;
String? driverId;
String? email;
String? phone;
@override
void onInit() {
super.onInit();
arguments = Get.arguments;
getPrompt();
initArguments();
}
void driveInit() {
arguments = Get.arguments;
initArguments();
}
void initArguments() {
if (arguments != null) {
driverId = arguments!['driverId'];
email = arguments!['email'];
phone = arguments!['phone_number'];
} else {
print('Arguments are null');
}
}
Map<String, dynamic> responseMap = {};
Map<String, dynamic> responseCarLicenseMapJordan = {};
Map<String, dynamic> responseBackCarLicenseMap = {};
Map<String, dynamic> responseIdCardMap = {};
Map<String, dynamic> responseIdCardDriverEgyptBack = {};
Map<String, dynamic> responseForComplaint = {};
Map<String, dynamic> responseIdCardDriverEgyptFront = {};
Map<String, dynamic> responseIdEgyptFront = {};
Map<String, dynamic> responseCriminalRecordEgypt = {};
Map<String, dynamic> responseIdEgyptBack = {};
Map<String, dynamic> responseIdEgyptDriverLicense = {};
String? responseIdCardDriverEgypt1;
bool isloading = false;
var image;
DateTime now = DateTime.now();
bool isLoading = false;
String getExpectedDocument(String imagePath) {
switch (imagePath) {
case 'car_front':
return 'car_license_front'.tr;
case 'car_back':
return 'car_license_back'.tr;
case 'id_back':
return 'id_card_back'.tr;
case 'id_front':
return 'id_card_front'.tr;
case 'driver_license':
return 'driver_license'.tr;
default:
return 'unknown_document'.tr;
}
}
DocumentType getExpectedType(String imagePath) {
switch (imagePath) {
case 'car_front':
return DocumentType.carLicenseFront;
case 'car_back':
return DocumentType.carLicenseBack;
case 'id_back':
return DocumentType.idCardBack;
case 'id_front':
return DocumentType.idCardFront;
case 'driver_license':
return DocumentType.driverLicense;
default:
return DocumentType.unknown;
}
}
String getDetectedDocument(DocumentType type) {
switch (type) {
case DocumentType.carLicenseFront:
return 'car_license_front'.tr;
case DocumentType.carLicenseBack:
return 'car_license_back'.tr;
case DocumentType.idCardFront:
return 'id_card_front'.tr;
case DocumentType.idCardBack:
return 'id_card_back'.tr;
case DocumentType.driverLicense:
return 'driver_license'.tr;
default:
return 'unknown_document'.tr;
}
}
DocumentType checkDocumentType(String text) {
// Convert text to lowercase and remove all spaces and new lines
text = text.toLowerCase().replaceAll(RegExp(r'\s+'), '');
// Keywords for each document type
final Map<DocumentType, List<String>> keywords = {
DocumentType.carLicenseBack: ['شاسيه', 'موتور', 'سم٣'],
DocumentType.carLicenseFront: ['رخصةتسيير'],
DocumentType.idCardFront: [
'بطاقةتحقيقالشخصية',
'بطاقة تحقيق الشخصية',
'تحقيق'
],
DocumentType.idCardBack: ['البطاقةساريةحتى'],
DocumentType.driverLicense: ['قيادةخاصة', 'خاصه', 'قيادة'],
};
// Check each document type
for (var entry in keywords.entries) {
if (entry.value.any((keyword) => text.contains(keyword))) {
return entry.key;
}
}
// If no match is found
return DocumentType.unknown;
}
List prompts = [];
getPrompt() async {
var res = await CRUD()
.get(link: AppLink.getPromptDriverDocumentsEgypt, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
prompts = d;
} else {}
}
Future allMethodForAI(String prompt, imagePath, driverID) async {
isLoading = true;
update();
await ImageController()
.choosImage(AppLink.uploadEgypt, driverID, imagePath);
var extractedString = await CRUD().arabicTextExtractByVisionAndAI(
imagePath: imagePath, driverID: driverID);
var json = jsonDecode(extractedString);
var textValues = extractTextFromLines(json);
Log.print('textValues: ${textValues}');
// await Get.put(AI()).geminiAiExtraction(prompt, textValues, imagePath);
DocumentType detectedType = checkDocumentType(textValues);
String expectedDocument = getExpectedDocument(imagePath);
String detectedDocument = getDetectedDocument(detectedType);
bool isCorrectDocument = (detectedType == getExpectedType(imagePath));
if (!isCorrectDocument) {
Get.defaultDialog(
title: 'incorrect_document_title'.tr,
middleText:
'${'expected'.tr}: $expectedDocument\n${'detected'.tr}: $detectedDocument',
confirm: MyElevatedButton(
title: 'OK'.tr,
onPressed: () {
Get.back();
}));
} else {
// Process the correct document
await anthropicAI(textValues, prompt, imagePath);
}
isLoading = false;
update();
}
String extractTextFromLines(Map<String, dynamic> jsonData) {
final readResult = jsonData['readResult'];
final blocks = readResult['blocks'];
final StringBuffer buffer = StringBuffer();
for (final block in blocks) {
final lines = block['lines'];
for (final line in lines) {
final text = line['text'];
buffer.write(text);
buffer.write('\n');
}
}
return buffer.toString().trim();
}
List driverNotCompleteRegistration = [];
getDriverNotCompleteRegistration() async {
var res = await CRUD()
.get(link: AppLink.getDriverNotCompleteRegistration, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
driverNotCompleteRegistration = d;
update();
} else {
Get.snackbar(res, '');
}
}
final today = DateTime.now();
Future<void> addDriverAndCarEgypt() async {
final expiryDate = responseIdEgyptDriverLicense['expiry_date'];
final expiryDateTime = DateTime.tryParse(expiryDate);
Log.print('expiryDateTime: ${expiryDateTime}');
final isExpired = expiryDateTime != null && expiryDateTime.isBefore(today);
final taxExpiryDate = responseIdCardDriverEgyptBack['tax_expiry'];
Log.print('taxExpiryDate: ${taxExpiryDate}');
// Get the inspection date from the response
final inspectionDate = responseIdCardDriverEgyptBack['inspection_date'];
final year = int.parse(inspectionDate.split('-')[0]);
// Try parsing the tax expiry date. If it fails, set it to null.
final taxExpiryDateTime = DateTime.tryParse(taxExpiryDate ?? '');
Log.print('taxExpiryDateTime: ${taxExpiryDateTime}');
final isExpiredCar =
taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today);
// Check if the inspection date is before today
final inspectionDateTime = DateTime(year, 12, 31);
final isInspectionExpired = inspectionDateTime.isBefore(today);
if (isExpiredCar || isInspectionExpired) {
Get.defaultDialog(
title: 'Expired Drivers License'.tr,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
"Your drivers license and/or car tax has expired. Please renew them before proceeding."
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 16),
IconButton(
onPressed: () async {
// await Get.find<TextToSpeechController>().speakText(
// 'Your drivers license and/or car tax has expired. Please renew them before proceeding.'
// .tr,
// );
},
icon: const Icon(Icons.volume_up),
),
],
),
actions: [
TextButton(
onPressed: () {
Get.back();
},
child: const Text('OK'),
),
],
);
} else if (isExpired) {
Get.defaultDialog(
title: 'Expired Drivers License'.tr,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
"Your drivers license has expired. Please renew it before proceeding."
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 16),
IconButton(
onPressed: () async {
// await Get.find<TextToSpeechController>().speakText(
// 'Your drivers license has expired. Please renew it before proceeding.'
// .tr,
// );
},
icon: const Icon(Icons.volume_up),
),
],
),
actions: [
TextButton(
onPressed: () {
Get.back();
},
child: const Text('OK'),
),
],
);
} else if (responseIdEgyptDriverLicense['national_number']
.toString()
.substring(0, 12) !=
responseIdEgyptBack['nationalID'].toString().substring(0, 12)) {
Get.defaultDialog(
barrierDismissible: false,
title: 'ID Mismatch',
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
"The national number on your drivers license does not match the one on your ID document. Please verify and provide the correct documents."
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 16),
IconButton(
onPressed: () async {
// await Get.find<TextToSpeechController>().speakText(
// 'The national number on your drivers license does not match the one on your ID document. Please verify and provide the correct documents.',
// );
},
icon: const Icon(Icons.volume_up),
),
],
),
actions: [
TextButton(
onPressed: () {
Get.back();
},
child: const Text('OK'),
),
],
);
}
// else if (responseCriminalRecordEgypt['FullName'] !=
// responseIdEgyptDriverLicense['name_arabic']) {
// Get.defaultDialog(
// barrierDismissible: false,
// title: 'Criminal Record Mismatch',
// content: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// const Icon(Icons.warning, size: 48, color: Colors.red),
// const SizedBox(height: 16),
// Text(
// 'The full name on your criminal record does not match the one on your drivers license. Please verify and provide the correct documents.'
// .tr,
// textAlign: TextAlign.center,
// style: AppStyle.title,
// ),
// const SizedBox(height: 16),
// IconButton(
// onPressed: () async {
// await Get.find<TextToSpeechController>().speakText(
// 'The full name on your criminal record does not match the one on your drivers license. Please verify and provide the correct documents.'
// .tr,
// );
// },
// icon: const Icon(Icons.volume_up),
// ),
// ],
// ),
// actions: [
// TextButton(
// onPressed: () {
// Get.back();
// },
// child: const Text('OK'),
// ),
// ],
// );
// }
else {
await addDriverEgypt();
await addRegistrationCarEgypt();
if (isCarSaved && isDriverSaved) {
Get.snackbar('added', '',
backgroundColor:
AppColor.greenColor); // Get.offAll(() => HomeCaptain());
// Get.offAll(() => HomeCaptain());
}
}
}
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();
var payload = {
'first_name': responseIdEgyptDriverLicense['firstName']?.toString() ??
'Not specified',
'last_name': responseIdEgyptDriverLicense['lastName']?.toString() ??
'Not specified',
'email': email?.toString() ?? 'Not specified',
'phone': phone?.toString() ?? 'Not specified',
'id': driverId?.toString() ?? 'Not specified',
'password': '123456',
'gender': responseIdEgyptBack['gender']?.toString() ?? 'Not specified',
'license_type':
responseIdEgyptDriverLicense['license_type']?.toString() ??
'Not specified',
'national_number':
responseIdEgyptBack['nationalID']?.toString() ?? 'Not specified',
'name_arabic': responseIdEgyptDriverLicense['name_arabic']?.toString() ??
'Not specified',
'name_english':
responseIdEgyptDriverLicense['name_english']?.toString() ??
'Not specified',
'issue_date': responseIdEgyptDriverLicense['issue_date']?.toString() ??
'Not specified',
'expiry_date': responseIdEgyptDriverLicense['expiry_date']?.toString() ??
'Not specified',
'license_categories': responseIdEgyptDriverLicense['license_categories']
is List
? responseIdEgyptDriverLicense['license_categories'].join(', ')
: responseIdEgyptDriverLicense['license_categories']?.toString() ??
'Not specified',
'address': responseIdEgyptFront['address']?.toString() ?? 'Not specified',
'card_id': responseIdEgyptFront['card_id']?.toString() ?? 'Not specified',
'occupation':
responseIdEgyptBack['occupation']?.toString() ?? 'Not specified',
'education':
responseIdEgyptBack['occupation']?.toString() ?? 'Not specified',
'licenseIssueDate':
responseIdEgyptDriverLicense['issue_date']?.toString() ??
'Not specified',
'religion':
responseIdEgyptBack['religion']?.toString() ?? 'Not specified',
'status': 'yet',
'birthdate': extractDOB(
responseIdEgyptDriverLicense['national_number'].toString()),
'maritalStatus':
responseIdEgyptBack['maritalStatus']?.toString() ?? 'Not specified',
'site': responseIdEgyptDriverLicense['address']?.toString() ??
'Not specified',
'employmentType':
responseIdEgyptDriverLicense['employmentType']?.toString() ??
'Not specified',
};
var res = await CRUD().post(link: AppLink.signUpCaptin, payload: payload);
var status1 = jsonDecode(res);
isLoading = false;
update();
// Handle response
if (status1['status'] == 'success') {
isDriverSaved = true;
Get.snackbar('Success', 'Driver data saved successfully',
backgroundColor: AppColor.greenColor);
} else {
Get.snackbar('Error', 'Failed to save driver data',
backgroundColor: Colors.red);
}
}
Future<void> addDriverEgyptHanding() async {
isLoading = true;
update();
var payload = {
'first_name': firstName.value.isNotEmpty
? firstName.value
: responseIdEgyptDriverLicense['firstName'],
'last_name': lastName.value.isNotEmpty
? lastName.value
: responseIdEgyptDriverLicense['lastName'],
'email': email?.toString() ?? 'Not specified',
'phone': phone?.toString() ?? 'Not specified',
'id': driverId?.toString() ?? 'Not specified',
'password': '123456',
'gender': gender.value.isNotEmpty
? gender.value
: responseIdEgyptBack['gender'],
'license_type': licenseType.value.isNotEmpty
? licenseType.value
: responseIdEgyptDriverLicense['license_type'],
'national_number': nationalNumber.value.isNotEmpty
? nationalNumber.value
: responseIdEgyptBack['nationalID'],
'name_arabic': nameArabic.value.isNotEmpty
? nameArabic.value
: responseIdEgyptDriverLicense['name_arabic'],
'name_english': nameEnglish.value.isNotEmpty
? nameEnglish.value
: responseIdEgyptDriverLicense['name_english'],
'issue_date': issueDate.value.isNotEmpty
? issueDate.value
: responseIdEgyptDriverLicense['issue_date'],
'expiry_date': expiryDate.value.isNotEmpty
? expiryDate.value
: responseIdEgyptDriverLicense['expiry_date'],
'license_categories': licenseCategories.value.isNotEmpty
? licenseCategories.value
: responseIdEgyptDriverLicense['license_categories'] is List
? responseIdEgyptDriverLicense['license_categories'].join(', ')
: responseIdEgyptDriverLicense['license_categories'],
'address': address.value.isNotEmpty
? address.value
: responseIdEgyptFront['address'],
'card_id': cardId.value.isNotEmpty
? cardId.value
: responseIdEgyptFront['card_id'],
'occupation': occupation.value.isNotEmpty
? occupation.value
: responseIdEgyptBack['occupation'],
'education': education.value.isNotEmpty
? education.value
: responseIdEgyptDriverLicense['issue_date'],
'licenseIssueDate': licenseIssueDate.value.isNotEmpty
? licenseIssueDate.value
: responseIdEgyptBack['religion'],
'religion': religion.value.isNotEmpty ? religion.value : 'Not specified',
'status': status.value.isNotEmpty ? status.value : 'yet',
'birthdate': birthdate.value.isNotEmpty
? birthdate.value
: extractDOB(
responseIdEgyptDriverLicense['national_number'].toString()),
'maritalStatus': maritalStatus.value.isNotEmpty
? maritalStatus.value
: responseIdEgyptBack['maritalStatus'],
'site': site.value.isNotEmpty
? site.value
: responseIdEgyptDriverLicense['address'],
'employmentType': employmentType.value.isNotEmpty
? employmentType.value
: responseIdEgyptDriverLicense['employmentType'],
};
var res = await CRUD().post(link: AppLink.signUpCaptin, payload: payload);
var status1 = jsonDecode(res);
isLoading = false;
update();
// Handle response
if (status1['status'] == 'success') {
isDriverSaved = true;
Get.snackbar('Success', 'Driver data saved successfully',
backgroundColor: AppColor.greenColor);
} else {
Get.snackbar('Error', 'Failed to save driver data',
backgroundColor: Colors.red);
}
}
addCriminalDeocuments() async {
var res = await CRUD().post(link: AppLink.addCriminalDocuments, payload: {
"driverId": box.read(BoxName.driverID),
"IssueDate": responseCriminalRecordEgypt['IssueDate'],
"InspectionResult": responseCriminalRecordEgypt['InspectionResult'],
});
if (res != 'failure') {
Get.snackbar('uploaded sucssefuly'.tr, '');
}
}
var firstName = ''.obs;
var lastName = ''.obs;
var id = ''.obs;
var password = '123456'.obs;
var gender = ''.obs;
var licenseType = ''.obs;
var nationalNumber = ''.obs;
var nameArabic = ''.obs;
var nameEnglish = ''.obs;
var issueDate = ''.obs;
var expiryDate = ''.obs;
var licenseCategories = ''.obs;
var address = ''.obs;
var cardId = ''.obs;
var occupation = ''.obs;
var education = ''.obs;
var licenseIssueDate = ''.obs;
var religion = ''.obs;
var status = 'yet'.obs;
var birthdate = ''.obs;
var maritalStatus = ''.obs;
var site = ''.obs;
var employmentType = ''.obs;
var vin = ''.obs;
var carPlate = ''.obs;
var make = ''.obs;
var model = ''.obs;
var year = ''.obs;
var expirationDate = ''.obs;
var color = ''.obs;
var owner = ''.obs;
var colorHex = ''.obs;
var addressCar = ''.obs;
var displacement = ''.obs;
var fuel = ''.obs;
var registrationDate = ''.obs;
Future addRegistrationCarEgypt() async {
try {
final inspectionDate =
responseIdCardDriverEgyptBack['inspection_date'].toString();
final year = int.parse(inspectionDate.split('-')[0]);
final inspectionDateTime = DateTime(year, 12, 31);
isLoading = true;
update();
var res = await CRUD().post(link: AppLink.addRegisrationCar, payload: {
'driverID': 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': '$inspectionDateTime',
});
isLoading = false;
update();
var status = jsonDecode(res);
if (status['status'] == 'success') {
isCarSaved = true;
Get.snackbar('Success', 'message',
backgroundColor: AppColor.greenColor);
}
} catch (e) {}
}
Future<void> addRegistrationCarEgyptHandling() async {
try {
final inspectionDate =
responseIdCardDriverEgyptBack['inspection_date']?.toString() ?? '';
final year = inspectionDate.isNotEmpty
? int.parse(inspectionDate.split('-')[0])
: DateTime.now().year;
final inspectionDateTime = DateTime(year, 12, 31);
Log.print('inspectionDateTime: $inspectionDateTime');
isLoading = true;
update();
var payload = {
'driverID': driverId,
'vin': vin.value.isNotEmpty
? vin.value
: responseIdCardDriverEgyptBack['chassis']?.toString() ?? '',
'car_plate': carPlate.value.isNotEmpty
? carPlate.value
: responseIdCardDriverEgyptFront['car_plate']?.toString() ?? '',
'make': make.value.isNotEmpty
? make.value
: responseIdCardDriverEgyptBack['make']?.toString() ?? '',
'model': model.value.isNotEmpty
? model.value
: responseIdCardDriverEgyptBack['model']?.toString() ?? '',
'year': year.toString(),
'expiration_date': expirationDate.value.isNotEmpty
? expirationDate.value
: responseIdCardDriverEgyptFront['LicenseExpirationDate']
?.toString() ??
'',
'color': color.value.isNotEmpty
? color.value
: responseIdCardDriverEgyptFront['color']?.toString() ?? '',
'owner': owner.value.isNotEmpty
? owner.value
: responseIdCardDriverEgyptFront['owner']?.toString() ?? '',
'color_hex': getColorHex(color.value),
'address': addressCar.value.isNotEmpty
? addressCar.value
: responseIdCardDriverEgyptFront['address']?.toString() ?? '',
'displacement': displacement.value.isNotEmpty
? displacement.value
: responseIdCardDriverEgyptBack['engine']?.toString() ?? '',
'fuel': fuel.value.isNotEmpty
? fuel.value
: responseIdCardDriverEgyptBack['fuel']?.toString() ?? '',
'registration_date': inspectionDateTime.toIso8601String(),
};
Log.print('Payload: $payload');
var res =
await CRUD().post(link: AppLink.addRegisrationCar, payload: payload);
isLoading = false;
update();
var status = jsonDecode(res);
Log.print('res: $res');
Log.print('status: $status');
if (status['status'] == 'success') {
isCarSaved = true;
Get.snackbar('Success', 'Registration successful',
backgroundColor: AppColor.greenColor);
Get.back();
} else {
Log.print('Error: Unexpected status: ${status['status']}');
Get.snackbar('Error', 'Registration failed',
backgroundColor: Colors.red);
}
} catch (e) {
Log.print('Error: $e');
Get.snackbar('Error', 'An error occurred during registration',
backgroundColor: Colors.red);
}
}
String getColorHex(String colorName) {
Map<String, String> colorMap = {
'red'.tr: '#FF0000',
'green'.tr: '#008000',
'blue'.tr: '#0000FF',
'black'.tr: '#000000',
'white'.tr: '#FFFFFF',
'yellow'.tr: '#FFFF00',
'purple'.tr: '#800080',
'orange'.tr: '#FFA500',
'pink'.tr: '#FFC0CB',
'brown'.tr: '#A52A2A',
'gray'.tr: '#808080',
'cyan'.tr: '#00FFFF',
'magenta'.tr: '#FF00FF',
'lime'.tr: '#00FF00',
'indigo'.tr: '#4B0082',
'violet'.tr: '#EE82EE',
'gold'.tr: '#FFD700',
'silver'.tr: '#C0C0C0',
'teal'.tr: '#008080',
'navy'.tr: '#000080',
'Eggplant'.tr: '#800000', // Eggplant
'Dark Red'.tr: '#8B0000', // Dark Red (Maroon)
'Sky Blue'.tr: '#87CEEB', // Sky Blue
'Mocha'.tr: '#C3B091', // Mocha
};
return colorMap[colorName.toLowerCase()] ??
'#000000'; // Default to black if color name is not found
}
Future getComplaintDataToAI() async {
var res = await CRUD().get(
link: AppLink.getComplaintAllDataForDriver,
payload: {'driver_id': driverId.toString()},
);
if (res != 'failure') {
var d = jsonDecode(res)['message'];
return d;
} else {
return [
{'data': 'no data'}
];
}
}
Future<dynamic> anthropicAIForComplaint() async {
var dataComplaint = await getComplaintDataToAI();
var messagesData = [
{
"role": "user",
"content": [
{
"type": "text",
"text": "$dataComplaint ${AppInformation.complaintPrompt} "
}
]
}
];
var requestBody = jsonEncode({
"model": "claude-3-haiku-20240307",
"max_tokens": 1024,
"temperature": 0,
"system": "Json output only without any additional ",
"messages": messagesData,
});
final response = await http.post(
Uri.parse('https://api.anthropic.com/v1/messages'),
headers: {
'x-api-key': AK.anthropicAIkeySeferNew,
'anthropic-version': '2023-06-01',
'content-type': 'application/json'
},
body: requestBody,
);
if (response.statusCode == 200) {
var responseData = jsonDecode(utf8.decode(response.bodyBytes));
// Process the responseData as needed
responseForComplaint = jsonDecode(responseData['content'][0]['text']);
}
}
Future<dynamic> anthropicAI(
String payload, String prompt, String idType) async {
var messagesData = [
{
"role": "user",
"content": [
{"type": "text", "text": "$payload $prompt"}
]
}
];
var requestBody = jsonEncode({
"model": "claude-3-haiku-20240307",
"max_tokens": 1024,
"temperature": 0,
"system": "Json output only without any additional ",
"messages": messagesData,
});
final response = await http.post(
Uri.parse('https://api.anthropic.com/v1/messages'),
headers: {
'x-api-key': AK.anthropicAIkeySeferNew,
'anthropic-version': '2023-06-01',
'content-type': 'application/json'
},
body: requestBody,
);
if (response.statusCode == 200) {
var responseData = jsonDecode(utf8.decode(response.bodyBytes));
// Process the responseData as needed
if (idType == 'car_back') {
responseIdCardDriverEgyptBack =
jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'car_front') {
responseIdCardDriverEgyptFront =
jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'id_front') {
responseIdEgyptFront = jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'id_back') {
responseIdEgyptBack = jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'driver_license') {
responseIdEgyptDriverLicense =
jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'criminalRecord') {
responseCriminalRecordEgypt =
jsonDecode(responseData['content'][0]['text']);
}
update();
return responseData.toString();
}
return responseIdCardDriverEgyptBack.toString();
}
Future<void> geminiAiExtraction(String prompt, payload, String idType) async {
var requestBody = jsonEncode({
"contents": [
{
"parts": [
{"text": "$payload $prompt"}
]
}
],
"generationConfig": {
"temperature": 1,
"topK": 64,
"topP": 0.95,
"maxOutputTokens": 8192,
"stopSequences": []
},
"safetySettings": [
{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
}
]
});
final response = await http.post(
Uri.parse(''),
// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'),
// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=${AK.geminiApi}'),
// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro:generateContent?key=${AK.geminiApi}'),
headers: {'Content-Type': 'application/json'},
body: requestBody,
);
if (response.statusCode == 200) {
var responseData = jsonDecode(response.body);
// Process the responseData as needed
var result = responseData['candidates'][0]['content']['parts'][0]['text'];
RegExp regex = RegExp(r"```json([^`]*)```");
String? jsonString =
regex.firstMatch(responseData.toString())?.group(1)?.trim();
if (jsonString != null) {
// Convert the JSON object to a String
jsonString = jsonEncode(json.decode(jsonString));
if (idType == 'car_back') {
responseIdCardDriverEgyptBack = jsonDecode(jsonString);
} else if (idType == 'car_front') {
responseIdCardDriverEgyptFront = jsonDecode(jsonString);
} else if (idType == 'id_front') {
responseIdEgyptFront = jsonDecode(jsonString);
} else if (idType == 'id_back') {
responseIdEgyptBack = jsonDecode(jsonString);
} else if (idType == 'driver_license') {
responseIdEgyptDriverLicense = jsonDecode(jsonString);
}
update();
} else {
Get.snackbar('Error', "JSON string not found",
backgroundColor: AppColor.redColor);
}
// Rest of your code...
} else {}
}
}

View File

@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
ThemeData themeEnglish = ThemeData(
fontFamily: "PlayfairDisplay",
textTheme: TextTheme(
displaySmall: AppStyle.title,
displayLarge: AppStyle.title,
displayMedium: AppStyle.title,
bodyLarge: AppStyle.title,
bodyMedium: AppStyle.title),
primarySwatch: Colors.blue,
dialogTheme: DialogTheme(
backgroundColor: AppColor.secondaryColor,
contentTextStyle: AppStyle.title,
titleTextStyle: AppStyle.title,
),
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 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)),
primarySwatch: Colors.blue,
);

185
lib/env/env.dart vendored Normal file
View File

@@ -0,0 +1,185 @@
import 'package:envied/envied.dart';
part 'env.g.dart';
@Envied()
abstract class Env {
@EnviedField(varName: 'basicAuthCredentials', obfuscate: true)
static final String basicAuthCredentials = _Env.basicAuthCredentials;
@EnviedField(varName: 'visionApi', obfuscate: true)
static final String visionApi = _Env.visionApi;
@EnviedField(varName: 'smsPasswordEgypt', obfuscate: true)
static final String smsPasswordEgypt = _Env.smsPasswordEgypt;
@EnviedField(varName: 'ocpApimSubscriptionKey', obfuscate: true)
static final String ocpApimSubscriptionKey = _Env.ocpApimSubscriptionKey;
@EnviedField(varName: 'serverPHP', obfuscate: true)
static final String serverPHP = _Env.serverPHP;
@EnviedField(varName: 'anthropicAIkeySeferNew', obfuscate: true)
static final String anthropicAIkeySeferNew = _Env.anthropicAIkeySeferNew;
@EnviedField(varName: 'A', obfuscate: true)
static final String A = _Env.A;
@EnviedField(varName: 'B', obfuscate: true)
static final String B = _Env.B;
@EnviedField(varName: 'C', obfuscate: true)
static final String C = _Env.C;
@EnviedField(varName: 'D', obfuscate: true)
static final String D = _Env.D;
@EnviedField(varName: 'E', obfuscate: true)
static final String E = _Env.E;
@EnviedField(varName: 'F', obfuscate: true)
static final String F = _Env.F;
@EnviedField(varName: 'G', obfuscate: true)
static final String G = _Env.G;
@EnviedField(varName: 'H', obfuscate: true)
static final String H = _Env.H;
@EnviedField(varName: 'I', obfuscate: true)
static final String I = _Env.I;
@EnviedField(varName: 'J', obfuscate: true)
static final String J = _Env.J;
@EnviedField(varName: 'K', obfuscate: true)
static final String K = _Env.K;
@EnviedField(varName: 'L', obfuscate: true)
static final String L = _Env.L;
@EnviedField(varName: 'M', obfuscate: true)
static final String M = _Env.M;
@EnviedField(varName: 'N', obfuscate: true)
static final String N = _Env.N;
@EnviedField(varName: 'O', obfuscate: true)
static final String O = _Env.O;
@EnviedField(varName: 'P', obfuscate: true)
static final String P = _Env.P;
@EnviedField(varName: 'Q', obfuscate: true)
static final String Q = _Env.Q;
@EnviedField(varName: 'R', obfuscate: true)
static final String R = _Env.R;
@EnviedField(varName: 'S', obfuscate: true)
static final String S = _Env.S;
@EnviedField(varName: 'T', obfuscate: true)
static final String T = _Env.T;
@EnviedField(varName: 'U', obfuscate: true)
static final String U = _Env.U;
@EnviedField(varName: 'V', obfuscate: true)
static final String V = _Env.V;
@EnviedField(varName: 'W', obfuscate: true)
static final String W = _Env.W;
@EnviedField(varName: 'X', obfuscate: true)
static final String X = _Env.X;
@EnviedField(varName: 'Y', obfuscate: true)
static final String Y = _Env.Y;
@EnviedField(varName: 'Z', obfuscate: true)
static final String Z = _Env.Z;
@EnviedField(varName: 'a', obfuscate: true)
static final String a = _Env.a;
@EnviedField(varName: 'b', obfuscate: true)
static final String b = _Env.b;
@EnviedField(varName: 'c', obfuscate: true)
static final String c = _Env.c;
@EnviedField(varName: 'd', obfuscate: true)
static final String d = _Env.d;
@EnviedField(varName: 'e', obfuscate: true)
static final String e = _Env.e;
@EnviedField(varName: 'f', obfuscate: true)
static final String f = _Env.f;
@EnviedField(varName: 'g', obfuscate: true)
static final String g = _Env.g;
@EnviedField(varName: 'h', obfuscate: true)
static final String h = _Env.h;
@EnviedField(varName: 'i', obfuscate: true)
static final String i = _Env.i;
@EnviedField(varName: 'j', obfuscate: true)
static final String j = _Env.j;
@EnviedField(varName: 'k', obfuscate: true)
static final String k = _Env.k;
@EnviedField(varName: 'l', obfuscate: true)
static final String l = _Env.l;
@EnviedField(varName: 'm', obfuscate: true)
static final String m = _Env.m;
@EnviedField(varName: 'n', obfuscate: true)
static final String n = _Env.n;
@EnviedField(varName: 'o', obfuscate: true)
static final String o = _Env.o;
@EnviedField(varName: 'p', obfuscate: true)
static final String p = _Env.p;
@EnviedField(varName: 'q', obfuscate: true)
static final String q = _Env.q;
@EnviedField(varName: 'r', obfuscate: true)
static final String r = _Env.r;
@EnviedField(varName: 's', obfuscate: true)
static final String s = _Env.s;
@EnviedField(varName: 't', obfuscate: true)
static final String t = _Env.t;
@EnviedField(varName: 'u', obfuscate: true)
static final String u = _Env.u;
@EnviedField(varName: 'v', obfuscate: true)
static final String v = _Env.v;
@EnviedField(varName: 'w', obfuscate: true)
static final String w = _Env.w;
@EnviedField(varName: 'x', obfuscate: true)
static final String x = _Env.x;
@EnviedField(varName: 'y', obfuscate: true)
static final String y = _Env.y;
@EnviedField(varName: 'z', obfuscate: true)
static final String z = _Env.z;
@EnviedField(varName: 'emailService', obfuscate: true)
static final String emailService = _Env.emailService;
@EnviedField(varName: 'keyOfApp', obfuscate: true)
static final String keyOfApp = _Env.keyOfApp;
}

1276
lib/env/env.g.dart vendored Normal file

File diff suppressed because it is too large Load Diff

62
lib/firebase_options.dart Normal file
View File

@@ -0,0 +1,62 @@
// File generated by FlutterFire CLI.
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for web - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for ios - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0',
appId: '1:594687661098:android:f81fcce13962121a595f53',
messagingSenderId: '594687661098',
projectId: 'ride-b1bd8',
storageBucket: 'ride-b1bd8.appspot.com',
);
}

50
lib/login_page.dart Normal file
View File

@@ -0,0 +1,50 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/views/widgets/my_textField.dart';
import 'controller/login_controller.dart';
class LoginPage extends StatelessWidget {
final LoginController controller = Get.put(LoginController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CupertinoNavigationBar(
middle: Text('Login'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
MyTextForm(
controller: controller.email,
label: 'email',
hint: 'email',
type: TextInputType.emailAddress),
const SizedBox(height: 20),
MyTextForm(
controller: controller.password,
label: 'Password',
hint: 'Password',
type: TextInputType.name),
const SizedBox(height: 40),
CupertinoButton.filled(
child: const Text('Login'),
onPressed: () {
controller.login();
},
),
],
),
),
),
),
);
}
}

60
lib/main.dart Normal file
View File

@@ -0,0 +1,60 @@
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'controller/firebase.dart';
import 'controller/local/local_controller.dart';
import 'controller/local/translations.dart';
import 'firebase_options.dart';
import 'login_page.dart';
import 'views/home/main.dart';
final box = GetStorage();
const storage = FlutterSecureStorage();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid || Platform.isIOS) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseMessagesController().requestFirebaseMessagingPermission();
// FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
List<Future> initializationTasks = [
FirebaseMessagesController().getNotificationSettings(),
FirebaseMessagesController().getToken(),
];
// cameras = await availableCameras();
await Future.wait(initializationTasks);
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({super.key});
LocaleController localController = Get.put(LocaleController());
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Sefer Service'.tr,
debugShowCheckedModeBanner: false,
translations: MyTranslation(),
locale: localController.language,
theme: localController.appTheme,
key: UniqueKey(),
home: LoginPage(),
);
}
}

13
lib/print.dart Normal file
View File

@@ -0,0 +1,13 @@
import 'dart:developer' as developer;
class Log {
Log._();
static void print(String value, {StackTrace? stackTrace}) {
developer.log(value, name: 'LOG', stackTrace: stackTrace);
}
static Object? inspect(Object? object) {
return developer.inspect(object);
}
}

204
lib/views/home/main.dart Normal file
View File

@@ -0,0 +1,204 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/controller/mainController/main_controller.dart';
import 'package:service/controller/mainController/pages/complaint.dart';
import 'package:service/controller/mainController/pages/edit_car_plate.dart';
import 'package:service/controller/mainController/pages/passengers_cant_regster.dart';
import 'package:service/views/widgets/my_dialog.dart';
import 'package:service/views/widgets/my_textField.dart';
import '../../constant/style.dart';
import '../../controller/mainController/pages/drivers_cant_register.dart';
import '../../controller/mainController/pages/welcome_call.dart';
import '../widgets/my_scafold.dart';
class Main extends StatelessWidget {
Main({super.key});
MainController mainController = Get.put(MainController());
@override
Widget build(BuildContext context) {
return MyScaffold(title: 'Sefer Service'.tr, isleading: false, body: [
ListView(
children: [
InkWell(
onTap: () {
MyDialog().getDialog(
'insert passenger phone'.tr,
'midTitle',
Column(
children: [
Form(
key: mainController.formKey,
child: MyTextForm(
controller: mainController.passengerPhoneController,
label: 'insert passenger phone'.tr,
hint: 'insert passenger phone'.tr,
type: TextInputType.phone,
)),
],
),
() {
mainController.searchPassengerByPhone();
},
);
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'passenger details by phone'.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () {
MyDialog().getDialog(
'insert Driver phone'.tr,
'midTitle',
Column(
children: [
Form(
key: mainController.formKey,
child: MyTextForm(
controller: mainController.driverPhoneController,
label: 'insert Driver phone'.tr,
hint: 'insert Driver phone'.tr,
type: TextInputType.phone,
)),
],
),
() {
mainController.searchDriverByPhone();
},
);
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Driver details by phone'.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () async {
await mainController.getDriverNotCompleteRegistration();
Get.to(() => DriversCantRegister());
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Drivers Cant Register'.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () async {
await mainController.getPassengerNotCompleteRegistration();
Get.to(() => PassengersCantRegister());
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Passengers Cant Register'.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () async {
await mainController.getCarPlateNotEdit();
if (mainController.carPlateNotEdit.isNotEmpty) {
Get.to(() => EditCarPlate());
}
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Edit car plate'.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () async {
// await mainController.getCarPlateNotEdit();
// if (mainController.carPlateNotEdit.isNotEmpty) {
Get.to(() => Complaint());
// }
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"View complaint".tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () async {
await mainController.getNewDriverRegister();
// if (mainController.carPlateNotEdit.isNotEmpty) {
Get.to(() => const WelcomeCall());
// }
},
child: Container(
decoration: AppStyle.boxDecoration,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Welcome call".tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
),
],
)
]);
}
}

View File

@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
class MyCircleContainer extends StatelessWidget {
final Widget child;
final Color backgroundColor;
final Color borderColor;
MyCircleContainer({
Key? key,
required this.child,
this.backgroundColor = AppColor.secondaryColor,
this.borderColor = AppColor.accentColor,
}) : super(key: key);
final controller = Get.put(CircleController());
@override
Widget build(BuildContext context) {
return GetBuilder<CircleController>(
builder: ((controller) => GestureDetector(
onTap: () {
controller.changeColor();
},
child: AnimatedContainer(
onEnd: () {
controller.onEnd();
},
duration: const Duration(milliseconds: 300),
width: controller.size,
height: controller.size,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: controller.backgroundColor,
border: Border.all(
color: borderColor,
width: 1,
),
),
child: Center(child: child),
),
)));
}
}
class CircleController extends GetxController {
Color backgroundColor = AppColor.secondaryColor;
double size = 40;
void changeColor() {
backgroundColor = backgroundColor == AppColor.secondaryColor
? AppColor.accentColor
: AppColor.secondaryColor;
size = 60;
update();
}
void onEnd() {
size = 40;
update();
}
}

View File

@@ -0,0 +1,53 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vibration/vibration.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
class MyElevatedButton extends StatelessWidget {
final String title;
final VoidCallback onPressed;
final Color kolor;
final int vibrateDuration;
const MyElevatedButton({
Key? key,
required this.title,
required this.onPressed,
this.kolor = AppColor.primaryColor,
this.vibrateDuration = 100,
}) : super(key: key);
@override
Widget build(BuildContext context) {
bool vibrate = box.read(BoxName.isvibrate) ?? true;
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: kolor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
onPressed: () async {
if (vibrate == true) {
if (Platform.isIOS) {
HapticFeedback.selectionClick();
} else if (Platform.isAndroid) {
await Vibration.vibrate(duration: vibrateDuration);
} else {}
}
onPressed();
},
child: Text(
title,
textAlign: TextAlign.center,
style: AppStyle.title.copyWith(color: AppColor.secondaryColor),
),
);
}
}

View File

@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
class IconWidgetMenu extends StatelessWidget {
const IconWidgetMenu({
Key? key,
required this.onpressed,
required this.icon,
required this.title,
}) : super(key: key);
final VoidCallback onpressed;
final IconData icon;
final String title;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onpressed,
child: Padding(
padding: const EdgeInsets.only(top: 1),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
decoration: const BoxDecoration(
color: AppColor.secondaryColor,
shape: BoxShape.circle,
// boxShadow: [
// BoxShadow(
// color: AppColor.secondaryColor,
// offset: Offset(-2, -2),
// blurRadius: 0,
// spreadRadius: 0,
// blurStyle: BlurStyle.outer,
// ),
// BoxShadow(
// color: AppColor.accentColor,
// offset: Offset(3, 3),
// blurRadius: 0,
// spreadRadius: 0,
// blurStyle: BlurStyle.outer,
// ),
// ],
),
child: Center(
child: Icon(
icon,
size: 30,
color: AppColor.primaryColor,
),
),
),
Text(
title,
style: AppStyle.subtitle.copyWith(color: AppColor.secondaryColor),
)
],
),
),
);
}
}

View File

@@ -0,0 +1,40 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import 'elevated_btn.dart';
class MyDialog extends GetxController {
void getDialog(
String title, String? midTitle, Widget widget, VoidCallback onPressed) {
// final textToSpeechController = Get.put(TextToSpeechController());
Get.defaultDialog(
title: title,
titleStyle: AppStyle.title,
middleTextStyle: AppStyle.title,
content: Column(
children: [
// IconButton(
// onPressed: () async {
// // await textToSpeechController.speakText(title ?? midTitle!);
// },
// icon: const Icon(Icons.headphones)),
widget
],
),
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: onPressed,
kolor: AppColor.greenColor,
),
cancel: MyElevatedButton(
title: 'Cancel',
kolor: AppColor.redColor,
onPressed: () {
Get.back();
}));
}
}

View File

@@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
class MyScaffold extends StatelessWidget {
const MyScaffold({
super.key,
required this.title,
this.action = const Icon(
Icons.clear,
color: AppColor.secondaryColor,
),
required this.isleading,
required this.body,
});
final String title;
final List<Widget> body;
final Widget action;
final bool isleading;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.secondaryColor,
appBar: AppBar(
backgroundColor: AppColor.secondaryColor,
elevation: 0,
leading: isleading
? IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(
Icons.arrow_back_ios_new,
color: AppColor.primaryColor,
),
)
: const SizedBox(),
actions: [action],
title: Text(
title,
style: AppStyle.title.copyWith(fontSize: 30),
),
),
body: SafeArea(child: Stack(children: body)));
}
}

View File

@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
class MyTextForm extends StatelessWidget {
const MyTextForm({
super.key,
required this.controller,
required this.label,
required this.hint,
required this.type,
});
final TextEditingController controller;
final String label, hint;
final TextInputType type;
@override
Widget build(BuildContext context) {
return Padding(
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,
),
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,
hintStyle: AppStyle.title,
labelStyle: AppStyle.title,
),
validator: (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) {
if (box.read(BoxName.countryCode) == 'Egypt') {
if (value.length != 11) {
return 'Please enter a valid phone number.'.tr;
}
} else if (value.length != 11) {
//for this you will return to 10 but now for service egypt
return 'Please enter a valid phone number.'.tr;
}
}
return null;
},
),
),
);
}
}

View File

@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
class MyCircularProgressIndicator extends StatelessWidget {
final Color backgroundColor;
const MyCircularProgressIndicator({
super.key,
this.backgroundColor = Colors.transparent,
});
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 110,
height: 110,
decoration: BoxDecoration(
color: backgroundColor,
shape: BoxShape.circle,
),
child: Stack(
children: [
const Center(child: CircularProgressIndicator()),
Column(
children: [
Align(
alignment: Alignment.center,
child: Image.asset('assets/images/logo.png'),
),
],
),
],
),
),
);
}
}