Files
intaleq/siro_admin/lib/controller/admin/register_captain_controller.dart
T
Hamza-AyedandClaude Opus 5 92dc6b3641 chore: استيراد أولي من سيرو (ecfe7568) — بلا أي تعديل
نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق».
نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا
`cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules ·
.dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore.

هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً
مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ.

⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا
صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم
توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 05:10:29 +03:00

583 lines
20 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:convert';
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/info.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../main.dart';
import '../../views/widgets/snackbar.dart';
import '../functions/crud.dart';
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;
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;
Future allMethodForAI(String prompt, imagePath, driverID) async {
isLoading = true;
update();
var extractedString = await CRUD().arabicTextExtractByVisionAndAI(
imagePath: imagePath, driverID: driverID);
var json = jsonDecode(extractedString);
var textValues = extractTextFromLines(json);
// await Get.put(AI()).geminiAiExtraction(prompt, textValues, imagePath);
await Get.put(RegisterCaptainController())
.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 {
mySnackbarError(res);
}
}
final today = DateTime.now();
Future<void> addDriverAndCarEgypt() async {
final expiryDate = responseIdEgyptDriverLicense['expiry_date'];
final expiryDateTime = DateTime.tryParse(expiryDate);
final isExpired = expiryDateTime != null && expiryDateTime.isBefore(today);
final taxExpiryDate = responseIdCardDriverEgyptBack['tax_expiry'];
// 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 ?? '');
final isExpiredCar =
taxExpiryDateTime != null && taxExpiryDateTime.isBefore(today);
// Check if the inspection date is before today
final inspectionDateTime = DateTime(year, 1, 1);
final isInspectionExpired = inspectionDateTime.isBefore(today);
if (isExpiredCar || isInspectionExpired) {
Get.defaultDialog(
title: 'Expired Driver’s License'.tr,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
'Your driver’s 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 driver’s 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 Driver’s License'.tr,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(
'Your driver’s 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 driver’s 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 driver’s 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 driver’s 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 driver’s 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 driver’s 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) {
mySnackbarSuccess('added'); // Get.offAll(() => HomeCaptain());
// Get.offAll(() => HomeCaptain());
}
}
}
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': responseIdEgyptFront['dob']?.toString() ?? 'Not specified',
'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;
mySnackbarSuccess('Driver data saved successfully');
} else {
mySnackbarError('Failed to save driver data');
}
}
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') {
mySnackbarSuccess('uploaded sucssefuly'.tr);
}
}
Future addRegistrationCarEgypt() async {
try {
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':
'${responseIdCardDriverEgyptBack['inspection_date']}',
});
isLoading = false;
update();
var status = jsonDecode(res);
if (status['status'] == 'success') {
isCarSaved = true;
mySnackbarSuccess('message');
}
} catch (e) {}
}
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
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 {
mySnackbarError("JSON string not found");
}
// Rest of your code...
} else {}
}
}