Initial commit
This commit is contained in:
336
lib/app/rental_service/rental_booking_search_screen.dart
Normal file
336
lib/app/rental_service/rental_booking_search_screen.dart
Normal file
@@ -0,0 +1,336 @@
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/rental_booking_search_controller.dart';
|
||||
import 'package:driver/models/rental_order_model.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/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
class RentalBookingSearchScreen extends StatelessWidget {
|
||||
const RentalBookingSearchScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalBookingSearchController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
titleSpacing: 0,
|
||||
centerTitle: false,
|
||||
),
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: controller.rentalBookingData.isEmpty
|
||||
? Constant.showEmptyView(message: "No Rental booking available", isDark: isDark)
|
||||
: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.rentalBookingData.length,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel rentalBookingData = controller.rentalBookingData[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(), arguments: {"rentalOrder": rentalBookingData.id});
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
ClipOval(
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: rentalBookingData.author!.profilePictureURL.toString(),
|
||||
width: 52,
|
||||
height: 52,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${rentalBookingData.author!.firstName} ${rentalBookingData.author!.lastName}'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Timeline.tileBuilder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
theme: TimelineThemeData(
|
||||
nodePosition: 0,
|
||||
// indicatorPosition: 0,
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
contentsAlign: ContentsAlign.basic,
|
||||
indicatorBuilder: (context, index) {
|
||||
return SvgPicture.asset("assets/icons/ic_location.svg");
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return DashedLineConnector(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
gap: 4,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
child: Text(
|
||||
"${rentalBookingData.sourceLocationName}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Package Details:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.name}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Distance:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedDistance} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Duration:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedHours} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_amount.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: rentalBookingData.subTotal).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_date.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(rentalBookingData.bookingDateTime!).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Reject".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
textColor: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500,
|
||||
onPress: () async {
|
||||
ShowToastDialog.showLoader("Rejecting booking...".tr);
|
||||
rentalBookingData.rejectedByDrivers!.add(FireStoreUtils.getCurrentUid());
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking rejected successfully".tr);
|
||||
controller.getRentalSearchBooking();
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Accept".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.driverModel.value.ownerId != null &&
|
||||
controller.driverModel.value.ownerId!.isNotEmpty) {
|
||||
if (controller.ownerModel.value.walletAmount != null &&
|
||||
controller.ownerModel.value.walletAmount! >=
|
||||
double.parse(Constant.minimumDepositToRideAccept)) {
|
||||
ShowToastDialog.showLoader("Accepting booking...".tr);
|
||||
rentalBookingData.status = Constant.driverAccepted;
|
||||
rentalBookingData.driverId = FireStoreUtils.getCurrentUid();
|
||||
rentalBookingData.driver = Constant.userModel;
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking accepted successfully".tr);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum ${Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)} wallet balance to accept the rental booking. Please contact your owner"
|
||||
.tr);
|
||||
}
|
||||
} else {
|
||||
if (controller.driverModel.value.walletAmount! >=
|
||||
double.parse(Constant.minimumDepositToRideAccept)) {
|
||||
ShowToastDialog.showLoader("Accepting booking...".tr);
|
||||
rentalBookingData.status = Constant.driverAccepted;
|
||||
rentalBookingData.driverId = FireStoreUtils.getCurrentUid();
|
||||
rentalBookingData.driver = Constant.userModel;
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking accepted successfully".tr);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum @amount wallet balance to accept the rental booking. Please contact your owner"
|
||||
.trParams({"amount": Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)}));
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
700
lib/app/rental_service/rental_dashboard_screen.dart
Normal file
700
lib/app/rental_service/rental_dashboard_screen.dart
Normal file
@@ -0,0 +1,700 @@
|
||||
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/rental_service/rental_home_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_order_list_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/rental_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 '../vehicle_information_screen/vehicle_information_screen.dart';
|
||||
|
||||
class RentalDashboardScreen extends StatelessWidget {
|
||||
const RentalDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalDashboardController(),
|
||||
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: [
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: 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 RentalHomeScreen()
|
||||
: controller.drawerIndex.value == 1
|
||||
? RentalOrderListScreen()
|
||||
: 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 VehicleInformationScreen()
|
||||
: controller.drawerIndex.value == 7
|
||||
? const ChangeLanguageScreen()
|
||||
: controller.drawerIndex.value == 8
|
||||
? 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: RentalDashboardController(),
|
||||
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,
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
trailing: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: CupertinoSwitch(
|
||||
value: controller.userModel.value.isActive ?? false,
|
||||
activeTrackColor: AppThemeData.primary300,
|
||||
onChanged: (value) async {
|
||||
if (Constant.isDriverVerification == true) {
|
||||
if (controller.userModel.value.isDocumentVerify == true) {
|
||||
controller.userModel.value.isActive = value;
|
||||
if (controller.userModel.value.isActive == true) {
|
||||
controller.updateCurrentLocation();
|
||||
}
|
||||
await FireStoreUtils.updateUser(controller.userModel.value);
|
||||
} else {
|
||||
ShowToastDialog.showToast("Document verification is pending. Please proceed to set up your document verification.".tr);
|
||||
}
|
||||
} else {
|
||||
controller.userModel.value.isActive = value;
|
||||
if (controller.userModel.value.isActive == true) {
|
||||
controller.updateCurrentLocation();
|
||||
}
|
||||
await FireStoreUtils.updateUser(controller.userModel.value);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Available Status'.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(
|
||||
'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;
|
||||
},
|
||||
),
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: 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;
|
||||
},
|
||||
),
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: 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.userModel?.ownerId == null || Constant.userModel!.ownerId!.isEmpty) && Constant.isDriverVerification == true) &&
|
||||
!((Constant.userModel?.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty && 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.shrink(),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: Icon(Icons.car_crash),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Vehicle Information'.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_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 = 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_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 = 8;
|
||||
},
|
||||
),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
902
lib/app/rental_service/rental_home_screen.dart
Normal file
902
lib/app/rental_service/rental_home_screen.dart
Normal file
@@ -0,0 +1,902 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:driver/app/rental_service/rental_booking_search_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/payment_list_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/send_notification.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/rental_dashboard_controller.dart';
|
||||
import 'package:driver/controllers/rental_home_controller.dart';
|
||||
import 'package:driver/models/rental_order_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/text_field_widget.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:driver/widget/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
import '../../models/user_model.dart';
|
||||
import '../chat_screens/chat_screen.dart';
|
||||
|
||||
class RentalHomeScreen extends StatelessWidget {
|
||||
const RentalHomeScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalHomeController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Constant.isDriverVerification == 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: () async {
|
||||
RentalDashboardController dashBoardController = Get.put(RentalDashboardController());
|
||||
dashBoardController.drawerIndex.value = 4;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: controller.userModel.value.isActive == false
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/empty_parcel.svg"),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'You’re Currently Offline'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
'Switch to online mode to accept and deliver rental orders.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: controller.rentalBookingData.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
final user = controller.userModel.value;
|
||||
final controllerOwner = controller.ownerModel.value;
|
||||
|
||||
final num wallet = user.walletAmount ?? 0.0;
|
||||
final num ownerWallet = controllerOwner.walletAmount ?? 0.0;
|
||||
final String? ownerId = user.ownerId;
|
||||
|
||||
final num minDeposit = double.parse(Constant.minimumDepositToRideAccept);
|
||||
|
||||
// 🧠 Logic:
|
||||
// If individual driver → check driver's own wallet
|
||||
// If owner driver → check owner's wallet
|
||||
if ((ownerId == null || ownerId.isEmpty) && wallet < minDeposit) {
|
||||
// Individual driver case
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 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 at least'.tr} ${Constant.amountShow(amount: Constant.minimumDepositToRideAccept.toString())} ${'in your wallet to receive orders'.tr}",
|
||||
style: TextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (ownerId != null && ownerId.isNotEmpty && ownerWallet < minDeposit) {
|
||||
// Owner-driver case
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.danger50,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Your owner doesn't have the minimum wallet amount to receive orders. Please contact your owner."
|
||||
.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
}),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/empty_parcel.svg"),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'No rental requests available in your selected zone.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Search Rental Booking".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () {
|
||||
Get.to(RentalBookingSearchScreen());
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(RentalBookingSearchScreen());
|
||||
},
|
||||
child: TextFieldWidget(
|
||||
hintText: 'Search new ride'.tr,
|
||||
enable: false,
|
||||
controller: null,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.getBookingData();
|
||||
},
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.rentalBookingData.length,
|
||||
padding: EdgeInsetsGeometry.zero,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel rentalBookingData = controller.rentalBookingData[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(),
|
||||
arguments: {"rentalOrder": rentalBookingData.id});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Author profile image
|
||||
ClipOval(
|
||||
child: rentalBookingData.author?.profilePictureURL != null
|
||||
? NetworkImageWidget(
|
||||
imageUrl: rentalBookingData.author!.profilePictureURL!,
|
||||
width: 52,
|
||||
height: 52,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey300,
|
||||
child: Icon(Icons.person, color: Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${rentalBookingData.author?.firstName ?? ''} ${rentalBookingData.author?.lastName ?? ''}'
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
// Phone and Chat buttons if status matches
|
||||
if (rentalBookingData.status == Constant.driverAccepted ||
|
||||
rentalBookingData.status == Constant.orderShipped)
|
||||
Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (rentalBookingData.author?.phoneNumber != null) {
|
||||
Constant.makePhoneCall(rentalBookingData.author!.phoneNumber!);
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_phone_dial.svg",
|
||||
width: 36,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(
|
||||
rentalBookingData.authorID ?? '');
|
||||
UserModel? driver = await FireStoreUtils.getUserProfile(
|
||||
rentalBookingData.driverId ?? '');
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
if (customer != null && driver != null) {
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer.fullName(),
|
||||
"restaurantName": driver.fullName(),
|
||||
"orderId": rentalBookingData.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
} else {
|
||||
ShowToastDialog.showToast("User not found");
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 42,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_wechat.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Timeline.tileBuilder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
theme: TimelineThemeData(
|
||||
nodePosition: 0,
|
||||
// indicatorPosition: 0,
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
contentsAlign: ContentsAlign.basic,
|
||||
indicatorBuilder: (context, index) {
|
||||
return SvgPicture.asset("assets/icons/ic_location.svg");
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return DashedLineConnector(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
gap: 4,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
child: Text(
|
||||
"${rentalBookingData.sourceLocationName}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Package Details:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.name}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Distance:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedDistance} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Duration:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedHours} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_amount.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: rentalBookingData.subTotal).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_date.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(rentalBookingData.bookingDateTime!).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
rentalBookingData.status == Constant.driverAccepted
|
||||
? RoundedButtonFill(
|
||||
title: "Reached Location".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
showVerifyRentalPassengerDialog(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
},
|
||||
)
|
||||
: rentalBookingData.status == Constant.orderInTransit &&
|
||||
double.parse(rentalBookingData.endKitoMetersReading.toString()) <
|
||||
double.parse(rentalBookingData.startKitoMetersReading.toString())
|
||||
? RoundedButtonFill(
|
||||
title: "Set Final kilometers".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
setFinalKilometerDialog(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
},
|
||||
)
|
||||
: rentalBookingData.paymentStatus == true
|
||||
? RoundedButtonFill(
|
||||
title: "Complete Booking".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.success500 : AppThemeData.success500,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
controller.completeParcel(rentalBookingData);
|
||||
},
|
||||
)
|
||||
: RoundedButtonFill(
|
||||
title: rentalBookingData.paymentMethod == PaymentGateway.cod.name
|
||||
? "Confirm cash payment".tr
|
||||
: "Payment Pending".tr,
|
||||
height: 5.5,
|
||||
color: rentalBookingData.paymentMethod == PaymentGateway.cod.name
|
||||
? AppThemeData.success500
|
||||
: isDark
|
||||
? AppThemeData.dangerDark300
|
||||
: AppThemeData.dangerDark300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (rentalBookingData.paymentMethod == PaymentGateway.cod.name) {
|
||||
conformCashPayment(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Please collect the payment from the customer through the app.");
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void showVerifyRentalPassengerDialog(
|
||||
BuildContext context,
|
||||
bool isDark,
|
||||
RentalHomeController controller,
|
||||
RentalOrderModel rentalBookingData,
|
||||
) {
|
||||
Rx<TextEditingController> otpController = TextEditingController().obs;
|
||||
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(90, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
Constant.enableOTPTripStartForRental == false ? "Trip Start" : "Verify Passenger".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 22,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => Get.back(),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Constant.enableOTPTripStartForRental == false
|
||||
? const SizedBox()
|
||||
: Text(
|
||||
"Enter the OTP shared by the customer to begin the trip".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey600,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
TextFieldWidget(
|
||||
controller: controller.currentKilometerController.value,
|
||||
hintText: 'Enter Current Kilometer reading'.tr,
|
||||
title: 'Current Kilometer reading'.tr,
|
||||
enable: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Constant.enableOTPTripStartForRental == false
|
||||
? const SizedBox()
|
||||
: PinCodeTextField(
|
||||
length: 4,
|
||||
appContext: context,
|
||||
keyboardType: const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
enablePinAutofill: true,
|
||||
hintCharacter: "-",
|
||||
hintStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey700,
|
||||
),
|
||||
textStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
pinTheme: PinTheme(
|
||||
fieldHeight: 50,
|
||||
fieldWidth: 50,
|
||||
inactiveFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
selectedFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
activeFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
inactiveColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
disabledColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
selectedColor: AppThemeData.primary300,
|
||||
activeColor: AppThemeData.primary300,
|
||||
shape: PinCodeFieldShape.box,
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
cursorColor: AppThemeData.primary300,
|
||||
enableActiveFill: true,
|
||||
controller: otpController.value,
|
||||
onCompleted: (v) async {},
|
||||
onChanged: (value) {},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
RoundedButtonFill(
|
||||
title: "Start Ride".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.currentKilometerController.value.text.isEmpty ||
|
||||
double.parse(controller.currentKilometerController.value.text) < 10) {
|
||||
ShowToastDialog.showToast("Please enter current kilometer reading".tr);
|
||||
return;
|
||||
}
|
||||
if (Constant.enableOTPTripStartForRental == true &&
|
||||
otpController.value.text.isEmpty &&
|
||||
otpController.value.text.length < 6) {
|
||||
ShowToastDialog.showToast("Please enter valid OTP".tr);
|
||||
return;
|
||||
}
|
||||
if (Constant.enableOTPTripStartForRental == true && rentalBookingData.otpCode != otpController.value.text.trim()) {
|
||||
ShowToastDialog.showToast("Invalid OTP".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
rentalBookingData.startKitoMetersReading = controller.currentKilometerController.value.text.trim();
|
||||
rentalBookingData.startTime = Timestamp.now();
|
||||
rentalBookingData.status = Constant.orderInTransit;
|
||||
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Ride started successfully".tr);
|
||||
controller.currentKilometerController.value.clear();
|
||||
otpController.value.clear();
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
|
||||
void setFinalKilometerDialog(BuildContext context, bool isDark, RentalHomeController controller, RentalOrderModel rentalBookingData) {
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(80, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text("Enter Kilometer Reading",
|
||||
style:
|
||||
AppThemeData.boldTextStyle(fontSize: 22, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Icon(Icons.close),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
TextFieldWidget(
|
||||
controller: controller.completeKilometerController.value,
|
||||
hintText: 'Enter Current Kilometer reading',
|
||||
title: ' Current Kilometer reading',
|
||||
inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.completeKilometerController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter current kilometer reading".tr);
|
||||
return;
|
||||
} else if (double.parse(controller.completeKilometerController.value.text.toString().trim()) <
|
||||
double.parse(rentalBookingData.startKitoMetersReading.toString())) {
|
||||
ShowToastDialog.showToast("Final kilometer reading cannot be less than starting kilometer reading".tr);
|
||||
return;
|
||||
} else {
|
||||
rentalBookingData.endKitoMetersReading = controller.completeKilometerController.value.text.toString().trim();
|
||||
rentalBookingData.endTime = Timestamp.now();
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Kilometer updated successfully".tr);
|
||||
controller.completeKilometerController.value.clear();
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
|
||||
void conformCashPayment(BuildContext context, bool isDark, RentalHomeController controller, RentalOrderModel rentalBookingData) {
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(80, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text("Confirm Cash Collection",
|
||||
style:
|
||||
AppThemeData.boldTextStyle(fontSize: 20, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
"Please confirm that you have received the full cash amount from the customer before continuing.",
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, fontSize: 14),
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
RoundedButtonFill(
|
||||
title: "Ride Completed".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
rentalBookingData.status = Constant.orderCompleted;
|
||||
rentalBookingData.paymentStatus = true;
|
||||
await controller.updateCabWalletAmount(rentalBookingData);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
Map<String, dynamic> payLoad = <String, dynamic>{"type": "rental_order", "orderId": rentalBookingData.id};
|
||||
SendNotification.sendFcmMessage(Constant.rentalCompleted, rentalBookingData.author!.fcmToken.toString(), payLoad);
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Ride completed successfully".tr);
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
650
lib/app/rental_service/rental_order_details_screen.dart
Normal file
650
lib/app/rental_service/rental_order_details_screen.dart
Normal file
@@ -0,0 +1,650 @@
|
||||
import 'package:driver/app/chat_screens/chat_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/models/user_model.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:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controllers/rental_order_details_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/responsive.dart';
|
||||
|
||||
class RentalOrderDetailsScreen extends StatelessWidget {
|
||||
const RentalOrderDetailsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalOrderDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"Order Details".tr,
|
||||
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
|
||||
? Center(child: Constant.loader())
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Booking Id : ${controller.order.value.id}",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: controller.order.value.id.toString()));
|
||||
ShowToastDialog.showToast("Booking ID copied to clipboard".tr);
|
||||
},
|
||||
child: Icon(Icons.copy),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Image.asset("assets/icons/pickup.png", height: 15, width: 15),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.sourceLocationName ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
if (controller.order.value.bookingDateTime != null)
|
||||
Text(
|
||||
Constant.timestampToDate(controller.order.value.bookingDateTime!),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
if (controller.order.value.rentalPackageModel != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Your Preference",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.name ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.description ?? "",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
Constant.amountShow(amount: controller.order.value.rentalPackageModel!.baseFare.toString()),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
if (controller.order.value.author != null)
|
||||
Column(
|
||||
children: [
|
||||
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),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("About Customer".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 52,
|
||||
height: 52,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadiusGeometry.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.userData.value?.profilePictureURL ?? '',
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.userData.value?.fullName() ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18),
|
||||
),
|
||||
Text(
|
||||
controller.userData.value?.email ?? '',
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.userData.value?.phoneNumber ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer =
|
||||
await FireStoreUtils.getUserProfile(controller.order.value.authorID.toString());
|
||||
UserModel? driver =
|
||||
await FireStoreUtils.getUserProfile(controller.order.value.driverId.toString());
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer!.fullName(),
|
||||
"restaurantName": driver!.fullName(),
|
||||
"orderId": controller.order.value.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
width: 42,
|
||||
height: 42,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_wechat.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// Visibility(
|
||||
// visible: controller.order.value?.status == Constant.orderCompleted ? true : false,
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
// child: RoundedButtonFill(
|
||||
// title: 'Add Review'.tr,
|
||||
// onPress: () async {
|
||||
// final result = await Get.to(() => RentalReviewScreen(), arguments: {'order': controller.order.value});
|
||||
//
|
||||
// // If review was submitted successfully
|
||||
// if (result == true) {
|
||||
// await controller.fetchCustomerDetails();
|
||||
// }
|
||||
// },
|
||||
// height: 5,
|
||||
// borderRadius: 15,
|
||||
// color: Colors.orange,
|
||||
// textColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
),
|
||||
if (controller.order.value.rentalVehicleType != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Vehicle Type",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.order.value.rentalVehicleType!.rentalVehicleIcon ?? "",
|
||||
height: 50,
|
||||
width: 50),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.rentalVehicleType!.name ?? "",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
Text(
|
||||
controller.order.value.rentalVehicleType!.shortDescription ?? "",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Rental Details".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Divider(color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Rental Package'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.name.toString().tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Rental Package Price'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: controller.order.value.rentalPackageModel!.baseFare.toString(),
|
||||
).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Including ${Constant.distanceType.tr}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.rentalPackageModel!.includedDistance.toString()} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Including Hours'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.rentalPackageModel!.includedHours.toString()} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Extra ${Constant.distanceType}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.getExtraKm(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Text(
|
||||
// 'Extra ${Constant.distanceType}',
|
||||
// textAlign: TextAlign.start,
|
||||
// style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// "${(double.parse(controller.order.value.endKitoMetersReading!.toString()) - double.parse(controller.order.value.startKitoMetersReading!.toString()) - double.parse(controller.order.value.rentalPackageModel!.includedDistance!.toString()))} ${Constant.distanceType}",
|
||||
// textAlign: TextAlign.start,
|
||||
// style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
controller.order.value.endTime == null
|
||||
? SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Extra Minutes'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.endTime == null ? "0" : (((controller.order.value.endTime!.toDate().difference(controller.order.value.startTime!.toDate()).inMinutes) - (int.parse(controller.order.value.rentalPackageModel!.includedHours.toString()) * 60)).clamp(0, double.infinity).toInt().toString())} Min",
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Order Summary".tr,
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_summaryTile(
|
||||
"Subtotal".tr,
|
||||
Constant.amountShow(amount: controller.subTotal.value.toString()),
|
||||
isDark,
|
||||
null,
|
||||
),
|
||||
_summaryTile(
|
||||
"Discount".tr,
|
||||
Constant.amountShow(amount: controller.discount.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.dangerDark300,
|
||||
),
|
||||
...List.generate(controller.order.value.taxSetting?.length ?? 0, (index) {
|
||||
final taxModel = controller.order.value.taxSetting![index];
|
||||
final taxTitle =
|
||||
"${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}";
|
||||
return _summaryTile(
|
||||
taxTitle,
|
||||
Constant.amountShow(
|
||||
amount: Constant.getTaxValue(
|
||||
amount: (controller.subTotal.value - controller.discount.value).toString(),
|
||||
taxModel: taxModel,
|
||||
).toString(),
|
||||
),
|
||||
isDark,
|
||||
null,
|
||||
);
|
||||
}),
|
||||
const Divider(),
|
||||
_summaryTile(
|
||||
"Order Total".tr,
|
||||
Constant.amountShow(amount: controller.totalAmount.value.toString()),
|
||||
isDark,
|
||||
null,
|
||||
),
|
||||
_summaryTile(
|
||||
"Admin Commission (${controller.order.value.adminCommission}${controller.order.value.adminCommissionType == "Percentage" || controller.order.value.adminCommissionType == "percentage" ? "%" : Constant.currencyModel!.symbol})"
|
||||
.tr,
|
||||
Constant.amountShow(amount: controller.adminCommission.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.danger300,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
controller.order.value.driver != null && controller.order.value.driver!.ownerId != null && controller.order.value.driver!.ownerId!.isNotEmpty ||
|
||||
controller.order.value.status == Constant.orderPlaced
|
||||
? SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: isDark ? AppThemeData.danger50 : AppThemeData.danger50),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Note : Admin commission will be debited from your wallet balance. \n \nAdmin commission will apply on your booking Amount minus Discount(if applicable).",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _summaryTile(String title, String value, bool isDark, Color? colors) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)),
|
||||
Text(
|
||||
value,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: title == "Order Total" ? 18 : 16, color: colors ?? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
233
lib/app/rental_service/rental_order_list_screen.dart
Normal file
233
lib/app/rental_service/rental_order_list_screen.dart
Normal file
@@ -0,0 +1,233 @@
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/rental_order_list_controller.dart';
|
||||
import '../../models/rental_order_model.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/round_button_fill.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
class RentalOrderListScreen extends StatelessWidget {
|
||||
const RentalOrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<RentalOrderListController>(
|
||||
init: RentalOrderListController(),
|
||||
builder: (controller) {
|
||||
return DefaultTabController(
|
||||
length: controller.tabTitles.length,
|
||||
initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value),
|
||||
child: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.selectTab(controller.tabTitles[index]);
|
||||
},
|
||||
indicatorColor: AppThemeData.parcelService500,
|
||||
labelColor: AppThemeData.parcelService500,
|
||||
dividerColor: isDark ? Colors.black : Colors.white,
|
||||
unselectedLabelColor: AppThemeData.grey500,
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
|
||||
tabs: controller.tabTitles.map((title) => Tab(child: Text(title))).toList(),
|
||||
),
|
||||
|
||||
// Body: loader or TabBarView
|
||||
Expanded(
|
||||
child: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: TabBarView(
|
||||
children: controller.tabTitles.map((title) {
|
||||
// filter by tab using controller helper
|
||||
final orders = controller.getOrdersForTab(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.all(16),
|
||||
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 :".tr, 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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (order.status == Constant.orderPlaced || order.status == Constant.driverAccepted) ...[
|
||||
SizedBox(height: 10),
|
||||
if (order.status == Constant.orderPlaced || order.status == Constant.driverAccepted)
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Cancel Booking".tr,
|
||||
onPress: () {
|
||||
// controller.cancelRentalRequest(order);
|
||||
},
|
||||
color: AppThemeData.danger300,
|
||||
textColor: AppThemeData.surface,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
167
lib/app/rental_service/rental_review_screen.dart
Normal file
167
lib/app/rental_service/rental_review_screen.dart
Normal file
@@ -0,0 +1,167 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/rental_review_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/round_button_fill.dart';
|
||||
import '../../themes/text_field_widget.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import '../../utils/network_image_widget.dart';
|
||||
|
||||
class RentalReviewScreen extends StatelessWidget {
|
||||
const RentalReviewScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<RentalReviewController>(
|
||||
init: RentalReviewController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
elevation: 0,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Icon(Icons.arrow_back_ios, color: isDark ? Colors.white : Colors.black),
|
||||
),
|
||||
title: Text(
|
||||
controller.ratingModel.value != null ? "Update Review".tr : "Add Review".tr,
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 16),
|
||||
),
|
||||
),
|
||||
body: Obx(
|
||||
() => controller.customerUser.value == null
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, top: 50, bottom: 20),
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 65),
|
||||
child: Column(
|
||||
children: [
|
||||
// Customer Name
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"${controller.customerUser.value?.firstName ?? ''} ${controller.customerUser.value?.lastName ?? ''}",
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black87, fontFamily: AppThemeData.medium, fontSize: 18),
|
||||
),
|
||||
),
|
||||
// Customer Email & Phone
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.customerUser.value?.email ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black87, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
controller.customerUser.value?.phoneNumber ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black38, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Divider(color: Colors.grey),
|
||||
),
|
||||
|
||||
// Title
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
child: Text(
|
||||
'How was your customer?'.tr,
|
||||
style: TextStyle(fontSize: 18, color: isDark ? Colors.white : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 1),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
"Share your feedback about the customer.".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8),
|
||||
),
|
||||
),
|
||||
|
||||
// Rating
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
'Rate the Customer'.tr,
|
||||
style: TextStyle(fontSize: 16, color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: RatingBar.builder(
|
||||
initialRating: controller.ratings.value,
|
||||
minRating: 1,
|
||||
direction: Axis.horizontal,
|
||||
allowHalfRating: true,
|
||||
itemCount: 5,
|
||||
itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber),
|
||||
unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400,
|
||||
onRatingUpdate: (rating) => controller.ratings.value = rating,
|
||||
),
|
||||
),
|
||||
|
||||
// Comment
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: TextFieldWidget(hintText: "Type comment....".tr, controller: controller.comment.value, maxLine: 5),
|
||||
),
|
||||
|
||||
// Submit
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: RoundedButtonFill(
|
||||
title: controller.ratingModel.value != null ? "Update Review".tr : "Add Review".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: isDark ? Colors.white : Colors.black,
|
||||
onPress: controller.submitReview,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.15), blurRadius: 8, spreadRadius: 6)],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
child: NetworkImageWidget(imageUrl: controller.customerUser.value?.profilePictureURL ?? '', fit: BoxFit.cover, height: 110, width: 110),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user