Initial commit
This commit is contained in:
678
lib/app/parcel_screen/parcel_dashboard_screen.dart
Normal file
678
lib/app/parcel_screen/parcel_dashboard_screen.dart
Normal file
@@ -0,0 +1,678 @@
|
||||
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/parcel_screen/parcel_home_screen.dart';
|
||||
import 'package:driver/app/parcel_screen/parcel_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' show ShowToastDialog;
|
||||
import 'package:driver/controllers/parcel_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';
|
||||
|
||||
|
||||
class ParcelDashboardScreen extends StatelessWidget {
|
||||
const ParcelDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ParcelDashboardController(),
|
||||
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 ParcelHomeScreen()
|
||||
: controller.drawerIndex.value == 1
|
||||
? ParcelOrderListScreen()
|
||||
: controller.drawerIndex.value == 2
|
||||
? const WalletScreen(
|
||||
isAppBarShow: false,
|
||||
)
|
||||
: controller.drawerIndex.value == 3
|
||||
? const WithdrawMethodSetupScreen()
|
||||
: controller.drawerIndex.value == 4
|
||||
? const VerificationScreen()
|
||||
: controller.drawerIndex.value == 5
|
||||
? const DriverInboxScreen()
|
||||
: controller.drawerIndex.value == 6
|
||||
? const ChangeLanguageScreen()
|
||||
: controller.drawerIndex.value == 7
|
||||
? const TermsAndConditionScreen(type: "temsandcondition")
|
||||
: const TermsAndConditionScreen(type: "privacy"),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerView extends StatelessWidget {
|
||||
const DrawerView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ParcelDashboardController(),
|
||||
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: SvgPicture.asset(
|
||||
"assets/icons/ic_chat.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Inbox'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 5;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'App Preferences'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_change_language.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Change Language'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 6;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_light_dark.svg",
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: CupertinoSwitch(
|
||||
value: controller.isDarkModeSwitch.value,
|
||||
activeTrackColor: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.toggleDarkMode(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Dark Mode'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Social'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_share.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Share app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Share.share(
|
||||
'${'Check out eMart, your ultimate food delivery application!'.tr} \n\n${'Google Play:'.tr} ${Constant.googlePlayLink} \n\n${'App Store:'.tr} ${Constant.appStoreLink}',
|
||||
subject: 'Look what I made!'.tr);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_rate.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Rate the app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
final InAppReview inAppReview = InAppReview.instance;
|
||||
inAppReview.requestReview();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Legal'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_terms_condition.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Terms and Conditions'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 7;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_privacyPolicy.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Privacy Policy'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 8;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_logout.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(
|
||||
Icons.keyboard_arrow_right_rounded,
|
||||
size: 24,
|
||||
color: AppThemeData.danger300,
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Log out'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CustomDialogBox(
|
||||
title: "Log out".tr,
|
||||
descriptions: "Are you sure you want to log out? You will need to enter your credentials to log back in.".tr,
|
||||
positiveString: "Log out".tr,
|
||||
negativeString: "Cancel".tr,
|
||||
positiveClick: () async {
|
||||
await AudioPlayerService.playSound(false);
|
||||
Constant.userModel!.fcmToken = "";
|
||||
await FireStoreUtils.updateUser(Constant.userModel!);
|
||||
await FirebaseAuth.instance.signOut();
|
||||
Get.offAll(const LoginScreen());
|
||||
},
|
||||
negativeClick: () {
|
||||
Get.back();
|
||||
},
|
||||
img: Image.asset(
|
||||
'assets/images/ic_logout.gif',
|
||||
height: 50,
|
||||
width: 50,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CustomDialogBox(
|
||||
title: "Delete Account".tr,
|
||||
descriptions: "Are you sure you want to delete your account? This action is irreversible and will permanently remove all your data.".tr,
|
||||
positiveString: "Delete".tr,
|
||||
negativeString: "Cancel".tr,
|
||||
positiveClick: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
await FireStoreUtils.deleteUser().then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
if (value == true) {
|
||||
ShowToastDialog.showToast("Account deleted successfully".tr);
|
||||
Get.offAll(const LoginScreen());
|
||||
} else {
|
||||
ShowToastDialog.showToast("Contact Administrator".tr);
|
||||
}
|
||||
});
|
||||
},
|
||||
negativeClick: () {
|
||||
Get.back();
|
||||
},
|
||||
img: Image.asset(
|
||||
'assets/icons/delete_dialog.gif',
|
||||
height: 50,
|
||||
width: 50,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/icons/ic_delete.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
'Delete Account'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
"V : ${Constant.appVersion}",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
407
lib/app/parcel_screen/parcel_order_details.dart
Normal file
407
lib/app/parcel_screen/parcel_order_details.dart
Normal file
@@ -0,0 +1,407 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/parcel_order_details_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import '../../utils/network_image_widget.dart';
|
||||
|
||||
class ParcelOrderDetails extends StatelessWidget {
|
||||
const ParcelOrderDetails({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ParcelOrderDetailsController(),
|
||||
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
|
||||
? Constant.loader()
|
||||
: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"${'Order Id:'.tr} ${Constant.orderId(orderId: controller.parcelOrder.value.id.toString())}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
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: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Timeline with icons and line
|
||||
Column(
|
||||
children: [
|
||||
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
|
||||
DottedBorder(
|
||||
options: CustomPathDottedBorderOptions(
|
||||
color: Colors.grey.shade400,
|
||||
strokeWidth: 2,
|
||||
dashPattern: [4, 4],
|
||||
customPath: (size) => Path()
|
||||
..moveTo(size.width / 2, 0)
|
||||
..lineTo(size.width / 2, size.height),
|
||||
),
|
||||
child: const SizedBox(width: 20, height: 95),
|
||||
),
|
||||
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// Address Details
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_infoSection(
|
||||
"Pickup Address (Sender):".tr,
|
||||
controller.parcelOrder.value.sender?.name ?? '',
|
||||
controller.parcelOrder.value.sender?.address ?? '',
|
||||
controller.parcelOrder.value.sender?.phone ?? '',
|
||||
// controller.parcelOrder.value.senderPickupDateTime != null
|
||||
// ? "Pickup Time: ${controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}"
|
||||
// : '',
|
||||
isDark,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_infoSection(
|
||||
"Delivery Address (Receiver):".tr,
|
||||
controller.parcelOrder.value.receiver?.name ?? '',
|
||||
controller.parcelOrder.value.receiver?.address ?? '',
|
||||
controller.parcelOrder.value.receiver?.phone ?? '',
|
||||
// controller.parcelOrder.value.receiverPickupDateTime != null
|
||||
// ? "Delivery Time: ${controller.formatDate(controller.parcelOrder.value.receiverPickupDateTime!)}"
|
||||
// : '',
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
if (controller.parcelOrder.value.isSchedule == true)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
"Schedule Pickup time: ${controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}".tr,
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
"Order Date:${controller.parcelOrder.value.isSchedule == true ? controller.formatDate(controller.parcelOrder.value.createdAt!) : controller.formatDate(controller.parcelOrder.value.senderPickupDateTime!)}".tr,
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Parcel Type:".tr,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
controller.parcelOrder.value.parcelType ?? '',
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
if (controller.getSelectedCategory()?.image != null &&
|
||||
controller.getSelectedCategory()!.image!.isNotEmpty)
|
||||
NetworkImageWidget(imageUrl: controller.getSelectedCategory()?.image ?? '', height: 20, width: 20),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
controller.parcelOrder.value.parcelImages == null || controller.parcelOrder.value.parcelImages!.isEmpty
|
||||
? SizedBox()
|
||||
: SizedBox(
|
||||
height: 120,
|
||||
child: ListView.builder(
|
||||
itemCount: controller.parcelOrder.value.parcelImages!.length,
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.parcelOrder.value.parcelImages![index],
|
||||
width: 100,
|
||||
fit: BoxFit.cover,
|
||||
borderRadius: 10,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// Distance, Weight, Rate
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_iconTile(
|
||||
"${controller.parcelOrder.value.distance ?? '--'} ${Constant.distanceType}",
|
||||
"Distance".tr,
|
||||
"assets/icons/ic_distance_parcel.svg",
|
||||
isDark,
|
||||
),
|
||||
_iconTile(
|
||||
controller.parcelOrder.value.parcelWeight ?? '--',
|
||||
"Weight".tr,
|
||||
"assets/icons/ic_weight_parcel.svg",
|
||||
isDark,
|
||||
),
|
||||
_iconTile(
|
||||
Constant.amountShow(amount: controller.parcelOrder.value.subTotal),
|
||||
"Rate".tr,
|
||||
"assets/icons/ic_rate_parcel.svg",
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
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.center,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 52,
|
||||
height: 52,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadiusGeometry.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.parcelOrder.value.author?.profilePictureURL ?? '',
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 35),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Text(
|
||||
controller.parcelOrder.value.author?.fullName() ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
),
|
||||
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, null),
|
||||
|
||||
// Tax List
|
||||
...List.generate(controller.parcelOrder.value.taxSetting!.length, (index) {
|
||||
return _summaryTile(
|
||||
"${controller.parcelOrder.value.taxSetting![index].title} ${controller.parcelOrder.value.taxSetting![index].type == 'fix' ? '' : '(${controller.parcelOrder.value.taxSetting![index].tax}%)'}",
|
||||
Constant.amountShow(
|
||||
amount: Constant.getTaxValue(
|
||||
amount: ((double.tryParse(controller.parcelOrder.value.subTotal.toString()) ?? 0.0) -
|
||||
(double.tryParse(controller.parcelOrder.value.discount.toString()) ?? 0.0))
|
||||
.toString(),
|
||||
taxModel: controller.parcelOrder.value.taxSetting![index],
|
||||
).toString(),
|
||||
),
|
||||
isDark,
|
||||
null);
|
||||
}),
|
||||
|
||||
const Divider(),
|
||||
|
||||
// Total
|
||||
_summaryTile(
|
||||
"Order Total".tr, Constant.amountShow(amount: controller.totalAmount.value.toString()), isDark, null),
|
||||
_summaryTile(
|
||||
"Admin Commission (${controller.parcelOrder.value.adminCommission}${controller.parcelOrder.value.adminCommissionType == "Percentage" || controller.parcelOrder.value.adminCommissionType == "percentage" ? "%" : Constant.currencyModel!.symbol})"
|
||||
.tr,
|
||||
Constant.amountShow(amount: controller.adminCommission.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.danger300,
|
||||
),
|
||||
|
||||
// controller.parcelOrder.value.driver?.ownerId != null &&
|
||||
// controller.parcelOrder.value.driver?.ownerId.isNotEmpty ||
|
||||
// controller.parcelOrder.value.status == Constant.orderPlaced
|
||||
((controller.parcelOrder.value.driver?.ownerId != null &&
|
||||
(controller.parcelOrder.value.driver?.ownerId?.isNotEmpty ?? false)) ||
|
||||
controller.parcelOrder.value.status == Constant.orderPlaced)
|
||||
? SizedBox()
|
||||
: 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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _infoSection(String title, String name, String address, String phone, bool isDark) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
//Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _iconTile(String value, title, icon, bool isDark) {
|
||||
return Column(
|
||||
children: [
|
||||
// Icon(icon, color: AppThemeData.primary300),
|
||||
SvgPicture.asset(icon, height: 28, width: 28, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800),
|
||||
const SizedBox(height: 6),
|
||||
Text(value, style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)),
|
||||
const SizedBox(height: 6),
|
||||
Text(title, style: AppThemeData.semiBoldTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
193
lib/app/parcel_screen/parcel_order_list_screen.dart
Normal file
193
lib/app/parcel_screen/parcel_order_list_screen.dart
Normal file
@@ -0,0 +1,193 @@
|
||||
import 'package:driver/app/parcel_screen/parcel_order_details.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/parcel_order_list_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
|
||||
class ParcelOrderListScreen extends StatelessWidget {
|
||||
const ParcelOrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX<ParcelOrderListController>(
|
||||
init: ParcelOrderListController(),
|
||||
builder: (controller) {
|
||||
return DefaultTabController(
|
||||
length: controller.tabTitles.length,
|
||||
initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value),
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.selectTab(controller.tabTitles[index]);
|
||||
},
|
||||
indicatorColor: AppThemeData.parcelService500,
|
||||
labelColor: AppThemeData.parcelService500,
|
||||
dividerColor: Colors.transparent,
|
||||
unselectedLabelColor: AppThemeData.grey500,
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
|
||||
tabs: controller.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) {
|
||||
final order = orders[index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => const ParcelOrderDetails(), arguments: order);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
"Order Date:${order.isSchedule == true ? controller.formatDate(order.createdAt!) : controller.formatDate(order.senderPickupDateTime!)}",
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
|
||||
DottedBorder(
|
||||
options: CustomPathDottedBorderOptions(
|
||||
color: Colors.grey.shade400,
|
||||
strokeWidth: 2,
|
||||
dashPattern: [4, 4],
|
||||
customPath: (size) => Path()
|
||||
..moveTo(size.width / 2, 0)
|
||||
..lineTo(size.width / 2, size.height),
|
||||
),
|
||||
child: const SizedBox(width: 20, height: 95),
|
||||
),
|
||||
Image.asset("assets/images/image_parcel.png", height: 32, width: 32),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_infoSection(
|
||||
"Pickup Address (Sender):".tr,
|
||||
order.sender?.name ?? '',
|
||||
order.sender?.address ?? '',
|
||||
order.sender?.phone ?? '',
|
||||
// order.senderPickupDateTime != null
|
||||
// ? "Pickup Time: ${controller.formatDate(order.senderPickupDateTime!)}"
|
||||
// : '',
|
||||
order.status,
|
||||
isDark,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_infoSection(
|
||||
"Delivery Address (Receiver):".tr,
|
||||
order.receiver?.name ?? '',
|
||||
order.receiver?.address ?? '',
|
||||
order.receiver?.phone ?? '',
|
||||
// order.receiverPickupDateTime != null
|
||||
// ? "Delivery Time: ${controller.formatDate(order.receiverPickupDateTime!)}"
|
||||
// : '',
|
||||
null,
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _infoSection(String title, String name, String address, String phone, String? status, bool isDark) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (status != null) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.info50,
|
||||
border: Border.all(color: AppThemeData.info300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(status, style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
Text(name, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(address, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Text(phone, style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
//Text(time, style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
447
lib/app/parcel_screen/parcel_search_screen.dart
Normal file
447
lib/app/parcel_screen/parcel_search_screen.dart
Normal file
@@ -0,0 +1,447 @@
|
||||
import 'package:driver/app/parcel_screen/parcel_order_details.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/parcel_search_controller.dart';
|
||||
import 'package:driver/models/parcel_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/network_image_widget.dart';
|
||||
import 'package:driver/widget/dotted_line.dart';
|
||||
import 'package:driver/widget/osm_map/map_picker_page.dart';
|
||||
import 'package:driver/widget/osm_map/place_model.dart';
|
||||
import 'package:driver/widget/place_picker/location_picker_screen.dart';
|
||||
import 'package:driver/widget/place_picker/selected_location_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart' as latlong;
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
class ParcelSearchScreen extends StatelessWidget {
|
||||
const ParcelSearchScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ParcelSearchController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
iconTheme: IconThemeData(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, size: 20),
|
||||
title: Text(
|
||||
"Search parcel".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
readOnly: true,
|
||||
controller: controller.sourceTextEditController.value,
|
||||
onClick: () async {
|
||||
if (Constant.selectedMapType == 'osm') {
|
||||
PlaceModel? result = await Get.to(() => MapPickerPage());
|
||||
if (result != null) {
|
||||
controller.sourceTextEditController.value.text = '';
|
||||
final firstPlace = result;
|
||||
final lat = firstPlace.coordinates.latitude;
|
||||
final lng = firstPlace.coordinates.longitude;
|
||||
|
||||
controller.sourceTextEditController.value.text = result.address.toString();
|
||||
controller.departureLatLongOsm.value = latlong.LatLng(lat, lng);
|
||||
}
|
||||
} else {
|
||||
Get.to(LocationPickerScreen())!.then((value) async {
|
||||
if (value != null) {
|
||||
SelectedLocationModel selectedLocationModel = value;
|
||||
|
||||
final place = selectedLocationModel.address;
|
||||
|
||||
// ✅ Build full readable address from Placemark fields
|
||||
controller.sourceTextEditController.value
|
||||
.text = '${place?.name ?? ''}, ${place?.street ?? ''}, ${place?.subLocality ?? ''}, '
|
||||
'${place?.locality ?? ''}, ${place?.administrativeArea ?? ''}, ${place?.postalCode ?? ''}, ${place?.country ?? ''}'
|
||||
.replaceAll(RegExp(r', ,|, , ,'), ',')
|
||||
.trim()
|
||||
.replaceAll(RegExp(r',+$'), '');
|
||||
|
||||
controller.departureLatLong.value = latlong.LatLng(
|
||||
selectedLocationModel.latLng!.latitude,
|
||||
selectedLocationModel.latLng!.longitude,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
hintText: 'Where you want to go?',
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SvgPicture.asset("assets/icons/ic_source.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
readOnly: true,
|
||||
controller: controller.destinationTextEditController.value,
|
||||
onClick: () async {
|
||||
if (Constant.selectedMapType == 'osm') {
|
||||
PlaceModel? result = await Get.to(() => MapPickerPage());
|
||||
if (result != null) {
|
||||
controller.destinationTextEditController.value.text = '';
|
||||
final firstPlace = result;
|
||||
final lat = firstPlace.coordinates.latitude;
|
||||
final lng = firstPlace.coordinates.longitude;
|
||||
// ignore: unused_local_variable
|
||||
final address = firstPlace.address;
|
||||
controller.destinationTextEditController.value.text = result.address.toString();
|
||||
controller.destinationLatLongOsm.value = latlong.LatLng(lat, lng);
|
||||
}
|
||||
} else {
|
||||
Get.to(LocationPickerScreen())!.then(
|
||||
(value) async {
|
||||
if (value != null) {
|
||||
SelectedLocationModel selectedLocationModel = value;
|
||||
final place = selectedLocationModel.address;
|
||||
|
||||
controller.destinationTextEditController.value
|
||||
.text = '${place?.name ?? ''}, ${place?.street ?? ''}, ${place?.subLocality ?? ''}, '
|
||||
'${place?.locality ?? ''}, ${place?.administrativeArea ?? ''}, ${place?.postalCode ?? ''}, ${place?.country ?? ''}'
|
||||
.replaceAll(RegExp(r', ,|, , ,'), ',')
|
||||
.trim()
|
||||
.replaceAll(RegExp(r',+$'), '');
|
||||
|
||||
controller.destinationLatLong.value = latlong.LatLng(
|
||||
selectedLocationModel.latLng!.latitude,
|
||||
selectedLocationModel.latLng!.longitude,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
hintText: 'Where to?',
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SvgPicture.asset("assets/icons/ic_destination.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextFieldWidget(
|
||||
controller: controller.dateTimeTextEditController.value,
|
||||
hintText: 'Select Date',
|
||||
readOnly: true,
|
||||
onClick: () async {
|
||||
controller.pickDateTime();
|
||||
},
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SvgPicture.asset("assets/images/ic_data.svg"),
|
||||
),
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Search Parcel".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
FocusScope.of(context).unfocus();
|
||||
controller.searchParcel();
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: controller.parcelList.isEmpty
|
||||
? Constant.showEmptyView(message: "Parcel Booking not found".tr, isDark: isDark)
|
||||
: ListView.builder(
|
||||
itemCount: controller.parcelList.length,
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemBuilder: (context, index) {
|
||||
ParcelOrderModel parcelBookingData = controller.parcelList[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => const ParcelOrderDetails(), arguments: parcelBookingData);
|
||||
},
|
||||
child: Container(
|
||||
width: Responsive.width(100, context),
|
||||
margin: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
shadows: [
|
||||
BoxShadow(
|
||||
color: isDark ? AppThemeData.greyDark200 : Color(0x14000000),
|
||||
blurRadius: 23,
|
||||
offset: Offset(0, 0),
|
||||
spreadRadius: 0,
|
||||
)
|
||||
],
|
||||
),
|
||||
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),
|
||||
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(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
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),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Parcel Type:".tr,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
parcelBookingData.parcelType ?? '',
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
if (controller.getSelectedCategory(parcelBookingData)?.image != null &&
|
||||
controller.getSelectedCategory(parcelBookingData)!.image!.isNotEmpty)
|
||||
NetworkImageWidget(
|
||||
imageUrl: controller.getSelectedCategory(parcelBookingData)?.image ?? '',
|
||||
height: 20,
|
||||
width: 20),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (parcelBookingData.isSchedule == true)
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (parcelBookingData.isSchedule == true)
|
||||
Text(
|
||||
"Schedule Pickup time: ${controller.formatDate(parcelBookingData.senderPickupDateTime!)}",
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: AppThemeData.info400),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
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.ownerMinimumDepositToRideAccept)) {
|
||||
controller.acceptParcelBooking(parcelBookingData);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum {amount} wallet balance to accept the parcel booking. Please contact your owner"
|
||||
.trParams({"amount": Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)}).tr);
|
||||
}
|
||||
} else {
|
||||
if (controller.driverModel.value.walletAmount != null &&
|
||||
controller.driverModel.value.walletAmount! >=
|
||||
double.parse(Constant.minimumDepositToRideAccept)) {
|
||||
controller.acceptParcelBooking(parcelBookingData);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum {amount} wallet balance to accept the parcel booking. Please contact your owner"
|
||||
.trParams({"amount": Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)}).tr);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
97
lib/app/parcel_screen/parcel_tracking_screen.dart
Normal file
97
lib/app/parcel_screen/parcel_tracking_screen.dart
Normal file
@@ -0,0 +1,97 @@
|
||||
import 'dart:io';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart' as flutterMap;
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:latlong2/latlong.dart' as location;
|
||||
import '../../controllers/parcel_tracking_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
|
||||
class ParcelTrackingScreen extends StatelessWidget {
|
||||
const ParcelTrackingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX<ParcelTrackingController>(
|
||||
init: ParcelTrackingController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 2,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
title: Text("Map view".tr),
|
||||
leading: InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.arrow_back,
|
||||
)),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Constant.selectedMapType == 'osm'
|
||||
? flutterMap.FlutterMap(
|
||||
mapController: controller.osmMapController,
|
||||
options: flutterMap.MapOptions(
|
||||
initialCenter: location.LatLng(
|
||||
Constant.userModel?.location?.latitude ?? 45.521563,
|
||||
Constant.userModel?.location?.longitude ??
|
||||
-122.677433),
|
||||
initialZoom: 10,
|
||||
),
|
||||
children: [
|
||||
flutterMap.TileLayer(
|
||||
urlTemplate:
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
userAgentPackageName: Platform.isAndroid
|
||||
? 'felix.fondex.driver'
|
||||
: 'felix.fondex.driver',
|
||||
),
|
||||
flutterMap.MarkerLayer(markers: controller.osmMarkers),
|
||||
if (controller.routePoints.isNotEmpty)
|
||||
flutterMap.PolylineLayer(
|
||||
polylines: [
|
||||
flutterMap.Polyline(
|
||||
points: controller.routePoints,
|
||||
strokeWidth: 5.0,
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: Obx(
|
||||
() => GoogleMap(
|
||||
myLocationEnabled: true,
|
||||
myLocationButtonEnabled: true,
|
||||
mapType: MapType.terrain,
|
||||
zoomControlsEnabled: false,
|
||||
polylines:
|
||||
Set<Polyline>.of(controller.polyLines.values),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 22.0,
|
||||
),
|
||||
markers: Set<Marker>.of(controller.markers.values),
|
||||
onMapCreated: (GoogleMapController mapController) {
|
||||
controller.mapController = mapController;
|
||||
},
|
||||
initialCameraPosition: CameraPosition(
|
||||
zoom: 15,
|
||||
target: LatLng(
|
||||
Constant.userModel?.location?.latitude ?? 45.521563,
|
||||
Constant.userModel?.location?.longitude ??
|
||||
-122.677433,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user