333 lines
19 KiB
Dart
333 lines
19 KiB
Dart
import 'package:customer/constant/constant.dart';
|
|
import 'package:customer/models/coupon_model.dart';
|
|
import 'package:customer/screen_ui/rental_service/rental_coupon_screen.dart';
|
|
import 'package:customer/themes/show_toast_dialog.dart';
|
|
import 'package:customer/utils/network_image_widget.dart';
|
|
import 'package:dotted_border/dotted_border.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import 'package:get/get.dart';
|
|
import '../../controllers/rental_conformation_controller.dart';
|
|
import '../../controllers/theme_controller.dart';
|
|
import '../../themes/app_them_data.dart';
|
|
import '../../themes/round_button_fill.dart';
|
|
|
|
class RentalConformationScreen extends StatelessWidget {
|
|
const RentalConformationScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final themeController = Get.find<ThemeController>();
|
|
final isDark = themeController.isDark.value;
|
|
return GetX(
|
|
init: RentalConformationController(),
|
|
builder: (controller) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
automaticallyImplyLeading: false,
|
|
backgroundColor: AppThemeData.primary300,
|
|
title: Padding(
|
|
padding: const EdgeInsets.only(bottom: 10),
|
|
child: Row(
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () {
|
|
Get.back();
|
|
},
|
|
child: Container(
|
|
height: 42,
|
|
width: 42,
|
|
decoration: BoxDecoration(shape: BoxShape.circle, color: AppThemeData.grey50),
|
|
child: Center(child: Padding(padding: const EdgeInsets.only(left: 5), child: Icon(Icons.arrow_back_ios, color: AppThemeData.grey900, size: 20))),
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Text("Confirm Rent a Car".tr, style: AppThemeData.boldTextStyle(fontSize: 18, color: AppThemeData.grey900)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
body:
|
|
controller.isLoading.value
|
|
? Center(child: Constant.loader())
|
|
: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 20),
|
|
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: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Image.asset("assets/icons/pickup.png", height: 15, width: 15),
|
|
SizedBox(width: 15),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"${controller.rentalOrderModel.value.sourceLocationName}",
|
|
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
|
),
|
|
Text(
|
|
Constant.timestampToDate(controller.rentalOrderModel.value.bookingDateTime!),
|
|
style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
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("Your Preference".tr, 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.rentalOrderModel.value.rentalPackageModel!.name.toString(),
|
|
style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
controller.rentalOrderModel.value.rentalPackageModel!.description.toString(),
|
|
style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(width: 10),
|
|
Text(
|
|
Constant.amountShow(amount: controller.rentalOrderModel.value.rentalPackageModel!.baseFare.toString()),
|
|
style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
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("Vehicle Type".tr, style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
|
SizedBox(height: 10),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadiusGeometry.circular(10),
|
|
child: NetworkImageWidget(imageUrl: controller.rentalOrderModel.value.rentalVehicleType!.rentalVehicleIcon.toString(), height: 50, width: 50, borderRadius: 10),
|
|
),
|
|
SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"${controller.rentalOrderModel.value.rentalVehicleType!.name}",
|
|
style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
|
),
|
|
Text(
|
|
"${controller.rentalOrderModel.value.rentalVehicleType!.shortDescription}",
|
|
style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
|
|
Row(
|
|
children: [
|
|
Expanded(child: Text("Coupons".tr, style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))),
|
|
InkWell(
|
|
onTap: () {
|
|
Get.to(RentalCouponScreen())!.then((value) {
|
|
if (value != null) {
|
|
double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: value);
|
|
if (couponAmount < controller.subTotal.value) {
|
|
controller.selectedCouponModel.value = value;
|
|
controller.calculateAmount();
|
|
} else {
|
|
ShowToastDialog.showToast("This offer not eligible for this booking".tr);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
child: Text(
|
|
"View All".tr,
|
|
style: AppThemeData.boldTextStyle(decoration: TextDecoration.underline, fontSize: 14, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 5),
|
|
|
|
// Coupon input
|
|
DottedBorder(
|
|
options: RoundedRectDottedBorderOptions(strokeWidth: 1, radius: const Radius.circular(10), color: isDark ? AppThemeData.parcelServiceDark300 : AppThemeData.primary300),
|
|
child: Container(
|
|
decoration: BoxDecoration(color: AppThemeData.parcelService50, borderRadius: BorderRadius.circular(10)),
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset("assets/icons/ic_coupon_parcel.svg", height: 28, width: 28),
|
|
SizedBox(width: 15),
|
|
Expanded(
|
|
child: TextFormField(
|
|
controller: controller.couponController.value,
|
|
style: AppThemeData.semiBoldTextStyle(color: AppThemeData.grey900),
|
|
decoration: InputDecoration(
|
|
hintText: "Write coupon code".tr,
|
|
hintStyle: AppThemeData.mediumTextStyle(fontSize: 16, color: AppThemeData.parcelService500),
|
|
border: InputBorder.none,
|
|
),
|
|
),
|
|
),
|
|
RoundedButtonFill(
|
|
title: "Redeem now".tr,
|
|
onPress: () {
|
|
if (controller.couponList.where((element) => element.code!.toLowerCase() == controller.couponController.value.text.toLowerCase()).isNotEmpty) {
|
|
CouponModel couponModel = controller.couponList.firstWhere((p0) => p0.code!.toLowerCase() == controller.couponController.value.text.toLowerCase());
|
|
if (couponModel.expiresAt!.toDate().isAfter(DateTime.now())) {
|
|
double couponAmount = Constant.calculateDiscount(amount: controller.subTotal.value.toString(), offerModel: couponModel);
|
|
if (couponAmount < controller.subTotal.value) {
|
|
controller.selectedCouponModel.value = couponModel;
|
|
controller.calculateAmount();
|
|
controller.update();
|
|
} else {
|
|
ShowToastDialog.showToast("This offer not eligible for this booking".tr);
|
|
}
|
|
} else {
|
|
ShowToastDialog.showToast("This coupon code has been expired".tr);
|
|
}
|
|
} else {
|
|
ShowToastDialog.showToast("Invalid coupon code".tr);
|
|
}
|
|
},
|
|
borderRadius: 10,
|
|
height: 4,
|
|
width: 28,
|
|
fontSizes: 14,
|
|
color: AppThemeData.primary300,
|
|
textColor: AppThemeData.grey900,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
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("Order Summary".tr, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500)),
|
|
const SizedBox(height: 8),
|
|
|
|
// Subtotal
|
|
_summaryTile("Subtotal".tr, Constant.amountShow(amount: controller.subTotal.value.toString()), isDark, null),
|
|
|
|
// Discount
|
|
_summaryTile("Discount".tr, Constant.amountShow(amount: controller.discount.value.toString()), isDark, AppThemeData.dangerDark300),
|
|
|
|
// Tax List
|
|
...List.generate(controller.rentalOrderModel.value.taxSetting!.length, (index) {
|
|
final taxModel = controller.rentalOrderModel.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: controller.rentalOrderModel.value.taxSetting![index],
|
|
).toString(),
|
|
),
|
|
isDark,
|
|
null,
|
|
);
|
|
}),
|
|
|
|
const Divider(),
|
|
|
|
// Total
|
|
_summaryTile("Order Total".tr, Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark, null),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
RoundedButtonFill(
|
|
title: "Book now".tr,
|
|
onPress: () {
|
|
controller.placeOrder();
|
|
},
|
|
color: AppThemeData.primary300,
|
|
textColor: AppThemeData.grey900,
|
|
),
|
|
SizedBox(height: 20),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
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))),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|