diff --git a/backend/Admin/Staff/add.php b/backend/Admin/Staff/add.php
index e0f1083..49742fb 100644
--- a/backend/Admin/Staff/add.php
+++ b/backend/Admin/Staff/add.php
@@ -32,6 +32,7 @@ $fingerprint = filterRequest("fingerprint") ?: '';
$gender = filterRequest("gender") ?? 'Male';
$birthdate = filterRequest("birthdate") ?? date('Y-m-d');
$site = filterRequest("site") ?? 'main';
+$country = filterRequest("country") ?? 'Jordan';
if (empty($name) || empty($password) || empty($role)) {
jsonError("Missing required fields (name, password, role).");
@@ -70,8 +71,8 @@ try {
} else {
// الإضافة لجدول المستخدمين (خدمة العملاء)
// أضفنا site و last_name (كقيمة افتراضية فارغة إذا لم تتوفر)
- $sql = "INSERT INTO users (id, fingerprint, fingerprint_hash, phone, email, gender, password, birthdate, user_type, first_name, last_name, site, created_at)
- VALUES (:id, :fp, :fp_hash, :phone, :email, :gender, :pass, :bdate, 'service', :fname, :lname, :site, NOW())";
+ $sql = "INSERT INTO users (id, fingerprint, fingerprint_hash, phone, email, gender, password, birthdate, user_type, first_name, last_name, site, country, created_at)
+ VALUES (:id, :fp, :fp_hash, :phone, :email, :gender, :pass, :bdate, 'service', :fname, :lname, :site, :country, NOW())";
$stmt = $con->prepare($sql);
$stmt->execute([
':id' => $uniqueId,
@@ -84,7 +85,8 @@ try {
':bdate' => $birthdate,
':fname' => $encName,
':lname' => '', // last_name is empty for now
- ':site' => $site
+ ':site' => $site,
+ ':country' => $country
]);
}
diff --git a/backend/Admin/Staff/add_super_admin.php b/backend/Admin/Staff/add_super_admin.php
new file mode 100644
index 0000000..96f659d
--- /dev/null
+++ b/backend/Admin/Staff/add_super_admin.php
@@ -0,0 +1,63 @@
+ 'Access denied. Admin key required.']));
+// }
+
+$con = Database::get('main');
+
+$name = filterRequest('name') ?: 'Super Admin';
+$email = filterRequest('email') ?: '';
+$phone = filterRequest('phone') ?: '';
+$fingerprint = filterRequest('fingerprint') ?: '';
+$password = filterRequest('password') ?: bin2hex(random_bytes(8));
+
+try {
+ $hashedPass = password_hash($password, PASSWORD_DEFAULT);
+ $encName = $encryptionHelper->encryptData($name);
+ $encPhone = $phone ? $encryptionHelper->encryptData($phone) : '';
+ $encEmail = $email ? $encryptionHelper->encryptData($email) : '';
+ $encFp = $fingerprint ? $encryptionHelper->encryptData($fingerprint) : '';
+ $fpHash = $fingerprint ? hash('sha256', $fingerprint) : '';
+ $uniqueId = bin2hex(random_bytes(16));
+
+ $check = $con->prepare("SELECT id FROM adminUser WHERE role = 'super_admin' LIMIT 1");
+ $check->execute();
+ if ($check->fetch()) {
+ echo "
⚠️ Super Admin already exists.
";
+ exit;
+ }
+
+ $sql = "INSERT INTO adminUser (id, fingerprint, fingerprint_hash, name, phone, email, password, role, created_at)
+ VALUES (:id, :fp, :fp_hash, :name, :phone, :email, :pass, 'super_admin', NOW())";
+ $stmt = $con->prepare($sql);
+ $stmt->execute([
+ ':id' => $uniqueId,
+ ':fp' => $encFp,
+ ':fp_hash' => $fpHash,
+ ':name' => $encName,
+ ':phone' => $encPhone,
+ ':email' => $encEmail,
+ ':pass' => $hashedPass,
+ ]);
+
+ if ($stmt->rowCount() > 0) {
+ echo "✅ Super Admin created successfully!
";
+ echo "ID: $uniqueId
";
+ echo "Name: $name
";
+ echo "Password: $password
";
+ echo "⚠️ Save this password. Delete this file after use.
";
+ } else {
+ echo "❌ Failed to create Super Admin.
";
+ }
+} catch (Exception $e) {
+ echo "❌ Error: " . htmlspecialchars($e->getMessage()) . "
";
+}
diff --git a/backend/serviceapp/getDriverDetailsForActivate.php b/backend/serviceapp/getDriverDetailsForActivate.php
index 2ce4aa9..c714199 100644
--- a/backend/serviceapp/getDriverDetailsForActivate.php
+++ b/backend/serviceapp/getDriverDetailsForActivate.php
@@ -5,7 +5,7 @@ $driverId = filterRequest("driverId");
$sql = "SELECT d.*, cr.*
FROM `driver` d
- JOIN `CarRegistration` cr ON cr.driverID = d.id
+ LEFT JOIN `CarRegistration` cr ON cr.driverID = d.id
WHERE d.id = :driverId ";
$stmt = $con->prepare($sql);
diff --git a/backend/serviceapp/getDriverNotCompleteRegistration.php b/backend/serviceapp/getDriverNotCompleteRegistration.php
index d458def..a33edbd 100644
--- a/backend/serviceapp/getDriverNotCompleteRegistration.php
+++ b/backend/serviceapp/getDriverNotCompleteRegistration.php
@@ -7,14 +7,14 @@ $sql = "SELECT
notesForDriverService.note
FROM
phone_verification
-INNER JOIN -- نستخدم INNER JOIN لضمان جلب من لديهم ملاحظات فقط
+INNER JOIN
`notesForDriverService`
ON
`notesForDriverService`.`phone` = `phone_verification`.`phone_number`
WHERE
`notesForDriverService`.`note` != 'delete'
ORDER BY
- `phone_verification`.`created_at` DESC -- الترتيب حسب تاريخ التحقق لأنه العمود الموجود
+ `phone_verification`.`created_at` DESC
LIMIT 400;
";
@@ -24,7 +24,6 @@ $stmt->execute();
if ($stmt->rowCount() > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
- // فك تشفير أرقام الهواتف فقط للإخراج
foreach ($rows as &$row) {
if (!empty($row['phone'])) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
@@ -42,4 +41,3 @@ if ($stmt->rowCount() > 0) {
} else {
jsonError("No Phone verified yet found");
}
-?>
\ No newline at end of file
diff --git a/backend/serviceapp/login.php b/backend/serviceapp/login.php
index f424a39..7a60dea 100644
--- a/backend/serviceapp/login.php
+++ b/backend/serviceapp/login.php
@@ -105,10 +105,6 @@ try {
$expires_in = $ttl;
}
- // توليد مفتاح HMAC فريد للمستخدم (للتوافق مع CRUD الجديد)
- $hmacKey = hash_hmac('sha256', (string)$user['id'], getenv('SECRET_KEY_HMAC'));
-
- // ✅ FIX H-05: لا نعيد مفتاح HMAC أبداً (يُحسب على العميل بنفس المعادلة)
printSuccess([
"message" => "Login successful",
"data" => $user,
diff --git a/siro_admin/lib/controller/admin/staff_controller.dart b/siro_admin/lib/controller/admin/staff_controller.dart
index ad09666..2f78444 100644
--- a/siro_admin/lib/controller/admin/staff_controller.dart
+++ b/siro_admin/lib/controller/admin/staff_controller.dart
@@ -18,6 +18,7 @@ class StaffController extends GetxController {
String selectedGender = 'Male';
String selectedRole = 'service'; // 'admin' or 'service'
+ String selectedCountry = 'Jordan';
bool isLoading = false;
@@ -43,6 +44,7 @@ class StaffController extends GetxController {
"birthdate": birthdateController.text.trim(),
"fingerprint": fingerprint,
"site": "main", // القيمة الافتراضية للفرع
+ "country": selectedCountry,
},
);
diff --git a/siro_admin/lib/views/admin/staff/add_staff_page.dart b/siro_admin/lib/views/admin/staff/add_staff_page.dart
index 057bf89..a167ad3 100644
--- a/siro_admin/lib/views/admin/staff/add_staff_page.dart
+++ b/siro_admin/lib/views/admin/staff/add_staff_page.dart
@@ -87,6 +87,14 @@ class AddStaffPage extends StatelessWidget {
),
],
),
+ const SizedBox(height: 16),
+ _buildDropdown(
+ label: "البلد",
+ value: controller.selectedCountry,
+ items: const ['Jordan', 'Syria', 'Egypt'],
+ onChanged: (val) => controller.selectedCountry = val!,
+ fillColor: inputColor,
+ ),
const SizedBox(height: 40),
GetBuilder(
builder: (controller) => SizedBox(
diff --git a/siro_admin/macos/Podfile.lock b/siro_admin/macos/Podfile.lock
index d88ecd3..ba42875 100644
--- a/siro_admin/macos/Podfile.lock
+++ b/siro_admin/macos/Podfile.lock
@@ -105,6 +105,8 @@ PODS:
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
+ - package_info_plus (0.0.1):
+ - FlutterMacOS
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
@@ -127,6 +129,7 @@ DEPENDENCIES:
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`)
+ - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
@@ -167,6 +170,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral
local_auth_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin
+ package_info_plus:
+ :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
sqflite_darwin:
@@ -191,11 +196,12 @@ SPEC CHECKSUMS:
FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7
flutter_image_compress_macos: e68daf54bb4bf2144c580fd4d151c949cbf492f0
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
- FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
+ FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
+ package_info_plus: 122abb51244f66eead59ce7c9c200d6b53111779
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
diff --git a/siro_service/lib/controller/login_controller.dart b/siro_service/lib/controller/login_controller.dart
index a6b2a89..6b53d69 100644
--- a/siro_service/lib/controller/login_controller.dart
+++ b/siro_service/lib/controller/login_controller.dart
@@ -140,6 +140,9 @@ class LoginController extends GetxController {
await storage.write(key: 'password', value: pass);
await box.write(BoxName.employeename, userData['first_name']);
await box.write(BoxName.password, pass);
+ if (userData['country'] != null) {
+ await box.write(BoxName.countryCode, userData['country']);
+ }
Get.offAll(() => Main());
} else {
diff --git a/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart b/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart
index 65cb87b..7dbf62b 100644
--- a/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart
+++ b/siro_service/lib/controller/mainController/pages/drivers_cant_register.dart
@@ -144,21 +144,22 @@ class DriversCantRegister extends StatelessWidget {
},
),
- // Edit button → go to registration form
- buildActionButton(
- icon: CupertinoIcons
- .pencil_ellipsis_rectangle,
- color: AppColor.gold,
- onPressed: () {
- Get.to(
- () => const ReviewDriverPage(),
- arguments: {
- "phone": driver['phone_number'],
- "driverId": driver['driverId'],
- },
- );
- },
- ),
+ // Edit button → go to review page (only if driverId exists)
+ if (driver['driverId'] != null)
+ buildActionButton(
+ icon: CupertinoIcons
+ .pencil_ellipsis_rectangle,
+ color: AppColor.gold,
+ onPressed: () {
+ Get.to(
+ () => const ReviewDriverPage(),
+ arguments: {
+ "phone": driver['phone_number'],
+ "driverId": driver['driverId'],
+ },
+ );
+ },
+ ),
buildActionButton(
icon: CupertinoIcons
.pencil_ellipsis_rectangle,
diff --git a/siro_service/lib/controller/mainController/review_driver_controller.dart b/siro_service/lib/controller/mainController/review_driver_controller.dart
index b6af42a..49e3e82 100644
--- a/siro_service/lib/controller/mainController/review_driver_controller.dart
+++ b/siro_service/lib/controller/mainController/review_driver_controller.dart
@@ -48,7 +48,7 @@ class ReviewDriverController extends GetxController {
'profile_picture': Icons.person,
};
- String get country => box.read('countryCode')?.toString() ?? 'Syria';
+ String get country => box.read('countryCode')?.toString() ?? 'Jordan';
static const Map>> fieldConfig = {
'id_front': [