This commit is contained in:
Hamza-Ayed
2024-12-22 01:36:07 +03:00
parent 90d4ca39bf
commit 2910750483
32 changed files with 1804 additions and 1231 deletions

View File

@@ -3,7 +3,7 @@ import 'dart:io';
import 'package:camera/camera.dart';
import 'package:get/get.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
// import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/constant/links.dart';
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
@@ -16,7 +16,7 @@ class CameraClassController extends GetxController {
late CameraController cameraController;
late List<CameraDescription> cameras;
bool isCameraInitialized = false;
final TextRecognizer _textRecognizer = TextRecognizer();
// final TextRecognizer _textRecognizer = TextRecognizer();
String? scannedText;
bool isloading = false;
@@ -126,45 +126,45 @@ class CameraClassController extends GetxController {
return responseString;
}
Future<void> takePictureAndMLGoogleScan() async {
try {
// Construct the path for the image file
final directory = await path_provider.getTemporaryDirectory();
final imagePath =
path.join(directory.path, '${box.read(BoxName.driverID)}.png');
// Future<void> takePictureAndMLGoogleScan() async {
// try {
// // Construct the path for the image file
// final directory = await path_provider.getTemporaryDirectory();
// final imagePath =
// path.join(directory.path, '${box.read(BoxName.driverID)}.png');
// Capture the image and save it to the specified path
final XFile capturedImage = await cameraController.takePicture();
// // Capture the image and save it to the specified path
// final XFile capturedImage = await cameraController.takePicture();
// Move the captured image to the desired path
await capturedImage.saveTo(imagePath);
// // Move the captured image to the desired path
// await capturedImage.saveTo(imagePath);
// Recognize the text in the image
final InputImage inputImage =
InputImage.fromFile(File(capturedImage.path));
final RecognizedText recognizedText =
await _textRecognizer.processImage(inputImage);
scannedText = recognizedText.text;
// // Recognize the text in the image
// final InputImage inputImage =
// InputImage.fromFile(File(capturedImage.path));
// final RecognizedText recognizedText =
// await _textRecognizer.processImage(inputImage);
// scannedText = recognizedText.text;
// Extract the scanned text line by line
final List<Map<String, dynamic>> lines = [];
for (var i = 0; i < recognizedText.blocks.length; i++) {
lines.add({
'line_number': i,
'text': recognizedText.blocks[i].text,
});
}
// // Extract the scanned text line by line
// final List<Map<String, dynamic>> lines = [];
// for (var i = 0; i < recognizedText.blocks.length; i++) {
// lines.add({
// 'line_number': i,
// 'text': recognizedText.blocks[i].text,
// });
// }
// Convert the list of lines to a JSON string
final String jsonOutput = jsonEncode(lines);
// // Convert the list of lines to a JSON string
// final String jsonOutput = jsonEncode(lines);
update();
// update();
// Print the JSON output
// // Print the JSON output
// Get.back();
} catch (e) {}
}
// // Get.back();
// } catch (e) {}
// }
String getTextAsJSON(String text) {
final lines = text.split('\n');

View File

@@ -42,6 +42,8 @@ enum DocumentType {
carLicenseFront,
carLicenseBack,
idCardFront,
nonIdCardFront,
nonIdCardBack,
idCardBack,
driverLicense,
unknown,
@@ -150,6 +152,14 @@ class AI extends GetxController {
// Check if the inspection date is before today
final inspectionDateTime = DateTime(year, 12, 31);
final isInspectionExpired = inspectionDateTime.isBefore(today);
// Add birthdate comparison for non-Egyptian ID
final frontBirthDate =
DateTime.tryParse(responseNonIdCardFront['birthdate'] ?? '');
final backBirthDate =
DateTime.tryParse(responseNonIdCardBack['birthDate'] ?? '');
final birthdatesMismatch = frontBirthDate != null &&
backBirthDate != null &&
frontBirthDate != backBirthDate;
if (isExpiredCar || isInspectionExpired) {
Get.defaultDialog(
@@ -186,6 +196,41 @@ class AI extends GetxController {
),
],
);
} else if (birthdatesMismatch && !isEgypt) {
Get.defaultDialog(
title: 'Birthdate Mismatch'.tr,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
"The birthdate on your ID front doesn't match the one on the back. Please verify your documents."
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 16),
IconButton(
onPressed: () async {
await Get.find<TextToSpeechController>().speakText(
"The birthdate on your ID front doesn't match the one on the back. Please verify your documents."
.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,
@@ -298,7 +343,7 @@ class AI extends GetxController {
// );
// }
else {
await addDriverEgypt();
isEgypt ? await addDriverEgypt() : await addDriverForeign();
await addRegistrationCarEgypt();
if (isCarSaved && isDriverSaved) {
@@ -343,6 +388,99 @@ class AI extends GetxController {
return dob;
}
Future<void> addDriverForeign() async {
isLoading = true;
update();
var payload = {
'first_name':
responseNonIdCardFront['full_name']?.toString().split(' ')[0] ??
'Not specified',
'last_name':
responseNonIdCardFront['full_name']?.toString().split(' ').last ??
'Not specified',
'email': box.read(BoxName.emailDriver)?.toString() ?? 'Not specified',
'phone': box.read(BoxName.phoneDriver)?.toString() ?? 'Not specified',
'id': box.read(BoxName.driverID)?.toString() ?? 'Not specified',
'password':
Get.put(LoginDriverController()).passwordController.text.isEmpty
? box.read(BoxName.emailDriver).toString()
: Get.find<LoginDriverController>()
.passwordController
.text
.toString(),
'gender': responseNonIdCardFront['gender']?.toString() ?? 'Not specified',
'license_type': 'Foreign',
'national_number':
responseNonIdCardFront['passport_no']?.toString() ?? 'Not specified',
'name_arabic':
responseNonIdCardFront['full_name']?.toString() ?? 'Not specified',
'name_english': 'Not specified',
'issue_date':
responseNonIdCardBack['issueDate']?.toString() ?? 'Not specified',
'expiry_date':
responseNonIdCardBack['residencyExpirationDate']?.toString() ??
'Not specified',
'license_categories': responseIdEgyptDriverLicense['license_categories']
is List
? responseIdEgyptDriverLicense['license_categories'].join(', ')
: responseIdEgyptDriverLicense['license_categories']?.toString() ??
'Not specified',
'address':
responseNonIdCardFront['address']?.toString() ?? 'Not specified',
'card_id':
responseNonIdCardFront['card_id']?.toString() ?? 'Not specified',
'occupation':
responseNonIdCardBack['workStatus']?.toString() ?? 'Not specified',
'education': 'Not specified',
'licenseIssueDate':
responseNonIdCardBack['issueDate']?.toString() ?? 'Not specified',
'religion':
responseNonIdCardFront['country']?.toString() ?? 'Not specified',
'status': 'yet',
'birthdate':
responseNonIdCardFront['birthdate']?.toString() ?? 'Not specified',
'maritalStatus': 'Not specified',
'site': responseNonIdCardFront['address']?.toString() ?? 'Not specified',
'employmentType':
responseNonIdCardBack['residencyType']?.toString() ?? 'Not specified',
};
try {
var res = await CRUD().post(link: AppLink.signUpCaptin, payload: payload);
var status1;
try {
status1 = jsonDecode(res);
} catch (e) {
throw FormatException("Invalid JSON response: $res");
}
isLoading = false;
update();
if (status1['status'] == 'success') {
isDriverSaved = true;
CRUD().post(
link: '${AppLink.seferGizaServer}/auth/captin/register.php',
payload: payload);
CRUD().post(
link: '${AppLink.seferAlexandriaServer}/auth/captin/register.php',
payload: payload);
mySnackbarSuccess('Foreign driver data saved successfully');
} else {
mySnackeBarError(
'${'Failed to save driver data'.tr}: ${status1['message']}');
}
} catch (e) {
isLoading = false;
update();
mySnackeBarError(
'An error occurred while saving driver data'.tr,
);
}
}
Future<void> addDriverEgypt() async {
isLoading = true;
update();
@@ -542,16 +680,24 @@ class AI extends GetxController {
Map<String, dynamic> responseForComplaint = {};
Map<String, dynamic> responseIdCardDriverEgyptFront = {};
Map<String, dynamic> responseIdEgyptFront = {};
Map<String, dynamic> responseNonIdCardFront = {};
Map<String, dynamic> responseNonIdCardBack = {};
Map<String, dynamic> responseCriminalRecordEgypt = {};
Map<String, dynamic> responseIdEgyptBack = {};
Map<String, dynamic> responseIdEgyptDriverLicense = {};
String? responseIdCardDriverEgypt1;
bool isloading = false;
bool isLoading = false;
bool isEgypt = true;
var image;
CroppedFile? croppedFile;
DateTime now = DateTime.now();
changeNationality() {
isEgypt = !isEgypt;
update();
}
Future<void> pickImage() async {
final pickedImage = await picker.pickImage(source: ImageSource.gallery);
@@ -607,6 +753,12 @@ class AI extends GetxController {
],
DocumentType.idCardBack: ['البطاقةساريةحتى'],
DocumentType.driverLicense: ['قيادةخاصة', 'خاصه', 'قيادة'],
DocumentType.nonIdCardFront: ['Foreign Residence Card', 'أجنبي', 'جواز'],
DocumentType.nonIdCardBack: [
'نوع الإقامة',
'الإقامة',
'Cardexpiresbyendofresidencepermit'
],
};
// Check each document type
@@ -637,7 +789,10 @@ class AI extends GetxController {
var extractedString =
await CRUD().arabicTextExtractByVisionAndAI(imagePath: imagePath);
var json = jsonDecode(extractedString);
// Log.print('extractedString: ${extractedString}');
var textValues = CRUD().extractTextFromLines(json);
Log.print('textValues: ${textValues}');
// Log.print('json: ${json}');
DocumentType detectedType = checkDocumentType(textValues);
String expectedDocument = getExpectedDocument(imagePath);
@@ -720,6 +875,10 @@ class AI extends GetxController {
return 'id_card_back'.tr;
case 'id_front':
return 'id_card_front'.tr;
case 'non_id_front':
return 'non_id_card_front'.tr;
case 'non_id_back':
return 'non_id_card_back'.tr;
case 'driver_license':
return 'driver_license'.tr;
default:
@@ -737,6 +896,10 @@ class AI extends GetxController {
return DocumentType.idCardBack;
case 'id_front':
return DocumentType.idCardFront;
case 'non_id_front':
return DocumentType.nonIdCardFront;
case 'non_id_back':
return DocumentType.nonIdCardBack;
case 'driver_license':
return DocumentType.driverLicense;
default:
@@ -754,6 +917,10 @@ class AI extends GetxController {
return 'id_card_front'.tr;
case DocumentType.idCardBack:
return 'id_card_back'.tr;
case DocumentType.nonIdCardFront:
return 'non_id_card_front'.tr;
case DocumentType.nonIdCardBack:
return 'non_id_card_back'.tr;
case DocumentType.driverLicense:
return 'driver_license'.tr;
default:
@@ -938,6 +1105,11 @@ class AI extends GetxController {
} else if (idType == 'criminalRecord') {
responseCriminalRecordEgypt =
jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'non_id_front') {
responseNonIdCardFront = jsonDecode(responseData['content'][0]['text']);
Log.print('responseNonIdCardFront: ${responseNonIdCardFront}');
} else if (idType == 'non_id_back') {
responseNonIdCardBack = jsonDecode(responseData['content'][0]['text']);
}
update();
@@ -1014,6 +1186,12 @@ class AI extends GetxController {
responseIdEgyptBack = jsonDecode(jsonString);
} else if (idType == 'driver_license') {
responseIdEgyptDriverLicense = jsonDecode(jsonString);
} else if (idType == 'non_id_front') {
responseNonIdCardFront =
jsonDecode(responseData['content'][0]['text']);
} else if (idType == 'non_id_back') {
responseNonIdCardBack =
jsonDecode(responseData['content'][0]['text']);
}
update();

View File

@@ -1,21 +1,20 @@
import 'dart:async';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/constant/links.dart';
import 'package:sefer_driver/controller/functions/crud.dart';
import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:sefer_driver/main.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
import '../home/captin/home_captain_controller.dart';
import '../home/payment/captain_wallet_controller.dart';
import 'crud.dart';
// LocationController.dart
class LocationController extends GetxController {
LocationData? _currentLocation;
late Location location;
late Location location = Location();
bool isLoading = false;
late double heading = 0;
late double accuracy = 0;
@@ -28,7 +27,7 @@ class LocationController extends GetxController {
late double speedAccuracy = 0;
late double headingAccuracy = 0;
bool isActive = false;
late LatLng myLocation;
late LatLng myLocation = LatLng(0, 0); // Default value
String totalPoints = '0';
LocationData? get currentLocation => _currentLocation;
Timer? _locationTimer;
@@ -36,13 +35,13 @@ class LocationController extends GetxController {
@override
void onInit() async {
super.onInit();
location = Location();
getLocation();
// startLocationUpdates();
location = Location(); // Initialize the location object
await getLocation(); // Fetch the location immediately
startLocationUpdates(); // Start periodic location updates
totalPoints = Get.put(CaptainWalletController()).totalPoints.toString();
// isActive = Get.put(HomeCaptainController()).isActive;
} // Function to determine which area the coordinates belong to
isActive = Get.put(HomeCaptainController()).isActive;
}
String getLocationArea(double latitude, double longitude) {
if (latitude >= 29.918901 &&
@@ -67,6 +66,10 @@ class LocationController extends GetxController {
Future<void> startLocationUpdates() async {
if (box.read(BoxName.driverID) != null) {
if (location == null) {
location = Location(); // Ensure location is initialized
}
_locationTimer =
Timer.periodic(const Duration(seconds: 5), (timer) async {
try {
@@ -77,10 +80,12 @@ class LocationController extends GetxController {
if (isActive) {
if (double.parse(totalPoints) > -300) {
await getLocation();
if (myLocation == null) {
return;
}
print(
'Latitude: ${myLocation.latitude}, Longitude: ${myLocation.longitude}');
// Determine the area
String area =
getLocationArea(myLocation.latitude, myLocation.longitude);
print('Determined Area: $area');
@@ -89,56 +94,25 @@ class LocationController extends GetxController {
switch (area) {
case 'Cairo':
print('Area matched: Cairo');
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
endpoint = AppLink.addCarsLocationCairoEndpoint;
break;
case 'Giza':
print('Area matched: Giza');
box.write(BoxName.serverChosen, AppLink.seferGizaServer);
endpoint = AppLink.addCarsLocationGizaEndpoint;
break;
case 'Alexandria':
print('Area matched: Alexandria');
box.write(
BoxName.serverChosen, AppLink.seferAlexandriaServer);
endpoint = AppLink.addCarsLocationAlexandriaEndpoint;
break;
default:
print('Unknown location area. Fallback to Cairo');
endpoint = AppLink.addCarsLocationCairoEndpoint;
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
}
Log.print('Final Endpoint: $endpoint');
switch (area) {
case 'Cairo':
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
endpoint = AppLink.addCarsLocationCairoEndpoint;
Log.print('Endpoint: $endpoint');
break;
case 'Giza':
box.write(BoxName.serverChosen, AppLink.seferGizaServer);
endpoint = AppLink.addCarsLocationGizaEndpoint;
Log.print('Endpoint: $endpoint');
break;
case 'Alexandria':
box.write(
BoxName.serverChosen, AppLink.seferAlexandriaServer);
endpoint = AppLink.addCarsLocationAlexandriaEndpoint;
Log.print('Endpoint: $endpoint');
break;
default:
// Handle any other unexpected cases
print('Unknown location area');
endpoint = AppLink
.addCarsLocationCairoEndpoint; // Fallback to Cairo endpoint
Log.print('Fallback Endpoint: $endpoint');
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
return;
}
// Ensure driver ID exists before making the API call
if (box.read(BoxName.driverID) != null) {
await CRUD().post(link: endpoint, payload: {
'driver_id': box.read(BoxName.driverID).toString(),
@@ -154,7 +128,6 @@ class LocationController extends GetxController {
'status': box.read(BoxName.statusDriverLocation).toString(),
});
// Update the camera position on the map
Get.find<HomeCaptainController>()
.mapHomeCaptainController
?.animateCamera(
@@ -169,7 +142,6 @@ class LocationController extends GetxController {
}
}
} catch (e) {
// Handle the error gracefully
Log.print('Error during location update: $e');
}
});
@@ -181,75 +153,58 @@ class LocationController extends GetxController {
}
Future<void> getLocation() async {
// isLoading = true;
// update();
if (location == null) {
location = Location(); // Ensure location is initialized
}
bool serviceEnabled;
PermissionStatus permissionGranted;
// Check if location services are enabled
serviceEnabled = await location.serviceEnabled();
if (!serviceEnabled) {
serviceEnabled = await location.requestService();
if (!serviceEnabled) {
// Location services are still not enabled, handle the error
return;
}
}
// Check if the app has permission to access location
permissionGranted = await location.hasPermission();
if (permissionGranted == PermissionStatus.denied) {
permissionGranted = await location.requestPermission();
if (permissionGranted != PermissionStatus.granted) {
// Location permission is still not granted, handle the error
return;
}
}
// Configure location accuracy
// LocationAccuracy desiredAccuracy = LocationAccuracy.high;
// Get the current location
LocationData _locationData = await location.getLocation();
myLocation =
(_locationData.latitude != null && _locationData.longitude != null
? LatLng(_locationData.latitude!, _locationData.longitude!)
: null)!;
getLocationArea(_locationData.latitude!, _locationData.longitude!);
speed = _locationData.speed!;
heading = _locationData.heading!;
// Calculate the distance between the current location and the previous location
if (_locationData.latitude != null && _locationData.longitude != null) {
myLocation = LatLng(_locationData.latitude!, _locationData.longitude!);
} else {
myLocation = LatLng(0, 0); // Default value
}
speed = _locationData.speed ?? 0;
heading = _locationData.heading ?? 0;
if (Get.find<HomeCaptainController>().rideId == 'rideId') {
Log.print(
'Get.find<HomeCaptainController>().rideId: ${Get.find<HomeCaptainController>().rideId}');
if (previousTime > 0) {
double distance = calculateDistanceInKmPerHour(
previousTime, _locationData.time, speed);
totalDistance += distance;
}
previousTime = _locationData.time!;
previousTime = _locationData.time ?? 0;
}
// Print location details
// isLoading = false;
update();
}
double calculateDistanceInKmPerHour(
double? startTime, double? endTime, double speedInMetersPerSecond) {
// Calculate the time difference in hours
double timeDifferenceInHours = (endTime! - startTime!) / 1000 / 3600;
// Convert speed to kilometers per hour
double timeDifferenceInHours =
(endTime ?? 0 - startTime! ?? 0) / 1000 / 3600;
double speedInKmPerHour = speedInMetersPerSecond * 3.6;
// Calculate the distance in kilometers
double distanceInKilometers = speedInKmPerHour * timeDifferenceInHours;
// Convert distance from kilometers to meters
double distanceInMeters = distanceInKilometers * 1000;
// If the calculated distance is less than 6 meters, return 0 to avoid fake distance
return distanceInMeters < 5 ? 0 : distanceInKilometers;
}
}