Files
Fondex-Driver/lib/app/parcel_screen/parcel_home_screen.dart
2025-12-08 23:25:00 +05:00

544 lines
37 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(
'Youre 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),
],
),
),
);
},
),
),
),
);
});
});
}
}