Initial commit

This commit is contained in:
2025-12-08 23:25:00 +05:00
commit ee5cb4ac1a
851 changed files with 115172 additions and 0 deletions

View File

@@ -0,0 +1,807 @@
import 'package:country_code_picker/country_code_picker.dart';
import 'package:driver/constant/constant.dart';
import 'package:driver/constant/show_toast_dialog.dart';
import 'package:driver/controllers/driver_create_controller.dart';
import 'package:driver/models/car_makes.dart';
import 'package:driver/models/section_model.dart';
import 'package:driver/models/vehicle_type.dart';
import 'package:driver/models/zone_model.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/text_field_widget.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import '../../models/car_model.dart' show CarModel;
import '../../themes/responsive.dart' show Responsive;
class DriverCreateScreen extends StatelessWidget {
const DriverCreateScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX(
init: DriverCreateController(),
builder: (controller) {
return Scaffold(
appBar: AppBar(
title: Text(controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty
? 'Update Driver'.tr
: 'Create Driver'.tr),
),
body: controller.isLoading.value
? Constant.loader()
: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Service".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
),
const SizedBox(height: 5),
DropdownButtonFormField<String>(
hint: Text(
'Service Type'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular),
),
icon: const Icon(Icons.keyboard_arrow_down),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
),
initialValue: controller.selectedService.value.isEmpty ? null : controller.selectedService.value,
onChanged: (value) {
controller.selectedService.value = value!;
if (value != "Delivery Service") {
controller.getSection();
}
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.service.map((item) {
return DropdownMenuItem<String>(value: item, child: Text(item.toString()));
}).toList(),
),
const SizedBox(height: 10),
],
),
controller.selectedService.value == "Cab Service" ||
controller.selectedService.value == "Rental Service" ||
controller.selectedService.value == "Parcel Service"
? Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Select section".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
),
const SizedBox(height: 5),
DropdownButtonFormField<SectionModel>(
hint: Text(
'Service Type'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular),
),
icon: const Icon(Icons.keyboard_arrow_down),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
),
initialValue:
controller.selectedSection.value.id == null ? null : controller.selectedSection.value,
onChanged: (value) {
controller.selectedSection.value = value!;
controller.getVehicleType();
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.sectionList.map((item) {
return DropdownMenuItem<SectionModel>(value: item, child: Text(item.name.toString()));
}).toList(),
),
const SizedBox(height: 10),
controller.selectedService.value == "Cab Service" ||
controller.selectedService.value == "Rental Service"
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Select Vehicle Type".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
),
const SizedBox(height: 5),
DropdownButtonFormField<VehicleType>(
hint: Text(
'Vehicle Type'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular),
),
icon: const Icon(Icons.keyboard_arrow_down),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
),
initialValue: controller.selectedVehicleType.value.id == null
? null
: controller.selectedVehicleType.value,
onChanged: (value) {
controller.selectedVehicleType.value = value!;
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.cabVehicleType.map((item) {
return DropdownMenuItem<VehicleType>(
value: item, child: Text(item.name.toString()));
}).toList(),
),
const SizedBox(height: 10),
Text(
"Select Car Brand".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
),
const SizedBox(height: 5),
DropdownButtonFormField<CarMakes>(
hint: Text(
'Car Brand'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular),
),
icon: const Icon(Icons.keyboard_arrow_down),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
),
initialValue: controller.selectedCarMakes.value.id == null
? null
: controller.selectedCarMakes.value,
onChanged: (value) {
controller.selectedCarMakes.value = value!;
controller.getCarModel();
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.carMakesList.map((item) {
return DropdownMenuItem<CarMakes>(value: item, child: Text(item.name.toString()));
}).toList(),
),
const SizedBox(height: 10),
Text(
"Select car model".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
),
const SizedBox(height: 5),
DropdownButtonFormField<CarModel>(
hint: Text(
'Car model'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular),
),
icon: const Icon(Icons.keyboard_arrow_down),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
),
initialValue: controller.selectedCarModel.value.id == null
? null
: controller.selectedCarModel.value,
onChanged: (value) {
controller.selectedCarModel.value = value!;
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.carModelList.map((item) {
return DropdownMenuItem<CarModel>(value: item, child: Text(item.name.toString()));
}).toList(),
),
const SizedBox(height: 10),
TextFieldWidget(
title: 'Car Plat Number'.tr,
controller: controller.carPlatNumberEditingController.value,
hintText: 'Enter Car Plat Number'.tr,
textInputAction: TextInputAction.next,
),
],
)
: SizedBox()
],
)
: SizedBox(),
controller.selectedService.value == "Cab Service"
? Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Select Ride Type".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
),
),
const SizedBox(height: 5),
Obx(
() => Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: RadioListTile<String>(
dense: true,
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
contentPadding: EdgeInsets.zero,
title: Text('Ride'.tr,
style: TextStyle(
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
value: 'ride',
activeColor: AppThemeData.primary300,
groupValue: controller.selectedValue.value,
onChanged: (value) {
controller.selectedValue.value = value!;
},
),
),
Expanded(
child: RadioListTile<String>(
dense: true,
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
contentPadding: EdgeInsets.zero,
activeColor: AppThemeData.primary300,
title: Text('Intercity'.tr,
style: TextStyle(
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
value: 'intercity',
groupValue: controller.selectedValue.value,
onChanged: (value) {
controller.selectedValue.value = value!;
},
),
),
Expanded(
child: RadioListTile<String>(
dense: true,
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
contentPadding: EdgeInsets.zero,
title: Text('Both'.tr,
style: TextStyle(
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
value: 'both',
activeColor: AppThemeData.primary300,
groupValue: controller.selectedValue.value,
onChanged: (value) {
controller.selectedValue.value = value!;
},
),
),
],
),
)
],
),
)
: SizedBox(),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Zone".tr,
style: TextStyle(
fontFamily: AppThemeData.semiBold,
fontSize: 14,
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
const SizedBox(
height: 5,
),
DropdownButtonFormField<ZoneModel>(
hint: Text(
'Select zone'.tr,
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
fontFamily: AppThemeData.regular,
),
),
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: InputDecoration(
errorStyle: const TextStyle(color: Colors.red),
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
),
),
initialValue: controller.selectedZone.value.id == null ? null : controller.selectedZone.value,
onChanged: (value) {
controller.selectedZone.value = value!;
controller.update();
},
style: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
items: controller.zoneList.map((item) {
return DropdownMenuItem<ZoneModel>(
value: item,
child: Text(item.name.toString()),
);
}).toList()),
],
),
const SizedBox(
height: 10,
),
Row(
children: [
Expanded(
child: TextFieldWidget(
title: 'First Name'.tr,
controller: controller.firstNameEditingController.value,
hintText: 'Enter First Name'.tr,
prefix: Padding(
padding: const EdgeInsets.all(12),
child: SvgPicture.asset(
"assets/icons/ic_user.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
),
),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: TextFieldWidget(
title: 'Last Name'.tr,
controller: controller.lastNameEditingController.value,
hintText: 'Enter Last Name'.tr,
prefix: Padding(
padding: const EdgeInsets.all(12),
child: SvgPicture.asset(
"assets/icons/ic_user.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
),
),
),
),
],
),
TextFieldWidget(
title: 'Email Address'.tr,
textInputType: TextInputType.emailAddress,
controller: controller.emailEditingController.value,
hintText: 'Enter Email Address'.tr,
enable:
controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty ? false : true,
prefix: Padding(
padding: const EdgeInsets.all(12),
child: SvgPicture.asset(
"assets/icons/ic_mail.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
),
),
),
TextFieldWidget(
title: 'Phone Number'.tr,
controller: controller.phoneNUmberEditingController.value,
hintText: 'Enter Phone Number'.tr,
textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true),
textInputAction: TextInputAction.done,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
prefix: CountryCodePicker(
onChanged: (value) {
controller.countryCodeEditingController.value.text = value.dialCode ?? Constant.defaultCountryCode;
},
dialogTextStyle: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontWeight: FontWeight.w500,
fontFamily: AppThemeData.medium),
dialogBackgroundColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
initialSelection: controller.countryCodeEditingController.value.text,
comparator: (a, b) => b.name!.compareTo(a.name.toString()),
textStyle: TextStyle(
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.medium),
searchDecoration: InputDecoration(iconColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
searchStyle: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontWeight: FontWeight.w500,
fontFamily: AppThemeData.medium),
),
),
controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty
? SizedBox()
: Column(
children: [
TextFieldWidget(
title: 'Password'.tr,
controller: controller.passwordEditingController.value,
hintText: 'Enter Password'.tr,
obscureText: controller.passwordVisible.value,
prefix: Padding(
padding: const EdgeInsets.all(12),
child: SvgPicture.asset(
"assets/icons/ic_lock.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
),
),
suffix: Padding(
padding: const EdgeInsets.all(12),
child: InkWell(
onTap: () {
controller.passwordVisible.value = !controller.passwordVisible.value;
},
child: controller.passwordVisible.value
? SvgPicture.asset(
"assets/icons/ic_password_show.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
)
: SvgPicture.asset(
"assets/icons/ic_password_close.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
)),
),
),
TextFieldWidget(
title: 'Confirm Password'.tr,
controller: controller.conformPasswordEditingController.value,
hintText: 'Enter Confirm Password'.tr,
obscureText: controller.conformPasswordVisible.value,
prefix: Padding(
padding: const EdgeInsets.all(12),
child: SvgPicture.asset(
"assets/icons/ic_lock.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
),
),
suffix: Padding(
padding: const EdgeInsets.all(12),
child: InkWell(
onTap: () {
controller.conformPasswordVisible.value = !controller.conformPasswordVisible.value;
},
child: controller.conformPasswordVisible.value
? SvgPicture.asset(
"assets/icons/ic_password_show.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
)
: SvgPicture.asset(
"assets/icons/ic_password_close.svg",
colorFilter: ColorFilter.mode(
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
BlendMode.srcIn,
),
)),
),
),
],
),
],
),
),
),
),
InkWell(
onTap: () {
if (controller.firstNameEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter first name".tr);
return;
} else if (controller.lastNameEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter last name".tr);
return;
} else if (controller.emailEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter email address".tr);
return;
} else if (!GetUtils.isEmail(controller.emailEditingController.value.text)) {
ShowToastDialog.showToast("Please enter valid email address".tr);
return;
} else if (controller.phoneNUmberEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter phone number".tr);
return;
} else if (controller.selectedZone.value.id == null) {
ShowToastDialog.showToast("Please select zone".tr);
return;
}
// Fix: use OR (||) instead of AND (&&)
if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
controller.passwordEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter password".tr);
return;
} else if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
controller.passwordEditingController.value.text.length < 6) {
ShowToastDialog.showToast("Password must be at least 6 characters".tr);
return;
} else if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
controller.conformPasswordEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter confirm password".tr);
return;
} else if (controller.passwordEditingController.value.text !=
controller.conformPasswordEditingController.value.text) {
ShowToastDialog.showToast("Password and confirm password do not match".tr);
return;
}
//Vehicle validation if service is NOT Parcel Service
if (controller.selectedService.value != "Parcel Service") {
if (controller.selectedVehicleType.value.id == null) {
ShowToastDialog.showToast("Please select vehicle type".tr);
return;
} else if (controller.selectedCarMakes.value.id == null) {
ShowToastDialog.showToast("Please select car brand".tr);
return;
} else if (controller.selectedCarModel.value.id == null) {
ShowToastDialog.showToast("Please select car model".tr);
return;
} else if (controller.carPlatNumberEditingController.value.text.isEmpty) {
ShowToastDialog.showToast("Please enter car plat number".tr);
return;
} else {
//Will work now
print("plz come..............");
controller.signUp();
}
} else {
//Parcel Service signup
print("plz come signUp ..............");
controller.signUp();
}
},
child: Container(
color: AppThemeData.primary300,
width: Responsive.width(100, context),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
'Save'.tr,
textAlign: TextAlign.center,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
fontSize: 16,
fontFamily: AppThemeData.medium,
fontWeight: FontWeight.w400,
),
),
),
),
)
],
),
);
});
}
}

