first commit
This commit is contained in:
@@ -0,0 +1,458 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:siro_service/constant/colors.dart';
|
||||
import 'package:siro_service/views/widgets/elevated_btn.dart';
|
||||
import 'package:siro_service/views/widgets/my_scafold.dart';
|
||||
|
||||
import '../registration_captain_controller.dart';
|
||||
|
||||
class RegisterCaptain extends StatelessWidget {
|
||||
const RegisterCaptain({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final controller = Get.put(RegisterCaptainController());
|
||||
|
||||
return MyScaffold(
|
||||
title: 'Syrian Documents Check'.tr,
|
||||
isleading: true,
|
||||
body: [
|
||||
Obx(() {
|
||||
if (controller.isLoading.value) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: StepIndicator(
|
||||
currentStep: controller.currentPageIndex.value,
|
||||
totalSteps: 4,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PageView(
|
||||
controller: controller.pageController,
|
||||
onPageChanged: (index) {
|
||||
controller.currentPageIndex.value = index;
|
||||
},
|
||||
children: [
|
||||
_buildSyrianDriverLicenseFront(context, controller),
|
||||
_buildSyrianDriverLicenseBack(context, controller),
|
||||
_buildSyrianCarLicenseFront(context, controller),
|
||||
_buildSyrianCarLicenseBack(controller),
|
||||
],
|
||||
),
|
||||
),
|
||||
_buildNavigationControls(controller),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavigationControls(RegisterCaptainController controller) {
|
||||
bool isLastPage = controller.currentPageIndex.value == 3;
|
||||
bool isFirstPage = controller.currentPageIndex.value == 0;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (!isFirstPage)
|
||||
MyElevatedButton(
|
||||
title: 'Back'.tr,
|
||||
onPressed: controller.previousPage,
|
||||
kolor: Colors.grey,
|
||||
),
|
||||
if (isFirstPage) const Spacer(),
|
||||
MyElevatedButton(
|
||||
title: isLastPage ? 'Save and Activate'.tr : 'Next'.tr,
|
||||
onPressed: isLastPage
|
||||
? controller.updateAndActivateSyrianDriver
|
||||
: controller.nextPage,
|
||||
kolor: isLastPage ? AppColor.greenColor : AppColor.primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTextField({
|
||||
required String label,
|
||||
required TextEditingController controller,
|
||||
IconData? icon,
|
||||
TextInputType keyboardType = TextInputType.text,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
keyboardType: keyboardType,
|
||||
readOnly: onTap != null,
|
||||
onTap: onTap,
|
||||
decoration: InputDecoration(
|
||||
labelText: label.tr,
|
||||
prefixIcon:
|
||||
icon != null ? Icon(icon, color: AppColor.secondaryColor) : null,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide:
|
||||
const BorderSide(color: AppColor.secondaryColor, width: 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPageContent({
|
||||
required RxString imageUrl,
|
||||
required List<Widget> formFields,
|
||||
}) {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Image.network(
|
||||
imageUrl.value,
|
||||
fit: BoxFit.fitWidth,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Container(
|
||||
height: 200,
|
||||
color: Colors.grey[200],
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Image not available'.tr,
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Divider(),
|
||||
...formFields,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildColorDropdown(RegisterCaptainController controller) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Obx(
|
||||
() => DropdownButtonFormField<String>(
|
||||
value: controller.colorHex.value.isEmpty
|
||||
? null
|
||||
: controller.colorHex.value,
|
||||
isExpanded: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Car Color'.tr,
|
||||
prefixIcon: Icon(Icons.color_lens, color: AppColor.secondaryColor),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
items: RegisterCaptainController.kCarColorOptions.map((opt) {
|
||||
final hex = opt['hex']!;
|
||||
final key = opt['key']!;
|
||||
return DropdownMenuItem<String>(
|
||||
value: hex,
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
decoration: BoxDecoration(
|
||||
color: controller.hexToColor(hex),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.black12),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: Text(key.tr)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (hex) {
|
||||
if (hex != null) {
|
||||
controller.updateColorSelection(hex);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGenderDropdown(RegisterCaptainController controller) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Obx(
|
||||
() => DropdownButtonFormField<String>(
|
||||
value: controller.selectedGender.value.isEmpty
|
||||
? null
|
||||
: controller.selectedGender.value,
|
||||
isExpanded: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Gender'.tr,
|
||||
prefixIcon: Icon(Icons.wc, color: AppColor.secondaryColor),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
items: ['Male', 'Female'].map((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value.tr),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue != null) {
|
||||
controller.selectedGender.value = newValue;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFuelDropdown(RegisterCaptainController controller) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Obx(
|
||||
() => DropdownButtonFormField<String>(
|
||||
value: RegisterCaptainController.kFuelOptions
|
||||
.contains(controller.selectedFuel.value)
|
||||
? controller.selectedFuel.value
|
||||
: null,
|
||||
isExpanded: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Fuel Type'.tr,
|
||||
prefixIcon:
|
||||
Icon(Icons.local_gas_station, color: AppColor.secondaryColor),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
items: RegisterCaptainController.kFuelOptions.map((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value.tr),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue != null) {
|
||||
controller.selectedFuel.value = newValue;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// --- PAGE 1: Driver License Front ---
|
||||
Widget _buildSyrianDriverLicenseFront(
|
||||
BuildContext context, RegisterCaptainController controller) {
|
||||
return _buildPageContent(
|
||||
imageUrl: controller.docUrls['driver_license_front']!,
|
||||
formFields: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'First Name',
|
||||
controller: controller.firstNameController,
|
||||
keyboardType: TextInputType.name),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'Last Name',
|
||||
controller: controller.lastNameController,
|
||||
keyboardType: TextInputType.name),
|
||||
),
|
||||
],
|
||||
),
|
||||
_buildTextField(
|
||||
label: 'Place of Registration',
|
||||
controller: controller.siteController,
|
||||
icon: Icons.location_city),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'National Number',
|
||||
controller: controller.nationalNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
icon: Icons.fingerprint),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(child: _buildGenderDropdown(controller)),
|
||||
],
|
||||
),
|
||||
// _buildTextField(
|
||||
// label: 'Birthdate',
|
||||
// controller: controller.birthdateController,
|
||||
// icon: Icons.cake,
|
||||
// onTap: () =>
|
||||
// controller.selectDate(context, controller.birthdateController)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// --- PAGE 2: Driver License Back ---
|
||||
Widget _buildSyrianDriverLicenseBack(
|
||||
BuildContext context, RegisterCaptainController controller) {
|
||||
return _buildPageContent(
|
||||
imageUrl: controller.docUrls['driver_license_back']!,
|
||||
formFields: [
|
||||
_buildTextField(
|
||||
label: 'License Category',
|
||||
controller: controller.licenseCategoriesController),
|
||||
_buildTextField(
|
||||
label: 'Expiry Date',
|
||||
controller: controller.expiryDateController,
|
||||
icon: Icons.event_busy,
|
||||
onTap: () => controller.selectDate(
|
||||
context, controller.expiryDateController)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// --- PAGE 3: Car License Front ---
|
||||
Widget _buildSyrianCarLicenseFront(
|
||||
BuildContext context, RegisterCaptainController controller) {
|
||||
return _buildPageContent(
|
||||
imageUrl: controller.docUrls['car_license_front']!,
|
||||
formFields: [
|
||||
_buildTextField(
|
||||
label: 'Owner Name',
|
||||
controller: controller.ownerController,
|
||||
keyboardType: TextInputType.name,
|
||||
icon: Icons.person_search),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildColorDropdown(controller)),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'Car Plate',
|
||||
controller: controller.carPlateController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// _buildTextField(
|
||||
// label: 'VIN',
|
||||
// controller: controller.vinController,
|
||||
// icon: Icons.confirmation_number),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'License Issue Date',
|
||||
controller: controller.licenseIssueDateController,
|
||||
onTap: () => controller.selectDate(
|
||||
context, controller.licenseIssueDateController))),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'License Expiry Date',
|
||||
controller: controller.carLicenseExpiryDateController,
|
||||
onTap: () => controller.selectDate(
|
||||
context, controller.carLicenseExpiryDateController))),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// --- PAGE 4: Car License Back ---
|
||||
Widget _buildSyrianCarLicenseBack(RegisterCaptainController controller) {
|
||||
return _buildPageContent(
|
||||
imageUrl: controller.docUrls['car_license_back']!,
|
||||
formFields: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'Make',
|
||||
controller: controller.makeController,
|
||||
)),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'Model',
|
||||
controller: controller.modelController,
|
||||
)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildTextField(
|
||||
label: 'Year',
|
||||
controller: controller.yearController,
|
||||
keyboardType: TextInputType.number)),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(child: _buildFuelDropdown(controller)),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StepIndicator extends StatelessWidget {
|
||||
final int currentStep;
|
||||
final int totalSteps;
|
||||
|
||||
const StepIndicator({
|
||||
super.key,
|
||||
required this.currentStep,
|
||||
required this.totalSteps,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
'${'Step'.tr} ${currentStep + 1} ${'of'.tr} $totalSteps',
|
||||
style: const TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black54),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(totalSteps, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
width: 30,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: index <= currentStep
|
||||
? AppColor.primaryColor
|
||||
: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user