Update: 2026-06-27 04:21:17
This commit is contained in:
@@ -583,13 +583,14 @@ $pwdHashed = password_hash($rawSecret, PASSWORD_DEFAULT);
|
|||||||
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
|
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
|
||||||
$con->rollBack();
|
$con->rollBack();
|
||||||
}
|
}
|
||||||
error_log("register_driver_and_car ERROR: " . $e->getMessage());
|
$msg = $e->getMessage();
|
||||||
jsonError("Server error");
|
error_log("register_driver_and_car ERROR: " . $msg);
|
||||||
|
jsonError("Server error: $msg", 400);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
|
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
|
||||||
$con->rollBack();
|
$con->rollBack();
|
||||||
}
|
}
|
||||||
error_log("register_driver_and_car PDO: " . $e->getMessage());
|
error_log("register_driver_and_car PDO: " . $e->getMessage());
|
||||||
jsonError("Database error.");
|
jsonError("Database error: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -43,7 +43,13 @@ class KazanController extends GetxController {
|
|||||||
if (decoded['status'] == "success") {
|
if (decoded['status'] == "success") {
|
||||||
var message = decoded['message'];
|
var message = decoded['message'];
|
||||||
if (message is List && message.isNotEmpty) {
|
if (message is List && message.isNotEmpty) {
|
||||||
kazanData.value = Map<String, dynamic>.from(message[0]);
|
final match = message.cast<Map<String, dynamic>>().firstWhere(
|
||||||
|
(row) =>
|
||||||
|
(row['country'] ?? '').toString().toLowerCase() ==
|
||||||
|
countryParam.toLowerCase(),
|
||||||
|
orElse: () => message[0] as Map<String, dynamic>,
|
||||||
|
);
|
||||||
|
kazanData.value = Map<String, dynamic>.from(match);
|
||||||
kazanData['country'] = selectedCountry.value;
|
kazanData['country'] = selectedCountry.value;
|
||||||
} else {
|
} else {
|
||||||
kazanData.value = {'country': selectedCountry.value};
|
kazanData.value = {'country': selectedCountry.value};
|
||||||
|
|||||||
@@ -102,6 +102,13 @@ class LoginDriverController extends GetxController {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
isPhoneVerified() async {
|
isPhoneVerified() async {
|
||||||
|
// If the phone is already verified locally and we have a driver ID, skip the API check
|
||||||
|
// This prevents asking for OTP again if the user restarts the app during registration.
|
||||||
|
if (box.read(BoxName.phoneVerified) == '1' && box.read(BoxName.driverID) != null) {
|
||||||
|
Get.offAll(() => RegistrationView());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var res = await CRUD().post(
|
var res = await CRUD().post(
|
||||||
link: AppLink.isPhoneVerified,
|
link: AppLink.isPhoneVerified,
|
||||||
payload: {'phone_number': box.read(BoxName.phoneDriver)});
|
payload: {'phone_number': box.read(BoxName.phoneDriver)});
|
||||||
|
|||||||
@@ -371,9 +371,15 @@ class RegistrationController extends GetxController {
|
|||||||
|
|
||||||
final _jwt = box.read(BoxName.jwt);
|
final _jwt = box.read(BoxName.jwt);
|
||||||
final String _token = _jwt != null ? r(_jwt).split(AppInformation.addd)[0] : '';
|
final String _token = _jwt != null ? r(_jwt).split(AppInformation.addd)[0] : '';
|
||||||
|
|
||||||
|
String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
String nonce = timestamp;
|
||||||
|
|
||||||
final headers = <String, String>{
|
final headers = <String, String>{
|
||||||
'Authorization': 'Bearer $_token',
|
'Authorization': 'Bearer $_token',
|
||||||
'X-HMAC-Auth': '${box.read(BoxName.hmac)}',
|
'X-Device-FP': box.read(BoxName.deviceFingerprint)?.toString() ?? '',
|
||||||
|
'X-Timestamp': timestamp,
|
||||||
|
'X-Nonce': nonce,
|
||||||
};
|
};
|
||||||
request.headers.addAll(headers);
|
request.headers.addAll(headers);
|
||||||
|
|
||||||
@@ -472,7 +478,7 @@ class RegistrationController extends GetxController {
|
|||||||
final req = http.MultipartRequest('POST', syrianUploadUri);
|
final req = http.MultipartRequest('POST', syrianUploadUri);
|
||||||
req.headers.addAll({
|
req.headers.addAll({
|
||||||
'Authorization': authHeader,
|
'Authorization': authHeader,
|
||||||
'X-HMAC-Auth': hmacHeader,
|
'X-Device-FP': box.read(BoxName.deviceFingerprint)?.toString() ?? '',
|
||||||
});
|
});
|
||||||
|
|
||||||
req.fields['driver_id'] = driverId;
|
req.fields['driver_id'] = driverId;
|
||||||
@@ -603,11 +609,14 @@ class RegistrationController extends GetxController {
|
|||||||
_addField(fields, 'expiry_date', driverLicenseExpiryController.text);
|
_addField(fields, 'expiry_date', driverLicenseExpiryController.text);
|
||||||
_addField(fields, 'password', 'generated_password_or_token');
|
_addField(fields, 'password', 'generated_password_or_token');
|
||||||
_addField(fields, 'status', 'yet');
|
_addField(fields, 'status', 'yet');
|
||||||
_addField(fields, 'email', 'Not specified');
|
|
||||||
|
String generatedEmail = 'driver_${box.read(BoxName.driverID) ?? DateTime.now().millisecondsSinceEpoch}@siromove.com';
|
||||||
|
_addField(fields, 'email', generatedEmail);
|
||||||
_addField(fields, 'gender', 'Male'); // يفضل ربطها بـ Dropdown أيضاً
|
_addField(fields, 'gender', 'Male'); // يفضل ربطها بـ Dropdown أيضاً
|
||||||
|
_addField(fields, 'country', box.read(BoxName.countryCode)?.toString() ?? 'Jordan');
|
||||||
|
|
||||||
// --- Car Data ---
|
// --- Car Data ---
|
||||||
_addField(fields, 'vin', 'yet');
|
_addField(fields, 'vin', carVinController.text.isNotEmpty ? carVinController.text : 'yet');
|
||||||
_addField(fields, 'car_plate', carPlateController.text);
|
_addField(fields, 'car_plate', carPlateController.text);
|
||||||
_addField(fields, 'make', carMakeController.text);
|
_addField(fields, 'make', carMakeController.text);
|
||||||
_addField(fields, 'model', carModelController.text);
|
_addField(fields, 'model', carModelController.text);
|
||||||
@@ -615,8 +624,9 @@ class RegistrationController extends GetxController {
|
|||||||
_addField(
|
_addField(
|
||||||
fields,
|
fields,
|
||||||
'expiration_date',
|
'expiration_date',
|
||||||
driverLicenseExpiryController
|
carRegistrationExpiryController.text.isNotEmpty
|
||||||
.text); // تأكد من أن هذا تاريخ انتهاء السيارة وليس الرخصة
|
? carRegistrationExpiryController.text
|
||||||
|
: driverLicenseExpiryController.text);
|
||||||
_addField(
|
_addField(
|
||||||
fields,
|
fields,
|
||||||
'color',
|
'color',
|
||||||
@@ -668,8 +678,8 @@ class RegistrationController extends GetxController {
|
|||||||
_addField(fields, 'id_front', idFrontUrl);
|
_addField(fields, 'id_front', idFrontUrl);
|
||||||
_addField(fields, 'id_back', idBackUrl);
|
_addField(fields, 'id_back', idBackUrl);
|
||||||
_addField(fields, 'driver_license', driverLicenseUrl);
|
_addField(fields, 'driver_license', driverLicenseUrl);
|
||||||
if (isSyria)
|
// Always add the key to avoid PHP undefined index error
|
||||||
_addField(fields, 'driver_license_back', driverLicenseBackUrl);
|
fields['driver_license_back'] = driverLicenseBackUrl ?? '';
|
||||||
_addField(fields, 'profile_picture', profilePicUrl);
|
_addField(fields, 'profile_picture', profilePicUrl);
|
||||||
_addField(fields, 'criminal_record', criminalRecordUrl);
|
_addField(fields, 'criminal_record', criminalRecordUrl);
|
||||||
_addField(fields, 'car_license_front', carFrontUrl);
|
_addField(fields, 'car_license_front', carFrontUrl);
|
||||||
@@ -677,6 +687,12 @@ class RegistrationController extends GetxController {
|
|||||||
|
|
||||||
req.fields.addAll(fields);
|
req.fields.addAll(fields);
|
||||||
|
|
||||||
|
Log.print('--- 🚀 Registration Request Payload ---');
|
||||||
|
req.fields.forEach((key, value) {
|
||||||
|
Log.print('[$key]: $value');
|
||||||
|
});
|
||||||
|
Log.print('---------------------------------------');
|
||||||
|
|
||||||
// 3) الإرسال
|
// 3) الإرسال
|
||||||
final streamed =
|
final streamed =
|
||||||
await client.send(req).timeout(const Duration(seconds: 60));
|
await client.send(req).timeout(const Duration(seconds: 60));
|
||||||
|
|||||||
@@ -400,7 +400,8 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
if (savedTrip != null && savedTrip.isNotEmpty) {
|
if (savedTrip != null && savedTrip.isNotEmpty) {
|
||||||
if (Get.currentRoute == '/') {
|
if (Get.currentRoute == '/') {
|
||||||
print('⏳ App is still on Splash screen. Postponing notification trip navigation to HomeCaptainController.');
|
print(
|
||||||
|
'⏳ App is still on Splash screen. Postponing notification trip navigation to HomeCaptainController.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await storage.delete(key: 'pending_driver_list');
|
await storage.delete(key: 'pending_driver_list');
|
||||||
@@ -425,7 +426,8 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
// ==============================================================================
|
// ==============================================================================
|
||||||
Future<void> _processAcceptOrder(List<dynamic> data) async {
|
Future<void> _processAcceptOrder(List<dynamic> data) async {
|
||||||
if (_isProcessingAccept) {
|
if (_isProcessingAccept) {
|
||||||
print("⏳ _processAcceptOrder: Already accepting order, skipping duplicate request.");
|
print(
|
||||||
|
"⏳ _processAcceptOrder: Already accepting order, skipping duplicate request.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_isProcessingAccept = true;
|
_isProcessingAccept = true;
|
||||||
|
|||||||
@@ -450,8 +450,48 @@ class RegistrationView extends StatelessWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: (img != null && img.isNotEmpty)
|
child: Stack(
|
||||||
? Image.network(
|
children: [
|
||||||
|
// Card template background
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[100],
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.grey[300]!,
|
||||||
|
width: 1.5,
|
||||||
|
strokeAlign: BorderSide.strokeAlignInside,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.credit_card, size: 48, color: Colors.grey[300]),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey[400],
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Uploaded image with 50% opacity
|
||||||
|
if (img != null && img.isNotEmpty)
|
||||||
|
Positioned.fill(
|
||||||
|
child: Opacity(
|
||||||
|
opacity: 0.5,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
child: Image.network(
|
||||||
img,
|
img,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
@@ -467,17 +507,24 @@ class RegistrationView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
: Column(
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Empty state with camera icon
|
||||||
|
if (img == null || img.isEmpty)
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.camera_alt_outlined,
|
Icon(Icons.camera_alt_outlined,
|
||||||
size: 40, color: Colors.grey[600]),
|
size: 40, color: Colors.grey[600]),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(title, style: TextStyle(color: Colors.grey[700])),
|
|
||||||
Text('Tap to upload'.tr,
|
Text('Tap to upload'.tr,
|
||||||
style:
|
style: const TextStyle(color: Colors.grey, fontSize: 12)),
|
||||||
const TextStyle(color: Colors.grey, fontSize: 12)),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user