View File

@@ -0,0 +1,86 @@
import 'package:driver/constant/constant.dart';
import 'package:driver/controllers/driver_location_controller.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart' as flutterMap;
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class DriverLocationScreen extends StatelessWidget {
const DriverLocationScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX(
init: DriverLocationController(),
builder: (controller) {
return Scaffold(
appBar: AppBar(
title: Text(
"Driver Locations",
style: TextStyle(
color: isDark ? Colors.white : Colors.black,
),
),
backgroundColor: isDark ? Colors.black : Colors.white,
iconTheme: IconThemeData(
color: isDark ? Colors.white : Colors.black,
),
),
body: controller.isLoading.value
? Constant.loader()
: Constant.selectedMapType == "osm"
? Obx(() {
// Schedule a post-frame callback to ensure the FlutterMap has been built
// before we attempt to move the map to the driver's location.
WidgetsBinding.instance.addPostFrameCallback((_) {
try {
controller.animateToSource();
} catch (_) {}
});
return flutterMap.FlutterMap(
mapController: controller.osmMapController,
options: flutterMap.MapOptions(
// center the OSM map on the controller's current position (updated by controller)
initialCenter: controller.current.value,
initialZoom: 12,
),
children: [
flutterMap.TileLayer(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: const ['a', 'b', 'c'],
userAgentPackageName: 'com.emart.app',
),
flutterMap.MarkerLayer(markers: controller.osmMarkers),
],
);
})
: GoogleMap(
initialCameraPosition: controller.driverList.isNotEmpty
? CameraPosition(
target: LatLng(controller.driverList.first.location == null ? 12.9716 : controller.driverList.first.location!.latitude!,
controller.driverList.first.location == null ? 77.5946 : controller.driverList.first.location!.longitude!),
zoom: 14,
)
: CameraPosition(
target: LatLng(12.9716, 77.5946),
zoom: 14,
),
myLocationEnabled: true,
myLocationButtonEnabled: true,
markers: controller.markers.toSet(),
onMapCreated: (GoogleMapController mapController) {
controller.mapController.complete(mapController);
// Wait for markers to load
Future.delayed(const Duration(milliseconds: 500), () async {
await controller.moveCameraToFirstDriver(mapController);
});
},
),
);
});
}
}

