Initial commit
This commit is contained in:
543
lib/app/parcel_screen/parcel_home_screen.dart
Normal file
543
lib/app/parcel_screen/parcel_home_screen.dart
Normal file
@@ -0,0 +1,543 @@
|
||||
import 'package:driver/app/parcel_screen/parcel_order_details.dart';
|
||||
import 'package:driver/app/parcel_screen/parcel_search_screen.dart';
|
||||
import 'package:driver/app/parcel_screen/parcel_tracking_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/parcel_dashboard_controller.dart';
|
||||
import 'package:driver/controllers/parcel_home_controller.dart';
|
||||
import 'package:driver/models/parcel_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/network_image_widget.dart';
|
||||
import 'package:driver/widget/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
import '../../constant/show_toast_dialog.dart';
|
||||
import '../../models/user_model.dart';
|
||||
import '../../utils/fire_store_utils.dart';
|
||||
import '../chat_screens/chat_screen.dart';
|
||||
|
||||
class ParcelHomeScreen extends StatelessWidget {
|
||||
const ParcelHomeScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ParcelHomeController(),
|
||||
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 {
|
||||
ParcelDashboardController dashBoardController = Get.put(ParcelDashboardController());
|
||||
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 parcel orders.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: controller.parcelOrdersList.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();
|
||||
}
|
||||
}),
|
||||
// (double.parse(Constant.userModel!.walletAmount == null ? "0.0" : Constant.userModel!.walletAmount.toString()) <
|
||||
// double.parse(Constant.minimumDepositToRideAccept) &&
|
||||
// (Constant.userModel?.ownerId == null || Constant.userModel!.ownerId!.isEmpty))
|
||||
// ? Container(
|
||||
// decoration: BoxDecoration(color: AppThemeData.danger50, borderRadius: BorderRadius.circular(10)),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Text(
|
||||
// "${'You have to minimum'.tr} ${Constant.amountShow(amount: Constant.minimumDepositToRideAccept.toString())} ${'wallet amount to receiving Order'.tr}",
|
||||
// style: TextStyle(color: isDark ? AppThemeData.danger300 : AppThemeData.danger300, fontSize: 14, fontFamily: AppThemeData.semiBold),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// : const SizedBox(),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/empty_parcel.svg"),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'No parcel requests available in your selected zone.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
'Try changing the location or date.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Search Parcel".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () {
|
||||
Get.to(ParcelSearchScreen())!.then((value) {
|
||||
if (value != null && value is bool && value) {
|
||||
controller.getParcelList();
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 15),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.getParcelList();
|
||||
},
|
||||
child: ListView.builder(
|
||||
itemCount: controller.parcelOrdersList.length,
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
ParcelOrderModel parcelBookingData = controller.parcelOrdersList[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => const ParcelOrderDetails(), arguments: parcelBookingData);
|
||||
},
|
||||
child: Container(
|
||||
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: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: 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 index == 0
|
||||
? SvgPicture.asset("assets/icons/ic_source.svg")
|
||||
: index == 1
|
||||
? SvgPicture.asset("assets/icons/ic_destination.svg")
|
||||
: SizedBox();
|
||||
},
|
||||
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(
|
||||
index == 0
|
||||
? "${parcelBookingData.sender!.address}"
|
||||
: "${parcelBookingData.receiver!.address}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipOval(
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: parcelBookingData.author!.profilePictureURL.toString(),
|
||||
width: 52,
|
||||
height: 52,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
parcelBookingData.author!.fullName().tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer =
|
||||
await FireStoreUtils.getUserProfile(parcelBookingData.authorID.toString());
|
||||
UserModel? driver =
|
||||
await FireStoreUtils.getUserProfile(parcelBookingData.driverId.toString());
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer!.fullName(),
|
||||
"restaurantName": driver!.fullName(),
|
||||
"orderId": parcelBookingData.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
},
|
||||
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"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/icons/ic_amount.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: controller.calculateParcelTotalAmountBooking(parcelBookingData))
|
||||
.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",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
'${Constant.timestampToDate(parcelBookingData.senderPickupDateTime!)} '.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/icons/weight-line.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
'${parcelBookingData.parcelWeight}'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
parcelBookingData.status == Constant.driverAccepted
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: RoundedButtonFill(
|
||||
title: "Pickup Parcel".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.success400,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
controller.pickupParcel(parcelBookingData);
|
||||
},
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: RoundedButtonFill(
|
||||
title: "Deliver Parcel".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.success400,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
controller.completeParcel(parcelBookingData);
|
||||
},
|
||||
),
|
||||
),
|
||||
parcelBookingData.status == Constant.driverAccepted ||
|
||||
parcelBookingData.status == Constant.orderInTransit
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
RoundedButtonFill(
|
||||
title: "Parcel Track".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.success400,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
Get.to(() => ParcelTrackingScreen(),
|
||||
arguments: {'parcelOrder': parcelBookingData});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user