add country-specific field config to review page, add warning snackbar, write AI extraction prompt

This commit is contained in:
Hamza-Ayed
2026-06-25 17:40:09 +03:00
parent 28b8558b6d
commit 1e24c3d0c8
4 changed files with 835 additions and 312 deletions

View File

@@ -91,6 +91,32 @@ class ReviewDriverPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Country indicator badge
Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: AppColor.primaryLight,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.public, size: 16, color: AppColor.primaryColor),
const SizedBox(width: 6),
Text(
c.country.value.isNotEmpty
? 'Country: ${c.country.value}'
: 'Detecting country...',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppColor.primaryColor,
),
),
],
),
),
_buildDocumentImage(c.docUrls[key]!.value),
const SizedBox(height: 16),
_buildFormFieldsForTab(c, key),
@@ -160,25 +186,195 @@ class ReviewDriverPage extends StatelessWidget {
}
Widget _buildFormFieldsForTab(ReviewDriverController c, String tabKey) {
switch (tabKey) {
case 'id_front':
return _buildIdFrontFields(c);
case 'id_back':
return _buildIdBackFields(c);
case 'driver_license':
return _buildDriverLicenseFields(c);
case 'driver_license_back':
return _buildLicenseBackFields(c);
case 'car_license_front':
return _buildCarFrontFields(c);
case 'car_license_back':
return _buildCarBackFields(c);
case 'criminal_record':
return _buildCriminalRecordFields();
case 'profile_picture':
return _buildProfilePhotoFields(c);
final fields = c.getFieldsForTab(tabKey);
// Special layouts for specific tabs
if (tabKey == 'criminal_record') {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${c.country.value} - Criminal Record',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const Divider(),
Card(
color: Colors.green[50],
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(Icons.check_circle, color: Colors.green[700], size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
_getCriminalRecordHint(c.country.value),
style: TextStyle(color: Colors.green[800]),
),
),
],
),
),
),
...fields.map((f) => _buildFieldFromConfig(c, f)),
],
);
}
if (tabKey == 'profile_picture') {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Profile Photo',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const Divider(),
Card(
color: Colors.blue[50],
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(Icons.face, color: Colors.blue[700], size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
'Verify the profile photo matches the person in the ID '
'and Driver License photos above.',
style: TextStyle(color: Colors.blue[800]),
),
),
],
),
),
),
const SizedBox(height: 12),
...fields.map((f) => _buildFieldFromConfig(c, f)),
],
);
}
// Dynamic fields for all other tabs
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${c.country.value} - ${c.tabLabels[tabKey] ?? tabKey}',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const Divider(),
...fields.map((f) => _buildFieldFromConfig(c, f)),
],
);
}
String _getCriminalRecordHint(String country) {
switch (country) {
case 'Syria':
return 'Review the "لا حكم عليه" document. Verify name matches driver.';
case 'Jordan':
return 'Review the "عدم محكومية" document. Verify name matches driver.';
case 'Egypt':
return 'Review the "فيش وتشبيه" document. Verify name matches driver.';
default:
return const SizedBox();
return 'Review the criminal record document. Verify name matches driver.';
}
}
Widget _buildFieldFromConfig(ReviewDriverController c, List<dynamic> fieldDef) {
if (fieldDef.length < 6) return const SizedBox();
final key = fieldDef[0] as String;
final label = fieldDef[1] as String;
final isDate = fieldDef[2] as bool;
final isGender = fieldDef[3] as bool;
final isColor = fieldDef[4] as bool;
final isFuel = fieldDef[5] as bool;
if (isGender) return _buildGenderDropdown(c, label);
if (isColor) return _buildColorDropdown(c, label);
if (isFuel) return _buildFuelDropdown(c, label);
final controller = _getController(c, key);
if (controller == null) return const SizedBox();
if (isDate) {
return _buildTextField(
label: label,
controller: controller,
icon: Icons.event,
onTap: () => c.selectDate(Get.context!, controller),
);
}
// Determine icon based on common field names
final icon = _getFieldIcon(key, label);
return _buildTextField(
label: label,
controller: controller,
icon: icon,
);
}
IconData? _getFieldIcon(String key, String label) {
final l = label.toLowerCase();
if (l.contains('national')) return Icons.fingerprint;
if (l.contains('phone')) return Icons.phone;
if (l.contains('email')) return Icons.email;
if (l.contains('address')) return Icons.location_on;
if (l.contains('birth')) return Icons.cake;
if (l.contains('father') || l.contains('mother')) return Icons.people;
if (l.contains('license') || l.contains('category')) return Icons.card_membership;
if (l.contains('plate')) return Icons.confirmation_number;
if (l.contains('owner')) return Icons.person_search;
if (l.contains('make') || l.contains('model')) return Icons.directions_car;
if (l.contains('year')) return Icons.calendar_today;
if (l.contains('vin')) return Icons.confirmation_number;
if (l.contains('governorate') || l.contains('place')) return Icons.location_city;
if (l.contains('blood')) return Icons.water_drop;
if (l.contains('spouse') || l.contains('marital')) return Icons.people;
if (l.contains('occupation')) return Icons.work;
if (l.contains('restriction')) return Icons.block;
if (l.contains('engine') || l.contains('capacity')) return Icons.settings;
if (l.contains('first name') || l.contains('last name')) return Icons.person;
return null;
}
TextEditingController? _getController(ReviewDriverController c, String key) {
switch (key) {
case 'firstNameController': return c.firstNameController;
case 'lastNameController': return c.lastNameController;
case 'phoneController': return c.phoneController;
case 'emailController': return c.emailController;
case 'siteController': return c.siteController;
case 'nationalNumberController': return c.nationalNumberController;
case 'birthdateController': return c.birthdateController;
case 'addressController': return c.addressController;
case 'licenseCategoriesController': return c.licenseCategoriesController;
case 'licenseTypeController': return c.licenseTypeController;
case 'expiryDateController': return c.expiryDateController;
case 'licenseIssueDateController': return c.licenseIssueDateController;
case 'ownerController': return c.ownerController;
case 'carPlateController': return c.carPlateController;
case 'vinController': return c.vinController;
case 'carLicenseExpiryDateController': return c.carLicenseExpiryDateController;
case 'makeController': return c.makeController;
case 'modelController': return c.modelController;
case 'yearController': return c.yearController;
case 'fatherNameController': return c.fatherNameController;
case 'motherNameController': return c.motherNameController;
case 'birthPlaceController': return c.birthPlaceController;
case 'bloodTypeController': return c.bloodTypeController;
case 'maritalStatusController': return c.maritalStatusController;
case 'spouseNameController': return c.spouseNameController;
case 'idIssueDateController': return c.idIssueDateController;
case 'idExpiryDateController': return c.idExpiryDateController;
case 'licenseNumberController': return c.licenseNumberController;
case 'licenseCategoryController': return c.licenseCategoryController;
case 'restrictionsController': return c.restrictionsController;
case 'governorateController': return c.governorateController;
case 'occupationController': return c.occupationController;
case 'religionController': return c.religionController;
case 'engineCapacityController': return c.engineCapacityController;
case 'passengerCapacityController': return c.passengerCapacityController;
default: return null;
}
}
@@ -215,7 +411,7 @@ class ReviewDriverPage extends StatelessWidget {
);
}
Widget _buildGenderDropdown(ReviewDriverController c) {
Widget _buildGenderDropdown(ReviewDriverController c, String label) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Obx(
@@ -225,7 +421,7 @@ class ReviewDriverPage extends StatelessWidget {
: c.selectedGender.value,
isExpanded: true,
decoration: InputDecoration(
labelText: 'Gender'.tr,
labelText: label.tr,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
@@ -243,7 +439,7 @@ class ReviewDriverPage extends StatelessWidget {
);
}
Widget _buildColorDropdown(ReviewDriverController c) {
Widget _buildColorDropdown(ReviewDriverController c, String label) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Obx(
@@ -251,7 +447,7 @@ class ReviewDriverPage extends StatelessWidget {
value: c.colorHex.value.isEmpty ? null : c.colorHex.value,
isExpanded: true,
decoration: InputDecoration(
labelText: 'Car Color'.tr,
labelText: label.tr,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
@@ -286,7 +482,7 @@ class ReviewDriverPage extends StatelessWidget {
);
}
Widget _buildFuelDropdown(ReviewDriverController c) {
Widget _buildFuelDropdown(ReviewDriverController c, String label) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Obx(
@@ -297,7 +493,7 @@ class ReviewDriverPage extends StatelessWidget {
: null,
isExpanded: true,
decoration: InputDecoration(
labelText: 'Fuel Type'.tr,
labelText: label.tr,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
@@ -315,283 +511,6 @@ class ReviewDriverPage extends StatelessWidget {
);
}
Widget _buildIdFrontFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('ID Card Information (Front)',
style: Get.textTheme.titleMedium),
const Divider(),
Row(
children: [
Expanded(
child: _buildTextField(
label: 'First Name',
controller: c.firstNameController,
icon: Icons.person,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildTextField(
label: 'Last Name',
controller: c.lastNameController,
icon: Icons.person,
),
),
],
),
Row(
children: [
Expanded(
child: _buildTextField(
label: 'National Number',
controller: c.nationalNumberController,
icon: Icons.fingerprint,
),
),
const SizedBox(width: 8),
Expanded(child: _buildGenderDropdown(c)),
],
),
_buildTextField(
label: 'Birthdate',
controller: c.birthdateController,
icon: Icons.cake,
onTap: () => c.selectDate(Get.context!, c.birthdateController),
),
],
);
}
Widget _buildIdBackFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('ID Card Information (Back)',
style: Get.textTheme.titleMedium),
const Divider(),
_buildTextField(
label: 'Address',
controller: c.addressController,
icon: Icons.location_on,
maxLines: 2,
),
_buildTextField(
label: 'Place of Registration',
controller: c.siteController,
icon: Icons.location_city,
),
],
);
}
Widget _buildDriverLicenseFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Driver License Information',
style: Get.textTheme.titleMedium),
const Divider(),
_buildTextField(
label: 'License Type',
controller: c.licenseTypeController,
icon: Icons.card_membership,
),
_buildTextField(
label: 'License Categories',
controller: c.licenseCategoriesController,
icon: Icons.category,
),
_buildTextField(
label: 'License Issue Date',
controller: c.licenseIssueDateController,
icon: Icons.event,
onTap: () =>
c.selectDate(Get.context!, c.licenseIssueDateController),
),
],
);
}
Widget _buildLicenseBackFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Driver License (Back)', style: Get.textTheme.titleMedium),
const Divider(),
_buildTextField(
label: 'Expiry Date',
controller: c.expiryDateController,
icon: Icons.event_busy,
onTap: () => c.selectDate(Get.context!, c.expiryDateController),
),
],
);
}
Widget _buildCarFrontFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Car Registration (Front)',
style: Get.textTheme.titleMedium),
const Divider(),
_buildTextField(
label: 'Owner Name',
controller: c.ownerController,
icon: Icons.person_search,
),
Row(
children: [
Expanded(child: _buildColorDropdown(c)),
const SizedBox(width: 8),
Expanded(
child: _buildTextField(
label: 'Car Plate',
controller: c.carPlateController,
icon: Icons.confirmation_number,
),
),
],
),
_buildTextField(
label: 'License Issue Date',
controller: c.licenseIssueDateController,
icon: Icons.event,
onTap: () =>
c.selectDate(Get.context!, c.licenseIssueDateController),
),
],
);
}
Widget _buildCarBackFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Car Registration (Back)',
style: Get.textTheme.titleMedium),
const Divider(),
Row(
children: [
Expanded(
child: _buildTextField(
label: 'Make',
controller: c.makeController,
icon: Icons.directions_car,
),
),
const SizedBox(width: 8),
Expanded(
child: _buildTextField(
label: 'Model',
controller: c.modelController,
icon: Icons.model_training,
),
),
],
),
Row(
children: [
Expanded(
child: _buildTextField(
label: 'Year',
controller: c.yearController,
keyboardType: TextInputType.number,
),
),
const SizedBox(width: 8),
Expanded(child: _buildFuelDropdown(c)),
],
),
_buildTextField(
label: 'VIN (Chassis Number)',
controller: c.vinController,
icon: Icons.confirmation_number,
),
_buildTextField(
label: 'Expiration Date',
controller: c.carLicenseExpiryDateController,
icon: Icons.event_busy,
onTap: () => c.selectDate(
Get.context!, c.carLicenseExpiryDateController),
),
],
);
}
Widget _buildCriminalRecordFields() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Criminal Record', style: Get.textTheme.titleMedium),
const Divider(),
Card(
color: Colors.green[50],
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(Icons.check_circle, color: Colors.green[700], size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
'Review the criminal record document above. '
'Verify the name matches the driver and the record is valid.',
style: TextStyle(color: Colors.green[800]),
),
),
],
),
),
),
],
);
}
Widget _buildProfilePhotoFields(ReviewDriverController c) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Profile Photo', style: Get.textTheme.titleMedium),
const Divider(),
Card(
color: Colors.blue[50],
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(Icons.face, color: Colors.blue[700], size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
'Verify the profile photo matches the person in the ID '
'and Driver License photos above.',
style: TextStyle(color: Colors.blue[800]),
),
),
],
),
),
),
const SizedBox(height: 12),
_buildTextField(
label: 'Phone Number',
controller: c.phoneController,
icon: Icons.phone,
keyboardType: TextInputType.phone,
),
_buildTextField(
label: 'Email',
controller: c.emailController,
icon: Icons.email,
keyboardType: TextInputType.emailAddress,
),
],
);
}
Widget _buildBottomActions(ReviewDriverController c, BuildContext context) {
return Obx(() {
final saving = c.isSaving.value;

View File

@@ -6,6 +6,7 @@ import 'package:siro_service/constant/box_name.dart';
import 'package:siro_service/constant/links.dart';
import 'package:siro_service/controller/functions/crud.dart';
import 'package:siro_service/main.dart';
import 'package:siro_service/views/widgets/mycircular.dart';
class ReviewDriverController extends GetxController {
var isLoading = true.obs;
@@ -48,6 +49,189 @@ class ReviewDriverController extends GetxController {
'profile_picture': Icons.person,
};
var country = ''.obs;
var countryDetected = false;
/// Get current country code from box or server data
String get currentCountry {
if (country.value.isNotEmpty) return country.value;
final boxCountry = box.read('countryCode')?.toString() ?? '';
if (boxCountry.isNotEmpty) {
country.value = boxCountry;
return boxCountry;
}
final site = serverData['site'] ?? '';
if (site.contains('سوريا') || site.contains('دمشق') || site.contains('حلب')) {
country.value = 'Syria';
return 'Syria';
}
if (site.contains('أردن') || site.contains('عمان') || site.contains('اربد')) {
country.value = 'Jordan';
return 'Jordan';
}
country.value = 'Syria';
return 'Syria';
}
/// Field configuration: which fields appear on which tab, per country
/// Each entry: [key, label, isDate, isGender, isColor, isFuel]
static final Map<String, Map<String, List<List<dynamic>>>> countryFieldConfig = {
'Syria': {
'id_front': [
['firstNameController', 'First Name', false, false, false, false],
['lastNameController', 'Last Name', false, false, false, false],
['fatherNameController', 'Father Name', false, false, false, false],
['motherNameController', 'Mother Name', false, false, false, false],
['nationalNumberController', 'National Number', false, false, false, false],
['gender', 'Gender', false, true, false, false],
['birthdateController', 'Birthdate', true, false, false, false],
['birthPlaceController', 'Birth Place', false, false, false, false],
['bloodTypeController', 'Blood Type', false, false, false, false],
],
'id_back': [
['addressController', 'Address', false, false, false, false],
['governorateController', 'Governorate', false, false, false, false],
['siteController', 'Place of Registration', false, false, false, false],
['maritalStatusController', 'Marital Status', false, false, false, false],
['spouseNameController', 'Spouse Name', false, false, false, false],
['idIssueDateController', 'ID Issue Date', true, false, false, false],
['idExpiryDateController', 'ID Expiry Date', true, false, false, false],
],
'driver_license': [
['licenseNumberController', 'License Number', false, false, false, false],
['licenseCategoryController', 'License Category', false, false, false, false],
['licenseTypeController', 'License Type', false, false, false, false],
['licenseIssueDateController', 'Issue Date', true, false, false, false],
['expiryDateController', 'Expiry Date', true, false, false, false],
],
'driver_license_back': [
['restrictionsController', 'Restrictions', false, false, false, false],
],
'car_license_front': [
['ownerController', 'Owner Name', false, false, false, false],
['carPlateController', 'Car Plate', false, false, false, false],
['makeController', 'Make', false, false, false, false],
['modelController', 'Model', false, false, false, false],
['yearController', 'Year', false, false, false, false],
['color', 'Car Color', false, false, true, false],
],
'car_license_back': [
['vinController', 'VIN / Chassis', false, false, false, false],
['fuel', 'Fuel Type', false, false, false, true],
['engineCapacityController', 'Engine Capacity', false, false, false, false],
['carLicenseExpiryDateController', 'License Expiry', true, false, false, false],
],
'criminal_record': [],
'profile_picture': [
['phoneController', 'Phone Number', false, false, false, false],
['emailController', 'Email', false, false, false, false],
],
},
'Jordan': {
'id_front': [
['firstNameController', 'First Name', false, false, false, false],
['lastNameController', 'Last Name', false, false, false, false],
['nationalNumberController', 'National Number', false, false, false, false],
['gender', 'Gender', false, true, false, false],
['birthdateController', 'Birthdate', true, false, false, false],
['siteController', 'Place of Registration', false, false, false, false],
['governorateController', 'Governorate', false, false, false, false],
],
'id_back': [
['addressController', 'Address', false, false, false, false],
['idIssueDateController', 'ID Issue Date', true, false, false, false],
['idExpiryDateController', 'ID Expiry Date', true, false, false, false],
['bloodTypeController', 'Blood Type', false, false, false, false],
['maritalStatusController', 'Marital Status', false, false, false, false],
['spouseNameController', 'Spouse Name', false, false, false, false],
['occupationController', 'Occupation', false, false, false, false],
],
'driver_license': [
['licenseNumberController', 'License Number', false, false, false, false],
['licenseCategoryController', 'License Category', false, false, false, false],
['licenseIssueDateController', 'Issue Date', true, false, false, false],
['expiryDateController', 'Expiry Date', true, false, false, false],
],
'driver_license_back': [
['restrictionsController', 'Restrictions', false, false, false, false],
],
'car_license_front': [
['ownerController', 'Owner Name', false, false, false, false],
['carPlateController', 'Car Plate', false, false, false, false],
['makeController', 'Make', false, false, false, false],
['modelController', 'Model', false, false, false, false],
['yearController', 'Year', false, false, false, false],
['color', 'Car Color', false, false, true, false],
],
'car_license_back': [
['vinController', 'VIN / Chassis', false, false, false, false],
['fuel', 'Fuel Type', false, false, false, true],
['engineCapacityController', 'Engine Capacity', false, false, false, false],
['passengerCapacityController', 'Passenger Capacity', false, false, false, false],
['carLicenseExpiryDateController', 'License Expiry', true, false, false, false],
],
'criminal_record': [],
'profile_picture': [
['phoneController', 'Phone Number', false, false, false, false],
['emailController', 'Email', false, false, false, false],
],
},
'Egypt': {
'id_front': [
['firstNameController', 'First Name', false, false, false, false],
['lastNameController', 'Last Name', false, false, false, false],
['nationalNumberController', 'National Number', false, false, false, false],
['gender', 'Gender', false, true, false, false],
['birthdateController', 'Birthdate', true, false, false, false],
['governorateController', 'Governorate', false, false, false, false],
],
'id_back': [
['addressController', 'Address', false, false, false, false],
['idIssueDateController', 'ID Issue Date', true, false, false, false],
['idExpiryDateController', 'ID Expiry Date', true, false, false, false],
['occupationController', 'Occupation', false, false, false, false],
['maritalStatusController', 'Marital Status', false, false, false, false],
['religionController', 'Religion', false, false, false, false],
['bloodTypeController', 'Blood Type', false, false, false, false],
['spouseNameController', 'Spouse Name', false, false, false, false],
],
'driver_license': [
['licenseNumberController', 'License Number', false, false, false, false],
['licenseCategoryController', 'License Category', false, false, false, false],
['licenseIssueDateController', 'Issue Date', true, false, false, false],
['expiryDateController', 'Expiry Date', true, false, false, false],
],
'driver_license_back': [
['restrictionsController', 'Restrictions', false, false, false, false],
],
'car_license_front': [
['ownerController', 'Owner Name', false, false, false, false],
['carPlateController', 'Car Plate', false, false, false, false],
['makeController', 'Make', false, false, false, false],
['modelController', 'Model', false, false, false, false],
['yearController', 'Year', false, false, false, false],
['color', 'Car Color', false, false, true, false],
],
'car_license_back': [
['vinController', 'VIN / Chassis', false, false, false, false],
['fuel', 'Fuel Type', false, false, false, true],
['engineCapacityController', 'Engine Capacity', false, false, false, false],
['carLicenseExpiryDateController', 'License Expiry', true, false, false, false],
],
'criminal_record': [],
'profile_picture': [
['phoneController', 'Phone Number', false, false, false, false],
['emailController', 'Email', false, false, false, false],
],
},
};
List<List<dynamic>> getFieldsForTab(String tabKey) {
final c = currentCountry;
final config = countryFieldConfig[c] ?? countryFieldConfig['Syria']!;
return config[tabKey] ?? [];
}
late TextEditingController firstNameController;
late TextEditingController lastNameController;
late TextEditingController phoneController;
@@ -67,6 +251,22 @@ class ReviewDriverController extends GetxController {
late TextEditingController makeController;
late TextEditingController modelController;
late TextEditingController yearController;
late TextEditingController fatherNameController;
late TextEditingController motherNameController;
late TextEditingController birthPlaceController;
late TextEditingController bloodTypeController;
late TextEditingController maritalStatusController;
late TextEditingController spouseNameController;
late TextEditingController idIssueDateController;
late TextEditingController idExpiryDateController;
late TextEditingController licenseNumberController;
late TextEditingController licenseCategoryController;
late TextEditingController restrictionsController;
late TextEditingController governorateController;
late TextEditingController occupationController;
late TextEditingController religionController;
late TextEditingController engineCapacityController;
late TextEditingController passengerCapacityController;
var selectedGender = ''.obs;
var colorHex = ''.obs;
@@ -105,6 +305,22 @@ class ReviewDriverController extends GetxController {
makeController = TextEditingController();
modelController = TextEditingController();
yearController = TextEditingController();
fatherNameController = TextEditingController();
motherNameController = TextEditingController();
birthPlaceController = TextEditingController();
bloodTypeController = TextEditingController();
maritalStatusController = TextEditingController();
spouseNameController = TextEditingController();
idIssueDateController = TextEditingController();
idExpiryDateController = TextEditingController();
licenseNumberController = TextEditingController();
licenseCategoryController = TextEditingController();
restrictionsController = TextEditingController();
governorateController = TextEditingController();
occupationController = TextEditingController();
religionController = TextEditingController();
engineCapacityController = TextEditingController();
passengerCapacityController = TextEditingController();
}
Future<void> fetchData() async {
@@ -124,7 +340,7 @@ class ReviewDriverController extends GetxController {
_populateDocUrls(raw['documents']);
}
} catch (e) {
Get.snackbar('Error', 'Failed to load data: $e');
mySnackeBarError('Failed to load data: $e');
} finally {
isLoading.value = false;
}
@@ -168,6 +384,39 @@ class ReviewDriverController extends GetxController {
modelController.text = serverData['model'] ?? '';
yearController.text = serverData['year'] ?? '';
selectedFuel.value = serverData['fuel'] ?? '';
fatherNameController.text = serverData['father_name'] ?? '';
motherNameController.text = serverData['mother_name'] ?? '';
birthPlaceController.text = serverData['birth_place'] ?? '';
bloodTypeController.text = serverData['blood_type'] ?? '';
maritalStatusController.text = serverData['marital_status'] ?? '';
spouseNameController.text = serverData['spouse_name'] ?? '';
idIssueDateController.text = serverData['id_issue_date'] ?? '';
idExpiryDateController.text = serverData['id_expiry_date'] ?? '';
licenseNumberController.text = serverData['license_number'] ?? '';
licenseCategoryController.text = serverData['license_category'] ?? '';
restrictionsController.text = serverData['restrictions'] ?? '';
governorateController.text = serverData['governorate'] ?? '';
occupationController.text = serverData['occupation'] ?? '';
religionController.text = serverData['religion'] ?? '';
engineCapacityController.text = serverData['engine_capacity'] ?? '';
passengerCapacityController.text = serverData['passenger_capacity'] ?? '';
// Detect country from server data if available
if (!countryDetected) {
countryDetected = true;
if (serverData['country']?.isNotEmpty == true) {
country.value = serverData['country']!;
} else if (serverData['site']?.isNotEmpty == true) {
final s = serverData['site']!;
if (s.contains('سوريا') || s.contains('دمشق')) {
country.value = 'Syria';
} else if (s.contains('أردن') || s.contains('عمان')) {
country.value = 'Jordan';
} else if (s.contains('مصر') || s.contains('القاهرة')) {
country.value = 'Egypt';
}
}
}
final serverColorName = serverData['color'] ?? '';
final colorOption = kCarColorOptions.firstWhere(
@@ -264,12 +513,12 @@ class ReviewDriverController extends GetxController {
payload: payload,
);
if (response != 'failure' && response['status'] == 'success') {
Get.snackbar('Success', 'Data saved successfully');
mySnackbarSuccess('Data saved successfully');
} else {
Get.snackbar('Error', 'Failed to save changes');
mySnackeBarError('Failed to save changes');
}
} catch (e) {
Get.snackbar('Error', 'Error: $e');
mySnackeBarError('Error: $e');
} finally {
isSaving.value = false;
}
@@ -284,14 +533,14 @@ class ReviewDriverController extends GetxController {
payload: payload,
);
if (response != 'failure' && response['status'] == 'success') {
Get.snackbar('Success', 'Driver activated successfully!');
mySnackbarSuccess('Driver activated successfully!');
await Future.delayed(const Duration(milliseconds: 500));
Get.back();
} else {
Get.snackbar('Error', 'Failed to activate driver');
mySnackeBarError('Failed to activate driver');
}
} catch (e) {
Get.snackbar('Error', 'Error: $e');
mySnackeBarError('Error: $e');
} finally {
isSaving.value = false;
}
@@ -299,7 +548,7 @@ class ReviewDriverController extends GetxController {
Future<void> rejectDriver(String reason) async {
if (reason.trim().isEmpty) {
Get.snackbar('Error', 'Please enter a rejection reason');
mySnackeBarError('Please enter a rejection reason');
return;
}
isSaving.value = true;
@@ -312,14 +561,14 @@ class ReviewDriverController extends GetxController {
},
);
if (response != 'failure' && response['status'] == 'success') {
Get.snackbar('Success', 'Driver rejected');
mySnackbarSuccess('Driver rejected');
await Future.delayed(const Duration(milliseconds: 500));
Get.back();
} else {
Get.snackbar('Error', 'Failed to reject driver');
mySnackeBarError('Failed to reject driver');
}
} catch (e) {
Get.snackbar('Error', 'Error: $e');
mySnackeBarError('Error: $e');
} finally {
isSaving.value = false;
}
@@ -414,6 +663,22 @@ class ReviewDriverController extends GetxController {
makeController.dispose();
modelController.dispose();
yearController.dispose();
fatherNameController.dispose();
motherNameController.dispose();
birthPlaceController.dispose();
bloodTypeController.dispose();
maritalStatusController.dispose();
spouseNameController.dispose();
idIssueDateController.dispose();
idExpiryDateController.dispose();
licenseNumberController.dispose();
licenseCategoryController.dispose();
restrictionsController.dispose();
governorateController.dispose();
occupationController.dispose();
religionController.dispose();
engineCapacityController.dispose();
passengerCapacityController.dispose();
super.onClose();
}
}