View File

@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../controllers/driver_order_controller.dart';
import '../../themes/theme_controller.dart';
import '../cab_screen/cab_order_list_screen.dart';
import '../parcel_screen/parcel_order_list_screen.dart';
import '../rental_service/rental_order_list_screen.dart';
class DriverOrderList extends StatelessWidget {
const DriverOrderList({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX<DriverOrderListController>(
init: DriverOrderListController(),
builder: (controller) {
return Scaffold(
appBar: AppBar(
title: Text(
"Driver Orders".tr,
style: TextStyle(
color: isDark ? Colors.white : Colors.black,
),
),
backgroundColor: isDark ? Colors.black : Colors.white,
iconTheme: IconThemeData(
color: isDark ? Colors.white : Colors.black,
),
),
body: _buildBody(controller.serviceType.value),
);
},
);
}
Widget _buildBody(String? serviceType) {
switch (serviceType) {
case "cab-service":
return const CabOrderListScreen();
case "parcel_delivery":
return const ParcelOrderListScreen();
case "rental-service":
return const RentalOrderListScreen();
default:
return const Center(child: Text("Service type not supported"));
}
}
}

View File

@@ -0,0 +1,653 @@
import 'package:driver/app/auth_screen/login_screen.dart';
import 'package:driver/app/change%20langauge/change_language_screen.dart';
import 'package:driver/app/chat_screens/driver_inbox_screen.dart';
import 'package:driver/app/edit_profile_screen/edit_profile_screen.dart';
import 'package:driver/app/owner_screen/driver_location_screen.dart';
import 'package:driver/app/owner_screen/owner_home_screen.dart';
import 'package:driver/app/terms_and_condition/terms_and_condition_screen.dart';
import 'package:driver/app/verification_screen/verification_screen.dart';
import 'package:driver/app/wallet_screen/wallet_screen.dart';
import 'package:driver/app/withdraw_method_setup_screens/withdraw_method_setup_screen.dart';
import 'package:driver/constant/constant.dart';
import 'package:driver/constant/show_toast_dialog.dart';
import 'package:driver/controllers/owner_dashboard_controller.dart';
import 'package:driver/services/audio_player_service.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/custom_dialog_box.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:driver/utils/fire_store_utils.dart';
import 'package:driver/utils/network_image_widget.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:share_plus/share_plus.dart';
import 'owner_order_list.dart';
class OwnerDashboardScreen extends StatelessWidget {
const OwnerDashboardScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
return Obx(() {
final isDark = themeController.isDark.value;
return GetX(
init: OwnerDashboardController(),
builder: (controller) {
return Scaffold(
drawerEnableOpenDragGesture: false,
appBar: AppBar(
// backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
titleSpacing: 5,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Welcome Back 👋'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontSize: 12,
fontFamily: AppThemeData.medium,
),
),
Text(
Constant.userModel!.fullName().tr,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontSize: 14,
fontFamily: AppThemeData.semiBold,
),
)
],
),
actions: [
InkWell(
onTap: () {
Get.to(() => const DriverLocationScreen());
},
child: SvgPicture.asset("assets/icons/ic_location_pin.svg")),
const SizedBox(
width: 14,
),
Visibility(
visible: Constant.userModel?.vendorID?.isEmpty == true,
child: InkWell(
onTap: () {
Get.to(const WalletScreen(isAppBarShow: true));
},
child: SvgPicture.asset("assets/icons/ic_wallet_home.svg")),
),
const SizedBox(
width: 10,
),
InkWell(
onTap: () {
Get.to(const EditProfileScreen());
},
child: SvgPicture.asset("assets/icons/ic_user_business.svg")),
const SizedBox(
width: 10,
),
],
leading: Builder(builder: (context) {
return InkWell(
onTap: () {
Scaffold.of(context).openDrawer();
},
child: Padding(
padding: const EdgeInsets.all(8),
child: Container(
decoration: ShapeDecoration(
color: isDark ? AppThemeData.carRent600 : AppThemeData.carRent50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(120),
),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: SvgPicture.asset("assets/icons/ic_drawer_open.svg"),
)),
),
);
}),
),
drawer: const DrawerView(),
body: controller.drawerIndex.value == 0
? const OwnerHomeScreen()
: controller.drawerIndex.value == 1
? OwnerOrderListScreen()
: controller.drawerIndex.value == 2
? const WalletScreen(
isAppBarShow: false,
)
: controller.drawerIndex.value == 3
? const WithdrawMethodSetupScreen()
: controller.drawerIndex.value == 4
? const VerificationScreen()
: controller.drawerIndex.value == 5
? const DriverInboxScreen()
: controller.drawerIndex.value == 6
? const ChangeLanguageScreen()
: controller.drawerIndex.value == 7
? const TermsAndConditionScreen(type: "temsandcondition")
: const TermsAndConditionScreen(type: "privacy"),
);
},
);
});
}
}
class DrawerView extends StatelessWidget {
const DrawerView({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
return Obx(() {
var isDark = themeController.isDark.value;
return GetX(
init: OwnerDashboardController(),
builder: (controller) {
return Drawer(
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
child: Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top + 20, left: 16, right: 16),
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Row(
children: [
ClipOval(
child: NetworkImageWidget(
imageUrl: Constant.userModel == null ? "" : Constant.userModel!.profilePictureURL.toString(),
height: 55,
width: 55,
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
Constant.userModel!.fullName().tr,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontSize: 18,
fontFamily: AppThemeData.semiBold,
),
),
Text(
'${Constant.userModel!.email}'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
fontSize: 14,
fontFamily: AppThemeData.regular,
),
)
],
),
)
],
),
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'About App'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
fontSize: 12,
fontFamily: AppThemeData.medium,
),
),
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_home_add.svg",
width: 20,
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Home'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 0;
},
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_shoping_cart.svg",
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Orders'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 1;
},
),
Visibility(
visible: Constant.userModel?.vendorID?.isEmpty == true,
child: ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_wallet.svg",
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Wallet'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 2;
},
),
),
Visibility(
visible: Constant.userModel?.vendorID?.isEmpty == true,
child: ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_settings.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Withdrawal Method'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 3;
},
),
),
Constant.isOwnerVerification == true
? ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_notes.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Document Verification'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 4;
},
)
: SizedBox(),
Visibility(
visible: false,
child: ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_chat.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Inbox'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 5;
},
),
),
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'App Preferences'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
fontSize: 12,
fontFamily: AppThemeData.medium,
),
),
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_change_language.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Change Language'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 6;
},
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_light_dark.svg",
),
trailing: Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
value: controller.isDarkModeSwitch.value,
activeTrackColor: AppThemeData.primary300,
onChanged: (value) {
controller.toggleDarkMode(value);
},
),
),
dense: true,
title: Text(
'Dark Mode'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
),
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'Social'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
fontSize: 12,
fontFamily: AppThemeData.medium,
),
),
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_share.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Share app'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
Share.share(
'${'Check out eMart, your ultimate food delivery application!'.tr} \n\n${'Google Play:'.tr} ${Constant.googlePlayLink} \n\n${'App Store:'.tr} ${Constant.appStoreLink}',
subject: 'Look what I made!'.tr);
},
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_rate.svg",
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Rate the app'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
final InAppReview inAppReview = InAppReview.instance;
inAppReview.requestReview();
},
),
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'Legal'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
fontSize: 12,
fontFamily: AppThemeData.medium,
),
),
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_terms_condition.svg",
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Terms and Conditions'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 7;
},
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_privacyPolicy.svg",
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
),
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
dense: true,
title: Text(
'Privacy Policy'.tr,
style: TextStyle(
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
controller.drawerIndex.value = 8;
},
),
const SizedBox(
height: 10,
),
ListTile(
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
leading: SvgPicture.asset(
"assets/icons/ic_logout.svg",
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
),
trailing: const Icon(
Icons.keyboard_arrow_right_rounded,
size: 24,
color: AppThemeData.danger300,
),
dense: true,
title: Text(
'Log out'.tr,
style: TextStyle(
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
fontFamily: AppThemeData.semiBold,
),
),
onTap: () {
Get.back();
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogBox(
title: "Log out".tr,
descriptions: "Are you sure you want to log out? You will need to enter your credentials to log back in.".tr,
positiveString: "Log out".tr,
negativeString: "Cancel".tr,
positiveClick: () async {
await AudioPlayerService.playSound(false);
Constant.userModel!.fcmToken = "";
await FireStoreUtils.updateUser(Constant.userModel!);
await FirebaseAuth.instance.signOut();
Get.offAll(const LoginScreen());
},
negativeClick: () {
Get.back();
},
img: Image.asset(
'assets/images/ic_logout.gif',
height: 50,
width: 50,
),
);
});
},
),
const SizedBox(
height: 20,
),
InkWell(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogBox(
title: "Delete Account".tr,
descriptions: "Are you sure you want to delete your account? This action is irreversible and will permanently remove all your data.".tr,
positiveString: "Delete".tr,
negativeString: "Cancel".tr,
positiveClick: () async {
ShowToastDialog.showLoader("Please wait".tr);
await FireStoreUtils.deleteUser().then((value) {
ShowToastDialog.closeLoader();
if (value == true) {
ShowToastDialog.showToast("Account deleted successfully".tr);
Get.offAll(const LoginScreen());
} else {
ShowToastDialog.showToast("Contact Administrator".tr);
}
});
},
negativeClick: () {
Get.back();
},
img: Image.asset(
'assets/icons/delete_dialog.gif',
height: 50,
width: 50,
),
);
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SvgPicture.asset(
"assets/icons/ic_delete.svg",
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
),
const SizedBox(
width: 10,
),
Text(
'Delete Account'.tr,
style: TextStyle(
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
fontFamily: AppThemeData.semiBold,
),
)
],
),
),
const SizedBox(
height: 10,
),
Center(
child: Text(
"V : ${Constant.appVersion}",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: AppThemeData.medium,
fontSize: 14,
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
),
),
),
const SizedBox(
height: 10,
),
],
),
),
);
});
});
}
}

View File

@@ -0,0 +1,436 @@
import 'package:driver/app/owner_screen/driver_create_screen.dart';
import 'package:driver/app/owner_screen/view_all_drivers.dart';
import 'package:driver/constant/constant.dart';
import 'package:driver/controllers/owner_dashboard_controller.dart';
import 'package:driver/controllers/owner_home_controller.dart';
import 'package:driver/models/user_model.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/responsive.dart';
import 'package:driver/themes/round_button_fill.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:driver/utils/network_image_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'driver_order_list.dart';
class OwnerHomeScreen extends StatelessWidget {
const OwnerHomeScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final dashController = Get.put(OwnerDashboardController());
return Obx(() {
final isDark = themeController.isDark.value;
return GetX(
init: OwnerHomeController(),
builder: (controller) {
return Scaffold(
body: controller.isLoading.value
? Constant.loader()
: Constant.isOwnerVerification == true && Constant.userModel!.isDocumentVerify == false
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: ShapeDecoration(
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(120),
),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: SvgPicture.asset("assets/icons/ic_document.svg"),
),
),
const SizedBox(
height: 12,
),
Text(
"Document Verification in Pending".tr,
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 22, fontFamily: AppThemeData.semiBold),
),
const SizedBox(
height: 5,
),
Text(
"Your documents are being reviewed. We will notify you once the verification is complete.".tr,
textAlign: TextAlign.center,
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.bold),
),
const SizedBox(
height: 20,
),
RoundedButtonFill(
title: "View Status".tr,
width: 55,
height: 5.5,
color: AppThemeData.primary300,
textColor: AppThemeData.grey50,
onPress: () {
OwnerDashboardController dashBoardController = Get.put(OwnerDashboardController());
dashBoardController.drawerIndex.value = 4;
},
),
],
),
)
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Column(
children: [
Obx(() {
num wallet = dashController.userModel.value.walletAmount ?? 0.0;
return wallet < double.parse(Constant.ownerMinimumDepositToRideAccept)
? Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Container(
decoration: BoxDecoration(color: AppThemeData.danger50, borderRadius: BorderRadius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"You must have a minimum of ${Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept.toString())} in your wallet to receive orders to your driver"
.tr,
style: TextStyle(
color: AppThemeData.danger300,
fontSize: 14,
fontFamily: AppThemeData.semiBold,
),
),
),
),
)
: const SizedBox();
}),
SizedBox(
height: 10,
),
Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
color: AppThemeData.homePageGradiant[0],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset("assets/icons/ic_ride.svg"),
SizedBox(
height: 10,
),
Text(
controller.totalRidesAllDrivers.toString(),
textAlign: TextAlign.center,
style: AppThemeData.boldTextStyle(
fontSize: 16,
color: AppThemeData.grey900,
),
),
SizedBox(
height: 5,
),
Text(
'Total Bookings'.tr,
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: AppThemeData.grey900,
),
),
],
),
),
),
),
SizedBox(
width: 10,
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: AppThemeData.homePageGradiant[1],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset("assets/icons/ic_total_ride.svg"),
SizedBox(
height: 10,
),
Text(
'${controller.driverList.length} ',
textAlign: TextAlign.center,
style: AppThemeData.boldTextStyle(
fontSize: 16,
color: AppThemeData.grey900,
),
),
SizedBox(
height: 5,
),
Text(
'Total Drivers'.tr,
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: AppThemeData.grey900,
),
),
],
),
),
),
),
],
),
SizedBox(
height: 10,
),
Container(
width: Responsive.width(100, context),
decoration: BoxDecoration(
color: AppThemeData.homePageGradiant[2],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset("assets/icons/ic_earning.svg"),
SizedBox(
height: 10,
),
Text(
'${Constant.currencyModel!.symbol.toString()}${controller.totalEarningsAllDrivers.toStringAsFixed(2)}',
textAlign: TextAlign.center,
style: AppThemeData.boldTextStyle(
fontSize: 16,
color: AppThemeData.grey900,
),
),
SizedBox(
height: 5,
),
Text(
'Earnings'.tr,
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: AppThemeData.grey900,
),
),
],
),
),
),
SizedBox(
height: 30,
),
controller.driverList.isEmpty
? SizedBox()
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Your Available Drivers'.tr,
textAlign: TextAlign.center,
style: AppThemeData.boldTextStyle(
fontSize: 16,
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
),
),
Text(
'Real-time status and earnings summary'.tr,
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
),
),
],
),
),
InkWell(
onTap: () {
Get.to(ViewAllDriverScreen())!.then(
(value) {
controller.getDriverList();
},
);
},
child: Text(
'View all'.tr,
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, decoration: TextDecoration.underline),
),
),
],
),
SizedBox(
height: 16,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
),
),
child: ListView.builder(
// itemCount: controller.driverList.length,
// physics: NeverScrollableScrollPhysics(),
// shrinkWrap: true,
itemCount: controller.driverList.length > 5 ? 5 : controller.driverList.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
UserModel driverModel = controller.driverList[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: NetworkImageWidget(
imageUrl: driverModel.profilePictureURL.toString(),
height: 42,
width: 42,
fit: BoxFit.fill,
),
),
SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
driverModel.fullName(),
textAlign: TextAlign.center,
style: AppThemeData.semiBoldTextStyle(
fontSize: 16,
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
),
),
Text(
'${driverModel.countryCode} ${driverModel.phoneNumber}',
textAlign: TextAlign.center,
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
),
),
],
),
),
SizedBox(
width: 10,
),
RoundedButtonFill(
title: driverModel.isActive == false ? "Offline" : "Online".tr,
height: 3.5,
width: 18,
borderRadius: 10,
color: driverModel.isActive == false ? AppThemeData.danger300 : AppThemeData.success300,
textColor: AppThemeData.grey50,
onPress: () async {},
),
PopupMenuButton<String>(
padding: EdgeInsets.zero,
onSelected: (value) {
if (value == 'Edit Driver') {
Get.to(DriverCreateScreen(), arguments: {"driverModel": driverModel})!.then(
(value0) {
if (value0 == true) {
controller.getDriverList();
}
},
);
} else if (value == 'Delete Driver') {
controller.deleteDriver(driverModel.id.toString());
} else if (value == 'View All Order') {
print("driver ::::::: ${driverModel.email}");
Get.to(() => const DriverOrderList(), arguments: {
"driverId": driverModel.id,
"serviceType": driverModel.serviceType,
});
}
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
PopupMenuItem<String>(
value: 'Edit Driver',
child: Text('Edit Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
PopupMenuItem<String>(
value: 'Delete Driver',
child: Text('Delete Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
PopupMenuItem<String>(
value: 'View All Order',
child: Text('View All Order'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
],
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
icon: Icon(Icons.more_vert, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), // Three dots icon
),
],
),
);
},
),
),
],
),
SizedBox(
height: 30,
),
],
),
),
),
floatingActionButton: Constant.userModel!.isDocumentVerify == true
? ClipOval(
child: FloatingActionButton(
onPressed: () {
Get.to(DriverCreateScreen())!.then((value) {
if (value == true) {
controller.getDriverList();
}
});
},
backgroundColor: AppThemeData.primary300,
child: Icon(
Icons.add,
color: AppThemeData.grey50,
),
),
)
: SizedBox.shrink(),
);
});
});
}
}

View File

@@ -0,0 +1,669 @@
import 'package:dotted_border/dotted_border.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/constant.dart';
import '../../controllers/owner_order_list_controller.dart';
import '../../models/cab_order_model.dart';
import '../../models/rental_order_model.dart';
import '../../models/user_model.dart';
import '../../themes/app_them_data.dart';
import '../../themes/round_button_fill.dart';
import '../cab_screen/cab_order_details.dart';
import '../parcel_screen/parcel_order_details.dart';
import '../rental_service/rental_order_details_screen.dart';
import '../../themes/theme_controller.dart';
import 'package:cached_network_image/cached_network_image.dart';
class OwnerOrderListScreen extends StatelessWidget {
const OwnerOrderListScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX<OwnerOrderListController>(
init: OwnerOrderListController(),
builder: (controller) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Select Service Type", style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
const SizedBox(height: 5),
DropdownButtonFormField<String>(
initialValue: controller.selectedService.value,
style: TextStyle(
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.semiBold,
),
dropdownColor: themeController.isDark.value ? AppThemeData.grey800 : AppThemeData.grey50,
items: controller.serviceList.map((service) {
return DropdownMenuItem<String>(
value: service,
child: Text(
service,
style: TextStyle(
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
),
),
);
}).toList(),
onChanged: (value) {
controller.selectedService.value = value!;
controller.selectedDriver.value = null;
controller.isDriverSelected.value = false;
},
decoration: _dropdownDecoration(themeController.isDark.value),
),
const SizedBox(height: 16),
Text("Select Driver", style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
const SizedBox(height: 5),
Obx(() => DropdownButtonFormField<UserModel?>(
initialValue: controller.selectedDriver.value,
hint: Text("Select Driver",
style: TextStyle(
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
fontFamily: AppThemeData.semiBold,
)),
items: [
const DropdownMenuItem<UserModel?>(
value: null,
child: Text("All Drivers"),
),
...controller.filteredDrivers.map((driver) {
return DropdownMenuItem<UserModel?>(
value: driver,
child: Text(
"${driver.firstName ?? ''} ${driver.lastName ?? ''}",
style: TextStyle(
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
),
),
);
}),
],
onChanged: (UserModel? value) {
controller.selectedDriver.value = value;
},
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
decoration: _dropdownDecoration(themeController.isDark.value),
)),
const SizedBox(height: 16),
// --- Search Button ---
RoundedButtonFill(
title: "Search",
height: 5.5,
color: AppThemeData.primary300,
textColor: AppThemeData.grey50,
onPress: controller.searchOrders,
),
const SizedBox(height: 16),
Expanded(
child: Obx(() {
switch (controller.serviceKey.value) {
case 'cab-service':
return cabListView(controller, isDark);
case 'parcel_delivery':
return parcleListView(controller, isDark);
case 'rental-service':
return rentalListView(controller, isDark);
default:
return const Center(child: Text("Service type not supported"));
}
}),
)
],
),
),
);
},
);
}
InputDecoration _dropdownDecoration(bool isDark) {
return InputDecoration(
isDense: true,
filled: true,
fillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: AppThemeData.primary300, width: 1.2),
),
);
}
DefaultTabController cabListView(OwnerOrderListController controller, bool isDark) {
return DefaultTabController(
length: controller.cabTabTitles.length,
initialIndex: controller.cabTabTitles.indexOf(controller.cabSelectedTab.value),
child: Column(
children: [
// TabBar
TabBar(
onTap: (index) {
controller.cabSelectedTab(controller.cabTabTitles[index]);
},
// isScrollable: true,
indicatorColor: AppThemeData.primary300,
labelColor: AppThemeData.primary300,
dividerColor: Colors.transparent,
unselectedLabelColor: AppThemeData.primary300.withOpacity(0.60),
labelStyle: AppThemeData.boldTextStyle(fontSize: 14),
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 14),
tabs: controller.cabTabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(),
),
// Body: loader or TabBarView
Expanded(
child: controller.isLoadingCab.value
? Constant.loader()
: TabBarView(
children: controller.cabTabTitles.map((title) {
final orders = controller.getCabOrdersForTab(title);
if (orders.isEmpty) {
return Center(
child: Text(
"No orders found".tr,
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
);
}
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemCount: orders.length,
itemBuilder: (context, index) {
CabOrderModel order = orders[index];
return GestureDetector(
onTap: () {
Get.to(() => CabOrderDetails(), arguments: {"cabOrderModel": order});
},
child: Container(
margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
borderRadius: BorderRadius.circular(15),
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
Icon(Icons.stop_circle_outlined, color: Colors.green),
DottedBorder(
options: CustomPathDottedBorderOptions(
color: Colors.grey.shade400,
strokeWidth: 2,
dashPattern: [4, 4],
customPath: (size) => Path()
..moveTo(size.width / 2, 0)
..lineTo(size.width / 2, size.height),
),
child: const SizedBox(width: 20, height: 55),
),
Icon(Icons.radio_button_checked, color: Colors.red),
],
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
// Source Location Name
Expanded(
child: Text(
order.sourceLocationName.toString(),
style: AppThemeData.semiBoldTextStyle(
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 8),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: AppThemeData.warning300, width: 1),
color: AppThemeData.warning50,
),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
child: Text(
order.status.toString(),
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.warning500),
overflow: TextOverflow.ellipsis,
),
),
],
),
SizedBox(height: 15),
DottedBorder(
options: CustomPathDottedBorderOptions(
color: Colors.grey.shade400,
strokeWidth: 2,
dashPattern: [4, 4],
customPath: (size) => Path()
..moveTo(0, size.height / 2) // start from left center
..lineTo(size.width, size.height / 2), // draw to right center
),
child: const SizedBox(width: 295, height: 3),
),
SizedBox(height: 15),
Text(
order.destinationLocationName.toString(),
style: AppThemeData.semiBoldTextStyle(
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
],
),
),
],
),
),
);
},
);
}).toList(),
),
),
],
),
);
}
DefaultTabController parcleListView(OwnerOrderListController controller, bool isDark) {
return DefaultTabController(
length: controller.parcelTabTitles.length,
initialIndex: controller.parcelTabTitles.indexOf(controller.parcelSelectedTab.value),
child: Column(
children: [
// TabBar
TabBar(
onTap: (index) {
controller.parcelSelectedTab(controller.parcelTabTitles[index]);
},
indicatorColor: AppThemeData.parcelService500,
labelColor: AppThemeData.parcelService500,
dividerColor: Colors.transparent,
unselectedLabelColor: AppThemeData.grey500,
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
tabs: controller.parcelTabTitles.map((title) => Tab(child: Text(title))).toList(),
),
// Body: loader or TabBarView
Expanded(
child: controller.isLoadingParcel.value
? Constant.loader()
: TabBarView(
children: controller.parcelTabTitles.map((title) {
// filter by tab using controller helper
final orders = controller.getParcelOrdersForTab(title);
if (orders.isEmpty) {
return Center(
child: Text(
"No orders found".tr,
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
);
}
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemCount: orders.length,
itemBuilder: (context, index) {
final order = orders[index];
return GestureDetector(
onTap: () {
Get.to(() => const ParcelOrderDetails(), arguments: order);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
"Order Date:${order.isSchedule == true ? controller.formatDate(order.createdAt!) : controller.formatDate(order.senderPickupDateTime!)}",
style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400),
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
DottedBorder(
options: CustomPathDottedBorderOptions(
color: Colors.grey.shade400,
strokeWidth: 2,
dashPattern: [4, 4],
customPath: (size) => Path()
..moveTo(size.width / 2, 0)
..lineTo(size.width / 2, size.height),
),
child: const SizedBox(width: 20, height: 95),
),
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
],
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_infoSection(
"Pickup Address (Sender):".tr,
order.sender?.name ?? '',
order.sender?.address ?? '',
order.sender?.phone ?? '',
// order.senderPickupDateTime != null
// ? "Pickup Time: ${controller.formatDate(order.senderPickupDateTime!)}"
// : '',
order.status,
isDark,
),
const SizedBox(height: 16),
_infoSection(
"Delivery Address (Receiver):".tr,
order.receiver?.name ?? '',
order.receiver?.address ?? '',
order.receiver?.phone ?? '',
// order.receiverPickupDateTime != null
// ? "Delivery Time: ${controller.formatDate(order.receiverPickupDateTime!)}"
// : '',
null,
isDark,
),
],
),
),
],
),
],
),
),
);
},
);
}).toList(),
),
),
],
),
);
}
Widget _infoSection(String title, String name, String address, String phone, String? status, bool isDark) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
title,
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
if (status != null) ...[
Container(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
decoration: BoxDecoration(
color: AppThemeData.info50,
border: Border.all(color: AppThemeData.info300),
borderRadius: BorderRadius.circular(12),
),
child: Text(status, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
),
],
],
),
Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
//Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
],
);
}
DefaultTabController rentalListView(OwnerOrderListController controller, bool isDark) {
return DefaultTabController(
length: controller.rentalTabTitles.length,
initialIndex: controller.rentalTabTitles.indexOf(controller.rentalSelectedTab.value),
child: Column(
children: [
// TabBar
TabBar(
onTap: (index) {
controller.rentalSelectedTab(controller.rentalTabTitles[index]);
},
indicatorColor: AppThemeData.parcelService500,
labelColor: AppThemeData.parcelService500,
dividerColor: Colors.transparent,
unselectedLabelColor: AppThemeData.grey500,
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
tabs: controller.rentalTabTitles.map((title) => Tab(child: Text(title))).toList(),
),
// Body: loader or TabBarView
Expanded(
child: controller.isLoadingRental.value
? Constant.loader()
: TabBarView(
children: controller.rentalTabTitles.map((title) {
// filter by tab using controller helper
final orders = controller.getRentalOrdersForTab(title);
if (orders.isEmpty) {
return Center(
child: Text(
"No orders found".tr,
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
);
}
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemCount: orders.length,
itemBuilder: (context, index) {
RentalOrderModel order = orders[index]; //use this
return InkWell(
onTap: () {
Get.to(() => RentalOrderDetailsScreen(), arguments: {"rentalOrder": order.id});
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
),
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(bottom: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 5),
child: Image.asset("assets/icons/pickup.png", height: 18, width: 18)),
const SizedBox(width: 10),
Expanded(
//prevents overflow
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
//text wraps if too long
child: Text(
order.sourceLocationName ?? "-",
style: AppThemeData.semiBoldTextStyle(
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
overflow: TextOverflow.ellipsis, //safe cutoff
maxLines: 2,
),
),
if (order.status != null) ...[
const SizedBox(width: 8),
Container(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
decoration: BoxDecoration(
color: AppThemeData.info50,
border: Border.all(color: AppThemeData.info300),
borderRadius: BorderRadius.circular(12),
),
child: Text(order.status ?? '',
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
),
],
],
),
if (order.bookingDateTime != null)
Text(
Constant.timestampToDateTime(order.bookingDateTime!),
style: AppThemeData.mediumTextStyle(
fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
),
],
),
),
],
),
const SizedBox(height: 12),
Text("Vehicle Type :".tr,
style: AppThemeData.boldTextStyle(
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: CachedNetworkImage(
imageUrl: order.rentalVehicleType?.rentalVehicleIcon ?? Constant.placeHolderImage,
height: 60,
width: 60,
fit: BoxFit.cover,
placeholder: (context, url) => Center(
child: CircularProgressIndicator.adaptive(
valueColor: AlwaysStoppedAnimation(AppThemeData.primary300),
),
),
errorWidget: (context, url, error) => Image.network(
Constant.placeHolderImage,
fit: BoxFit.cover,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${order.rentalVehicleType!.name}",
style: AppThemeData.semiBoldTextStyle(
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: Text(
"${order.rentalVehicleType!.shortDescription}",
style: AppThemeData.mediumTextStyle(
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
),
),
],
),
),
),
],
),
),
Text("Package info :",
style: AppThemeData.boldTextStyle(
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
order.rentalPackageModel!.name.toString(),
style: AppThemeData.semiBoldTextStyle(
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
const SizedBox(height: 4),
Text(
order.rentalPackageModel!.description.toString(),
style: AppThemeData.mediumTextStyle(
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
),
],
),
),
SizedBox(width: 10),
Text(
Constant.amountShow(amount: order.rentalPackageModel!.baseFare.toString()),
style: AppThemeData.boldTextStyle(
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
],
),
),
],
),
),
);
},
);
}).toList(),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,127 @@
import 'package:driver/app/owner_screen/driver_create_screen.dart';
import 'package:driver/app/owner_screen/driver_order_list.dart';
import 'package:driver/controllers/owner_home_controller.dart';
import 'package:driver/themes/app_them_data.dart';
import 'package:driver/themes/round_button_fill.dart';
import 'package:driver/themes/theme_controller.dart';
import 'package:driver/utils/network_image_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class ViewAllDriverScreen extends StatelessWidget {
const ViewAllDriverScreen({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final isDark = themeController.isDark.value;
return GetX<OwnerHomeController>(
init: Get.find<OwnerHomeController>(),
builder: (controller) {
return Scaffold(
appBar: AppBar(
title: Text("All Drivers".tr),
),
body: controller.driverList.isEmpty
? Center(child: Text("No drivers found".tr))
: ListView.builder(
padding: const EdgeInsets.all(10),
itemCount: controller.driverList.length,
itemBuilder: (context, index) {
final driver = controller.driverList[index];
return Padding(
padding: const EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
),
),
padding: EdgeInsets.all(10),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: NetworkImageWidget(
imageUrl: driver.profilePictureURL ?? '',
height: 42,
width: 42,
fit: BoxFit.cover,
),
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
driver.fullName(),
style: AppThemeData.semiBoldTextStyle(
fontSize: 16,
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
),
),
Text(
'${driver.countryCode ?? ''} ${driver.phoneNumber ?? ''}',
style: AppThemeData.mediumTextStyle(
fontSize: 12,
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
),
),
],
),
),
RoundedButtonFill(
title: driver.isActive == false ? "Offline" : "Online".tr,
height: 3.5,
width: 18,
borderRadius: 10,
color: driver.isActive == false ? AppThemeData.danger300 : AppThemeData.success300,
textColor: AppThemeData.grey50,
onPress: () {},
),
PopupMenuButton<String>(
onSelected: (value) {
if (value == 'Edit Driver') {
Get.to(() => const DriverCreateScreen(), arguments: {"driverModel": driver})?.then((value0) {
if (value0 == true) controller.getDriverList();
});
} else if (value == 'Delete Driver') {
controller.deleteDriver(driver.id.toString());
} else if (value == 'View All Order') {
Get.to(() => const DriverOrderList(), arguments: {
"driverId": driver.id,
"serviceType": driver.serviceType,
});
}
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
PopupMenuItem<String>(
value: 'Edit Driver',
child: Text('Edit Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
PopupMenuItem<String>(
value: 'Delete Driver',
child: Text('Delete Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
PopupMenuItem<String>(
value: 'View All Order',
child: Text('View All Order'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
),
],
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
icon: Icon(Icons.more_vert, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
),
],
),
),
);
},
),
);
},
);
}
}