Initial commit
This commit is contained in:
252
lib/app/auth_screen/login_screen.dart
Normal file
252
lib/app/auth_screen/login_screen.dart
Normal file
@@ -0,0 +1,252 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:driver/app/auth_screen/phone_number_screen.dart';
|
||||
import 'package:driver/app/auth_screen/signup_screen.dart';
|
||||
import 'package:driver/app/forgot_password_screen/forgot_password_screen.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/login_controller.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:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: LoginController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Log In to Your Account".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
Text(
|
||||
"Sign in to access your eMart account and manage your deliveries seamlessly.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "Didn’t Have an account?".tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 10,
|
||||
)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.to(const SignupScreen());
|
||||
},
|
||||
text: 'Sign up'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Email Address'.tr,
|
||||
controller: controller.emailEditingController.value,
|
||||
hintText: 'Enter email address'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_mail.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Password'.tr,
|
||||
controller: controller.passwordEditingController.value,
|
||||
hintText: 'Enter password'.tr,
|
||||
obscureText: controller.passwordVisible.value,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_lock.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
suffix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.passwordVisible.value = !controller.passwordVisible.value;
|
||||
},
|
||||
child: controller.passwordVisible.value
|
||||
? SvgPicture.asset(
|
||||
"assets/icons/ic_password_show.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
"assets/icons/ic_password_close.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)),
|
||||
),
|
||||
textInputAction: TextInputAction.done,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(const ForgotPasswordScreen());
|
||||
},
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
"Forgot Password".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: Platform.isAndroid ? 10 : 30, horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RoundedButtonFill(
|
||||
title: "Continue with Mobile Number".tr,
|
||||
textColor: isDark ? AppThemeData.grey100 : AppThemeData.grey900,
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey100,
|
||||
icon: SvgPicture.asset(
|
||||
"assets/icons/ic_phone.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.grey900, BlendMode.srcIn),
|
||||
),
|
||||
isRight: false,
|
||||
onPress: () async {
|
||||
Get.to(const PhoneNumberScreen());
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "with Google".tr,
|
||||
textColor: isDark ? AppThemeData.grey100 : AppThemeData.grey900,
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey100,
|
||||
icon: SvgPicture.asset("assets/icons/ic_google.svg"),
|
||||
isRight: false,
|
||||
onPress: () async {
|
||||
controller.loginWithGoogle();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Platform.isIOS
|
||||
? Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "with Apple".tr,
|
||||
textColor: isDark ? AppThemeData.grey100 : AppThemeData.grey900,
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey100,
|
||||
icon: SvgPicture.asset("assets/icons/ic_apple.svg"),
|
||||
isRight: false,
|
||||
onPress: () async {
|
||||
controller.loginWithApple();
|
||||
},
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (controller.emailEditingController.value.text.trim().isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter valid email".tr);
|
||||
} else if (controller.passwordEditingController.value.text.trim().isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter valid password".tr);
|
||||
} else {
|
||||
controller.loginWithEmailAndPassword();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
height: Responsive.width(16, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Log in".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
271
lib/app/auth_screen/otp_screen.dart
Normal file
271
lib/app/auth_screen/otp_screen.dart
Normal file
@@ -0,0 +1,271 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:driver/app/auth_screen/login_screen.dart';
|
||||
import 'package:driver/app/auth_screen/signup_screen.dart';
|
||||
import 'package:driver/app/cab_screen/cab_dashboard_screen.dart';
|
||||
import 'package:driver/app/dash_board_screen/dash_board_screen.dart';
|
||||
import 'package:driver/app/owner_screen/owner_dashboard_screen.dart';
|
||||
import 'package:driver/app/parcel_screen/parcel_dashboard_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_dashboard_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/otp_controller.dart';
|
||||
import 'package:driver/models/user_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/notification_service.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
|
||||
class OtpScreen extends StatelessWidget {
|
||||
const OtpScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX<OtpController>(
|
||||
init: OtpController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Verify Your Mobile Number".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
Text(
|
||||
"Enter the OTP sent to your mobile number to verify and secure your account.".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey200 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 60,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: PinCodeTextField(
|
||||
length: 6,
|
||||
appContext: context,
|
||||
keyboardType: TextInputType.phone,
|
||||
enablePinAutofill: true,
|
||||
hintCharacter: "-",
|
||||
hintStyle: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular),
|
||||
textStyle: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.regular),
|
||||
pinTheme: PinTheme(
|
||||
fieldHeight: 50,
|
||||
fieldWidth: 50,
|
||||
inactiveFillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
selectedFillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
activeFillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
selectedColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
inactiveColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
disabledColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: PinCodeFieldShape.box,
|
||||
errorBorderColor: isDark ? AppThemeData.grey600 : AppThemeData.grey300,
|
||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
cursorColor: AppThemeData.primary300,
|
||||
enableActiveFill: true,
|
||||
controller: controller.otpController.value,
|
||||
onCompleted: (v) async {},
|
||||
onChanged: (value) {},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
Center(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
text: "${'Did’t receive any code? '.tr} ",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
controller.otpController.value.clear();
|
||||
controller.sendOTP();
|
||||
},
|
||||
text: 'Send Again'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.medium,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: Platform.isAndroid ? 10 : 30),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Already Have an account?'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 10,
|
||||
)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.offAll(const LoginScreen());
|
||||
},
|
||||
text: 'Log in'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
if (controller.otpController.value.text.length == 6) {
|
||||
ShowToastDialog.showLoader("Verify otp".tr);
|
||||
|
||||
PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: controller.verificationId.value, smsCode: controller.otpController.value.text);
|
||||
String fcmToken = await NotificationService.getToken();
|
||||
await FirebaseAuth.instance.signInWithCredential(credential).then((value) async {
|
||||
if (value.additionalUserInfo!.isNewUser) {
|
||||
UserModel userModel = UserModel();
|
||||
userModel.id = value.user!.uid;
|
||||
userModel.countryCode = controller.countryCode.value;
|
||||
userModel.phoneNumber = controller.phoneNumber.value;
|
||||
userModel.fcmToken = fcmToken;
|
||||
userModel.provider = 'phone';
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
Get.off(const SignupScreen(), arguments: {
|
||||
"userModel": userModel,
|
||||
"type": "mobileNumber",
|
||||
});
|
||||
} else {
|
||||
await FireStoreUtils.userExistOrNot(value.user!.uid).then((userExit) async {
|
||||
ShowToastDialog.closeLoader();
|
||||
if (userExit == true) {
|
||||
UserModel? userModel = await FireStoreUtils.getUserProfile(value.user!.uid);
|
||||
if (userModel!.role == Constant.userRoleDriver) {
|
||||
if (userModel.active == true) {
|
||||
userModel.fcmToken = await NotificationService.getToken();
|
||||
await FireStoreUtils.updateUser(userModel);
|
||||
if (userModel.isOwner == true) {
|
||||
Get.offAll(OwnerDashboardScreen());
|
||||
} else {
|
||||
if (userModel.serviceType == "delivery-service") {
|
||||
Get.offAll(const DashBoardScreen());
|
||||
} else if (userModel.serviceType == "cab-service") {
|
||||
Get.offAll(const CabDashboardScreen());
|
||||
} else if (userModel.serviceType == "parcel_delivery") {
|
||||
Get.offAll(const ParcelDashboardScreen());
|
||||
} else if (userModel.serviceType == "rental-service") {
|
||||
Get.offAll(const RentalDashboardScreen());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ShowToastDialog.showToast("This user is disable please contact to administrator".tr);
|
||||
await FirebaseAuth.instance.signOut();
|
||||
Get.offAll(const LoginScreen());
|
||||
}
|
||||
} else {
|
||||
await FirebaseAuth.instance.signOut();
|
||||
Get.offAll(const LoginScreen());
|
||||
ShowToastDialog.showToast("Account already created in other application. You are not able login this application.".tr);
|
||||
}
|
||||
} else {
|
||||
UserModel userModel = UserModel();
|
||||
userModel.id = value.user!.uid;
|
||||
userModel.countryCode = controller.countryCode.value;
|
||||
userModel.phoneNumber = controller.phoneNumber.value;
|
||||
userModel.fcmToken = fcmToken;
|
||||
userModel.provider = 'phone';
|
||||
|
||||
Get.off(const SignupScreen(), arguments: {
|
||||
"userModel": userModel,
|
||||
"type": "mobileNumber",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catchError((error) {
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Invalid Code".tr);
|
||||
});
|
||||
} else {
|
||||
ShowToastDialog.showToast("Enter Valid otp".tr);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Send Code".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
177
lib/app/auth_screen/phone_number_screen.dart
Normal file
177
lib/app/auth_screen/phone_number_screen.dart
Normal file
@@ -0,0 +1,177 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:driver/app/auth_screen/login_screen.dart';
|
||||
import 'package:driver/app/auth_screen/signup_screen.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/phone_number_controller.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../constant/constant.dart';
|
||||
|
||||
class PhoneNumberScreen extends StatelessWidget {
|
||||
const PhoneNumberScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: PhoneNumberController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Log In Using Your Mobile Number".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
Text(
|
||||
"Enter your mobile number to quickly access your account and start managing your deliveries.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Didn’t Have an account?'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 10,
|
||||
)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.to(const SignupScreen());
|
||||
},
|
||||
text: 'Sign up'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Phone Number'.tr,
|
||||
controller: controller.phoneNUmberEditingController.value,
|
||||
hintText: 'Enter Phone Number'.tr,
|
||||
textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
prefix: CountryCodePicker(
|
||||
onChanged: (value) {
|
||||
controller.countryCodeEditingController.value.text = value.dialCode ?? Constant.defaultCountryCode;
|
||||
},
|
||||
dialogTextStyle: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontWeight: FontWeight.w500, fontFamily: AppThemeData.medium),
|
||||
dialogBackgroundColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
initialSelection: controller.countryCodeEditingController.value.text,
|
||||
comparator: (a, b) => b.name!.compareTo(a.name.toString()),
|
||||
textStyle: TextStyle(fontSize: 14, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium),
|
||||
searchDecoration: InputDecoration(iconColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
|
||||
searchStyle: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontWeight: FontWeight.w500, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: Platform.isAndroid ? 10 : 30),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Log in with'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 10,
|
||||
)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.offAll(const LoginScreen());
|
||||
},
|
||||
text: 'E-mail'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (controller.phoneNUmberEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter mobile number".tr);
|
||||
} else {
|
||||
controller.sendCode();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Send Code".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
811
lib/app/auth_screen/signup_screen.dart
Normal file
811
lib/app/auth_screen/signup_screen.dart
Normal file
@@ -0,0 +1,811 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:driver/app/auth_screen/login_screen.dart';
|
||||
import 'package:driver/app/auth_screen/phone_number_screen.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/signup_controller.dart';
|
||||
import 'package:driver/models/car_makes.dart';
|
||||
import 'package:driver/models/car_model.dart';
|
||||
import 'package:driver/models/section_model.dart';
|
||||
import 'package:driver/models/vehicle_type.dart';
|
||||
import 'package:driver/models/zone_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../constant/constant.dart';
|
||||
|
||||
class SignupScreen extends StatelessWidget {
|
||||
const SignupScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: SignupController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Create an Account".tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
Text(
|
||||
"Sign up now to start your journey as a eMart driver and begin earning with every delivery.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Already Have an account?'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(child: SizedBox(width: 5)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.offAll(const LoginScreen());
|
||||
},
|
||||
text: 'Log in'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Service".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold, fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<String>(
|
||||
hint: Text(
|
||||
'Service Type'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedService.value.isEmpty ? null : controller.selectedService.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedService.value = value!;
|
||||
if (value != "Delivery Service") {
|
||||
controller.getSection();
|
||||
}
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium),
|
||||
items: controller.service.map((item) {
|
||||
return DropdownMenuItem<String>(value: item, child: Text(item.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
controller.selectedService.value == "Delivery Service"
|
||||
? SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Continue as a.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RadioListTile<String>(
|
||||
title: Text(
|
||||
'Individual'.tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700),
|
||||
),
|
||||
value: 'Individual',
|
||||
groupValue: controller.selectedValue.value,
|
||||
activeColor: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Company'.tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700)),
|
||||
value: 'Company',
|
||||
groupValue: controller.selectedValue.value,
|
||||
activeColor: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
controller.selectedValue.value == "Company"
|
||||
? SizedBox()
|
||||
: controller.selectedService.value == "Cab Service" ||
|
||||
controller.selectedService.value == "Rental Service" ||
|
||||
controller.selectedService.value == "Parcel Service"
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select section".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<SectionModel>(
|
||||
hint: Text(
|
||||
'Select Section'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedSection.value.id == null ? null : controller.selectedSection.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedSection.value = value!;
|
||||
controller.getVehicleType();
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.sectionList.map((item) {
|
||||
return DropdownMenuItem<SectionModel>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
controller.selectedService.value == "Cab Service" || controller.selectedService.value == "Rental Service"
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Vehicle Type".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<VehicleType>(
|
||||
hint: Text(
|
||||
'Vehicle Type'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedVehicleType.value.id == null
|
||||
? null
|
||||
: controller.selectedVehicleType.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedVehicleType.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.cabVehicleType.map((item) {
|
||||
return DropdownMenuItem<VehicleType>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Select Car Brand".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<CarMakes>(
|
||||
hint: Text(
|
||||
'Car Brand'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue:
|
||||
controller.selectedCarMakes.value.id == null ? null : controller.selectedCarMakes.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarMakes.value = value!;
|
||||
controller.getCarModel();
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.carMakesList.map((item) {
|
||||
return DropdownMenuItem<CarMakes>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Select car model".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<CarModel>(
|
||||
hint: Text(
|
||||
'Car model'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue:
|
||||
controller.selectedCarModel.value.id == null ? null : controller.selectedCarModel.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarModel.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.carModelList.map((item) {
|
||||
return DropdownMenuItem<CarModel>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextFieldWidget(
|
||||
title: 'Car Plat Number'.tr,
|
||||
controller: controller.carPlatNumberEditingController.value,
|
||||
hintText: 'Enter Car Plat Number'.tr,
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
],
|
||||
)
|
||||
: SizedBox()
|
||||
],
|
||||
)
|
||||
: SizedBox(),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'First Name'.tr,
|
||||
controller: controller.firstNameEditingController.value,
|
||||
hintText: 'Enter First Name'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_user.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'Last Name'.tr,
|
||||
controller: controller.lastNameEditingController.value,
|
||||
hintText: 'Enter Last Name'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_user.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Email Address'.tr,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
controller: controller.emailEditingController.value,
|
||||
hintText: 'Enter Email Address'.tr,
|
||||
enable: controller.type.value == "google" || controller.type.value == "apple" ? false : true,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_mail.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Phone Number'.tr,
|
||||
controller: controller.phoneNUmberEditingController.value,
|
||||
hintText: 'Enter Phone Number'.tr,
|
||||
enable: controller.type.value == "mobileNumber" ? false : true,
|
||||
textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
prefix: CountryCodePicker(
|
||||
enabled: controller.type.value == "mobileNumber" ? false : true,
|
||||
onChanged: (value) {
|
||||
controller.countryCodeEditingController.value.text = value.dialCode ?? Constant.defaultCountryCode;
|
||||
},
|
||||
dialogTextStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: AppThemeData.medium),
|
||||
dialogBackgroundColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
initialSelection: controller.countryCodeEditingController.value.text,
|
||||
comparator: (a, b) => b.name!.compareTo(a.name.toString()),
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.medium),
|
||||
searchDecoration: InputDecoration(iconColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
|
||||
searchStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.selectedValue.value == "Company"
|
||||
? SizedBox()
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Zone".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DropdownButtonFormField<ZoneModel>(
|
||||
hint: Text(
|
||||
'Select zone'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular,
|
||||
),
|
||||
),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
disabledBorder: UnderlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, width: 1),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedZone.value.id == null ? null : controller.selectedZone.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedZone.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.zoneList.map((item) {
|
||||
return DropdownMenuItem<ZoneModel>(
|
||||
value: item,
|
||||
child: Text(item.name.toString()),
|
||||
);
|
||||
}).toList()),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
controller.type.value == "google" || controller.type.value == "apple" || controller.type.value == "mobileNumber"
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Password'.tr,
|
||||
controller: controller.passwordEditingController.value,
|
||||
hintText: 'Enter Password'.tr,
|
||||
obscureText: controller.passwordVisible.value,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_lock.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
suffix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.passwordVisible.value = !controller.passwordVisible.value;
|
||||
},
|
||||
child: controller.passwordVisible.value
|
||||
? SvgPicture.asset(
|
||||
"assets/icons/ic_password_show.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
"assets/icons/ic_password_close.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Confirm Password'.tr,
|
||||
controller: controller.conformPasswordEditingController.value,
|
||||
hintText: 'Enter Confirm Password'.tr,
|
||||
obscureText: controller.conformPasswordVisible.value,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_lock.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
suffix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.conformPasswordVisible.value = !controller.conformPasswordVisible.value;
|
||||
},
|
||||
child: controller.conformPasswordVisible.value
|
||||
? SvgPicture.asset(
|
||||
"assets/icons/ic_password_show.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
"assets/icons/ic_password_close.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)),
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Log in with'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
)),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(
|
||||
width: 10,
|
||||
)),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
Get.to(const PhoneNumberScreen());
|
||||
},
|
||||
text: 'Mobile Number'.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.primary300,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.primary300)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (controller.type.value == "google" || controller.type.value == "apple" || controller.type.value == "mobileNumber") {
|
||||
if (controller.firstNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter first name".tr);
|
||||
} else if (controller.lastNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter last name".tr);
|
||||
} else if (controller.emailEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter valid email".tr);
|
||||
} else if (controller.phoneNUmberEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter Phone number".tr);
|
||||
} else if (controller.selectedZone.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select zone".tr);
|
||||
} else {
|
||||
controller.signUpWithEmailAndPassword();
|
||||
}
|
||||
} else {
|
||||
if (controller.firstNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter first name".tr);
|
||||
} else if (controller.lastNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter last name".tr);
|
||||
} else if (controller.emailEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter valid email".tr);
|
||||
} else if (controller.phoneNUmberEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter Phone number".tr);
|
||||
} else if (controller.passwordEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter password");
|
||||
} else if (controller.conformPasswordEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter Confirm password".tr);
|
||||
} else if (controller.passwordEditingController.value.text !=
|
||||
controller.conformPasswordEditingController.value.text) {
|
||||
ShowToastDialog.showToast("Password and Confirm password doesn't match".tr);
|
||||
} else if (controller.selectedValue.value == "Individual" && controller.selectedZone.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select zone".tr);
|
||||
} else {
|
||||
controller.signUpWithEmailAndPassword();
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Sign up".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
703
lib/app/cab_screen/cab_dashboard_screen.dart
Normal file
703
lib/app/cab_screen/cab_dashboard_screen.dart
Normal file
@@ -0,0 +1,703 @@
|
||||
import 'package:driver/app/auth_screen/login_screen.dart';
|
||||
import 'package:driver/app/cab_screen/cab_order_list_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/terms_and_condition/terms_and_condition_screen.dart';
|
||||
import 'package:driver/app/verification_screen/verification_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/wallet_screen.dart';
|
||||
import 'package:driver/app/withdraw_method_setup_screens/withdraw_method_setup_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/cab_dashboard_controller.dart';
|
||||
import 'package:driver/services/audio_player_service.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/custom_dialog_box.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import '../vehicle_information_screen/vehicle_information_screen.dart';
|
||||
import 'cab_home_screen.dart';
|
||||
|
||||
class CabDashboardScreen extends StatelessWidget {
|
||||
const CabDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: CabDashBoardController(),
|
||||
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 CabHomeScreen()
|
||||
: controller.drawerIndex.value == 1
|
||||
? const CabOrderListScreen()
|
||||
: controller.drawerIndex.value == 2
|
||||
? const WalletScreen(
|
||||
isAppBarShow: false,
|
||||
)
|
||||
: controller.drawerIndex.value == 3
|
||||
? const WithdrawMethodSetupScreen()
|
||||
: controller.drawerIndex.value == 4
|
||||
? const VerificationScreen()
|
||||
: controller.drawerIndex.value == 5
|
||||
? const DriverInboxScreen()
|
||||
: controller.drawerIndex.value == 6
|
||||
? const VehicleInformationScreen()
|
||||
: controller.drawerIndex.value == 7
|
||||
? const ChangeLanguageScreen()
|
||||
: controller.drawerIndex.value == 8
|
||||
? const TermsAndConditionScreen(type: "temsandcondition")
|
||||
: const TermsAndConditionScreen(type: "privacy"),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerView extends StatelessWidget {
|
||||
const DrawerView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
var isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: CabDashBoardController(),
|
||||
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;
|
||||
controller.userModel.value.inProgressOrderID = Constant.userModel!.inProgressOrderID;
|
||||
controller.userModel.value.orderCabRequestData = Constant.userModel!.orderCabRequestData;
|
||||
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;
|
||||
controller.userModel.value.inProgressOrderID = Constant.userModel!.inProgressOrderID;
|
||||
controller.userModel.value.orderCabRequestData = Constant.userModel!.orderCabRequestData;
|
||||
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;
|
||||
},
|
||||
)
|
||||
: const 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;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: Icon(Icons.car_crash),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Vehicle Information'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 6;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'App Preferences'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_change_language.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Change Language'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 7;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_light_dark.svg",
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: CupertinoSwitch(
|
||||
value: controller.isDarkModeSwitch.value,
|
||||
activeTrackColor: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.toggleDarkMode(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Dark Mode'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Social'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_share.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Share app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Share.share(
|
||||
'${'Check out eMart, your ultimate food delivery application!'.tr} \n\n${'Google Play:'.tr} ${Constant.googlePlayLink} \n\n${'App Store:'.tr} ${Constant.appStoreLink}',
|
||||
subject: 'Look what I made!'.tr);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_rate.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Rate the app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
final InAppReview inAppReview = InAppReview.instance;
|
||||
inAppReview.requestReview();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Legal'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_terms_condition.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Terms and Conditions'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 8;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_privacyPolicy.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Privacy Policy'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 9;
|
||||
},
|
||||
),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
1281
lib/app/cab_screen/cab_home_screen.dart
Normal file
1281
lib/app/cab_screen/cab_home_screen.dart
Normal file
File diff suppressed because it is too large
Load Diff
427
lib/app/cab_screen/cab_order_details.dart
Normal file
427
lib/app/cab_screen/cab_order_details.dart
Normal file
@@ -0,0 +1,427 @@
|
||||
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/cab_order_details_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import 'package:flutter_map/flutter_map.dart' as fm;
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart' as gmap;
|
||||
import 'package:latlong2/latlong.dart' as osm;
|
||||
import '../../themes/theme_controller.dart';
|
||||
import '../../utils/network_image_widget.dart';
|
||||
|
||||
class CabOrderDetails extends StatelessWidget {
|
||||
const CabOrderDetails({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: CabOrderDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"Ride Details",
|
||||
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(
|
||||
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.cabOrder.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(
|
||||
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: [
|
||||
Text(
|
||||
"${'Booking Date:'.tr}${controller.formatDate(controller.cabOrder.value.scheduleDateTime!)}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Icon(Icons.stop_circle_outlined, color: Colors.green),
|
||||
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: 55),
|
||||
),
|
||||
Icon(Icons.radio_button_checked, color: Colors.red),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Source Location Name
|
||||
Expanded(
|
||||
child: Text(
|
||||
controller.cabOrder.value.sourceLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: AppThemeData.warning300, width: 1),
|
||||
color: AppThemeData.warning50,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
child: Text(
|
||||
controller.cabOrder.value.status.toString(),
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.warning500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
DottedBorder(
|
||||
options: CustomPathDottedBorderOptions(
|
||||
color: Colors.grey.shade400,
|
||||
strokeWidth: 2,
|
||||
dashPattern: [4, 4],
|
||||
customPath: (size) => Path()
|
||||
..moveTo(0, size.height / 2) // start from left center
|
||||
..lineTo(size.width, size.height / 2), // draw to right center
|
||||
),
|
||||
child: const SizedBox(width: 295, height: 3),
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
Text(
|
||||
controller.cabOrder.value.destinationLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// map view show
|
||||
Container(
|
||||
height: 180,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Constant.selectedMapType == "osm"
|
||||
? fm.FlutterMap(
|
||||
options: fm.MapOptions(
|
||||
initialCenter: osm.LatLng(controller.cabOrder.value.sourceLocation!.latitude!, controller.cabOrder.value.sourceLocation!.longitude!),
|
||||
initialZoom: 13,
|
||||
),
|
||||
children: [
|
||||
fm.TileLayer(urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png"),
|
||||
|
||||
// Only show polyline if points exist
|
||||
if (controller.osmPolyline.isNotEmpty)
|
||||
fm.PolylineLayer(polylines: [fm.Polyline(points: controller.osmPolyline.toList(), color: Colors.blue, strokeWidth: 4)]),
|
||||
|
||||
fm.MarkerLayer(
|
||||
markers: [
|
||||
fm.Marker(
|
||||
point: osm.LatLng(controller.cabOrder.value.sourceLocation!.latitude!, controller.cabOrder.value.sourceLocation!.longitude!),
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: Image.asset('assets/icons/ic_cab_pickup.png', width: 10, height: 10),
|
||||
),
|
||||
fm.Marker(
|
||||
point: osm.LatLng(
|
||||
controller.cabOrder.value.destinationLocation!.latitude!,
|
||||
controller.cabOrder.value.destinationLocation!.longitude!,
|
||||
),
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: Image.asset('assets/icons/ic_cab_destination.png', width: 10, height: 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: gmap.GoogleMap(
|
||||
initialCameraPosition: gmap.CameraPosition(
|
||||
target: gmap.LatLng(controller.cabOrder.value.sourceLocation!.latitude!, controller.cabOrder.value.sourceLocation!.longitude!),
|
||||
zoom: 13,
|
||||
),
|
||||
polylines: controller.googlePolylines.toSet(),
|
||||
markers: controller.googleMarkers.toSet(),
|
||||
),
|
||||
),
|
||||
),
|
||||
controller.cabOrder.value.driver != null
|
||||
? Column(
|
||||
children: [
|
||||
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: [
|
||||
Text(
|
||||
"About Customer".tr,
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 52,
|
||||
height: 52,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadiusGeometry.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.cabOrder.value.author?.profilePictureURL ?? '',
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Text(
|
||||
controller.cabOrder.value.author?.fullName() ?? '',
|
||||
style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18),
|
||||
),
|
||||
// Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// controller.cabOrder.value.author?.fullName() ?? '',
|
||||
// style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18),
|
||||
// ),
|
||||
// Text(
|
||||
// "${controller.cabOrder.value.author?.vehicleType ?? ''} | ${controller.cabOrder.value.author?.carMakes.toString()}",
|
||||
// style: TextStyle(
|
||||
// fontFamily: AppThemeData.medium,
|
||||
// color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
// fontSize: 14,
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// controller.cabOrder.value.driver?.carNumber ?? '',
|
||||
// style: AppThemeData.boldTextStyle(color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 16),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: SizedBox(),
|
||||
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: EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_iconTile(
|
||||
controller.cabOrder.value.distance != null
|
||||
? "${double.tryParse(controller.cabOrder.value.distance.toString())?.toStringAsFixed(2) ?? '--'} KM"
|
||||
: "-- KM",
|
||||
"Distance".tr,
|
||||
"assets/icons/ic_distance_parcel.svg",
|
||||
isDark,
|
||||
),
|
||||
_iconTile(controller.cabOrder.value.duration ?? '--', "Duration".tr, "assets/icons/ic_duration.svg", isDark),
|
||||
_iconTile(
|
||||
Constant.amountShow(amount: controller.cabOrder.value.subTotal),
|
||||
"${controller.cabOrder.value.paymentMethod}".tr,
|
||||
"assets/icons/ic_rate_parcel.svg",
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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: [
|
||||
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.cabOrder.value.taxSetting!.length, (index) {
|
||||
return _summaryTile(
|
||||
"${controller.cabOrder.value.taxSetting![index].title} ${controller.cabOrder.value.taxSetting![index].type == 'fix' ? '' : '(${controller.cabOrder.value.taxSetting![index].tax}%)'}",
|
||||
Constant.amountShow(
|
||||
amount: Constant.getTaxValue(
|
||||
amount: ((double.tryParse(controller.cabOrder.value.subTotal.toString()) ?? 0.0) -
|
||||
(double.tryParse(controller.cabOrder.value.discount.toString()) ?? 0.0))
|
||||
.toString(),
|
||||
taxModel: controller.cabOrder.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.cabOrder.value.adminCommission}${controller.cabOrder.value.adminCommissionType == "Percentage" || controller.cabOrder.value.adminCommissionType == "percentage" ? "%" : Constant.currencyModel!.symbol})"
|
||||
.tr,
|
||||
Constant.amountShow(amount: controller.adminCommission.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.danger300,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
controller.cabOrder.value.driver!.ownerId != null && controller.cabOrder.value.driver!.ownerId!.isNotEmpty ||
|
||||
controller.cabOrder.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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
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)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
182
lib/app/cab_screen/cab_order_list_screen.dart
Normal file
182
lib/app/cab_screen/cab_order_list_screen.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/cab_order_list_controller.dart';
|
||||
import '../../models/cab_order_model.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import 'cab_order_details.dart';
|
||||
|
||||
class CabOrderListScreen extends StatelessWidget {
|
||||
const CabOrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: CabOrderListController(),
|
||||
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]);
|
||||
},
|
||||
// isScrollable: true,
|
||||
indicatorColor: AppThemeData.primary300,
|
||||
labelColor: AppThemeData.primary300,
|
||||
dividerColor: isDark ? Colors.black : Colors.white,
|
||||
unselectedLabelColor: AppThemeData.primary300.withOpacity(0.60),
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 14),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 14),
|
||||
tabs: controller.tabTitles.map((title) => Tab(child: Center(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",
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: orders.length,
|
||||
itemBuilder: (context, index) {
|
||||
CabOrderModel order = orders[index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => CabOrderDetails(), arguments: {"cabOrderModel": 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: [
|
||||
Text(
|
||||
"${'Booking Date:'.tr} ${controller.formatDate(order.scheduleDateTime!)}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Icon(Icons.stop_circle_outlined, color: Colors.green),
|
||||
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: 55),
|
||||
),
|
||||
Icon(Icons.radio_button_checked, color: Colors.red),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Source Location Name
|
||||
Expanded(
|
||||
child: Text(
|
||||
order.sourceLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: AppThemeData.warning300, width: 1),
|
||||
color: AppThemeData.warning50,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
child: Text(
|
||||
order.status.toString(),
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.warning500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
DottedBorder(
|
||||
options: CustomPathDottedBorderOptions(
|
||||
color: Colors.grey.shade400,
|
||||
strokeWidth: 2,
|
||||
dashPattern: [4, 4],
|
||||
customPath: (size) => Path()
|
||||
..moveTo(0, size.height / 2) // start from left center
|
||||
..lineTo(size.width, size.height / 2), // draw to right center
|
||||
),
|
||||
child: const SizedBox(width: 295, height: 3),
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
Text(
|
||||
order.destinationLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
89
lib/app/change langauge/change_language_screen.dart
Normal file
89
lib/app/change langauge/change_language_screen.dart
Normal file
@@ -0,0 +1,89 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/change_language_controller.dart';
|
||||
import 'package:driver/services/localization_service.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/utils/preferences.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class ChangeLanguageScreen extends StatelessWidget {
|
||||
const ChangeLanguageScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ChangeLanguageController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: GridView.count(
|
||||
crossAxisCount: 2,
|
||||
childAspectRatio: (1.1 / 1),
|
||||
crossAxisSpacing: 5,
|
||||
mainAxisSpacing: 1,
|
||||
children: controller.languageList
|
||||
.map(
|
||||
(data) => GestureDetector(
|
||||
onTap: () {
|
||||
LocalizationService().changeLocale(data.slug.toString());
|
||||
Preferences.setString(Preferences.languageCodeKey, jsonEncode(data));
|
||||
controller.selectedLanguage.value = data;
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
NetworkImageWidget(
|
||||
imageUrl: data.image.toString(),
|
||||
height: 80,
|
||||
width: 80,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"${data.title}",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: controller.selectedLanguage.value.slug == data.slug
|
||||
? AppThemeData.primary300
|
||||
: isDark
|
||||
? AppThemeData.grey400
|
||||
: AppThemeData.grey500,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
9
lib/app/chat_screens/ChatVideoContainer.dart
Normal file
9
lib/app/chat_screens/ChatVideoContainer.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
import 'package:driver/models/conversation_model.dart';
|
||||
|
||||
class ChatVideoContainer {
|
||||
Url videoUrl;
|
||||
|
||||
String thumbnailUrl;
|
||||
|
||||
ChatVideoContainer({required this.videoUrl, required this.thumbnailUrl});
|
||||
}
|
||||
358
lib/app/chat_screens/chat_screen.dart
Normal file
358
lib/app/chat_screens/chat_screen.dart
Normal file
@@ -0,0 +1,358 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:driver/app/chat_screens/ChatVideoContainer.dart';
|
||||
import 'package:driver/app/chat_screens/full_screen_image_viewer.dart';
|
||||
import 'package:driver/app/chat_screens/full_screen_video_viewer.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/chat_controller.dart';
|
||||
import 'package:driver/models/conversation_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/firebase_pagination/src/firestore_pagination.dart';
|
||||
import 'package:driver/widget/firebase_pagination/src/models/view_type.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:image_picker/image_picker.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class ChatScreen extends StatelessWidget {
|
||||
const ChatScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ChatController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text(
|
||||
controller.customerName.value,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
child: FirestorePagination(
|
||||
controller: controller.scrollController,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemBuilder: (context, documentSnapshots, index) {
|
||||
ConversationModel inboxModel = ConversationModel.fromJson(documentSnapshots[index].data() as Map<String, dynamic>);
|
||||
return chatItemView(isDark, inboxModel.senderId == FireStoreUtils.getCurrentUid(), inboxModel);
|
||||
},
|
||||
onEmpty: Constant.showEmptyView(message: "No Conversion found".tr, isDark: isDark),
|
||||
// orderBy is compulsory to enable pagination
|
||||
query: FirebaseFirestore.instance
|
||||
.collection(controller.chatType.value == "Driver" ? 'chat_driver' : 'chat_restaurant')
|
||||
.doc(controller.orderId.value)
|
||||
.collection("thread")
|
||||
.orderBy('createdAt', descending: false),
|
||||
isLive: true,
|
||||
viewType: ViewType.list,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
onCameraClick(context, controller);
|
||||
},
|
||||
child: SvgPicture.asset("assets/icons/ic_picture_one.svg")),
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: TextField(
|
||||
textInputAction: TextInputAction.send,
|
||||
keyboardType: TextInputType.text,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
controller: controller.messageController.value,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.only(top: 3, left: 10),
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
hintText: 'Type message here....'.tr,
|
||||
),
|
||||
onSubmitted: (value) async {
|
||||
if (controller.messageController.value.text.isNotEmpty) {
|
||||
controller.sendMessage(controller.messageController.value.text, null, '', 'text');
|
||||
Timer(const Duration(milliseconds: 500), () => controller.scrollController.jumpTo(controller.scrollController.position.maxScrollExtent));
|
||||
controller.messageController.value.clear();
|
||||
}
|
||||
},
|
||||
),
|
||||
)),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (controller.messageController.value.text.isNotEmpty) {
|
||||
controller.sendMessage(controller.messageController.value.text, null, '', 'text');
|
||||
Timer(const Duration(milliseconds: 500), () => controller.scrollController.jumpTo(controller.scrollController.position.maxScrollExtent));
|
||||
controller.messageController.value.clear();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SvgPicture.asset("assets/icons/ic_send.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget chatItemView(isDark, bool isMe, ConversationModel data) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
|
||||
child: isMe
|
||||
? Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
data.messageType == "text"
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomLeft: Radius.circular(12)),
|
||||
color: AppThemeData.primary300,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Text(
|
||||
data.message.toString(),
|
||||
style: const TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
),
|
||||
)
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomLeft: Radius.circular(12)),
|
||||
// color: AppThemeData.primary300,
|
||||
// ),
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
// child: Text(
|
||||
// data.message.toString(),
|
||||
// style: const TextStyle(
|
||||
// fontFamily: AppThemeData.medium,
|
||||
// fontSize: 16,
|
||||
// color: AppThemeData.grey50,
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
: data.messageType == "image"
|
||||
? ClipRRect(
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomLeft: Radius.circular(12)),
|
||||
child: Stack(alignment: Alignment.center, children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(FullScreenImageViewer(imageUrl: data.url!.url));
|
||||
},
|
||||
child: Hero(
|
||||
tag: data.url!.url,
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: data.url!.url,
|
||||
height: 100,
|
||||
width: 100,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
)
|
||||
: FloatingActionButton(
|
||||
mini: true,
|
||||
heroTag: data.id,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
onPressed: () {
|
||||
Get.to(FullScreenVideoViewer(heroTag: data.id.toString(), videoUrl: data.url!.url));
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(DateFormat('MMM d, yyyy hh:mm aa').format(DateTime.fromMillisecondsSinceEpoch(data.createdAt!.millisecondsSinceEpoch)),
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
data.messageType == "text"
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomRight: Radius.circular(12)),
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Text(
|
||||
data.message.toString(),
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
)
|
||||
: data.messageType == "image"
|
||||
? ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 50,
|
||||
maxWidth: 200,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12), bottomRight: Radius.circular(12)),
|
||||
child: Stack(alignment: Alignment.center, children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(FullScreenImageViewer(imageUrl: data.url!.url));
|
||||
},
|
||||
child: Hero(
|
||||
tag: data.url!.url,
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: data.url!.url,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
))
|
||||
: FloatingActionButton(
|
||||
mini: true,
|
||||
heroTag: data.id,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
onPressed: () {
|
||||
Get.to(FullScreenVideoViewer(heroTag: data.id.toString(), videoUrl: data.url!.url));
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(DateFormat('MMM d, yyyy hh:mm aa').format(DateTime.fromMillisecondsSinceEpoch(data.createdAt!.millisecondsSinceEpoch)),
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void onCameraClick(BuildContext context, ChatController controller) {
|
||||
final action = CupertinoActionSheet(
|
||||
message: Text(
|
||||
'Send Media'.tr,
|
||||
style: TextStyle(fontSize: 15.0),
|
||||
),
|
||||
actions: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
isDefaultAction: false,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
XFile? image = await controller.imagePicker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
Url url = await FireStoreUtils.uploadChatImageToFireStorage(File(image.path), context);
|
||||
controller.sendMessage('', url, '', 'image');
|
||||
}
|
||||
},
|
||||
child: Text("Choose image from gallery".tr),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
isDefaultAction: false,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
XFile? galleryVideo = await controller.imagePicker.pickVideo(source: ImageSource.gallery);
|
||||
if (galleryVideo != null) {
|
||||
ChatVideoContainer? videoContainer = await FireStoreUtils.uploadChatVideoToFireStorage(context, File(galleryVideo.path));
|
||||
if (videoContainer != null) {
|
||||
controller.sendMessage('', videoContainer.videoUrl, videoContainer.thumbnailUrl, 'video');
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text("Choose video from gallery".tr),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
isDestructiveAction: false,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
XFile? image = await controller.imagePicker.pickImage(source: ImageSource.camera);
|
||||
if (image != null) {
|
||||
Url url = await FireStoreUtils.uploadChatImageToFireStorage(File(image.path), context);
|
||||
controller.sendMessage('', url, '', 'image');
|
||||
}
|
||||
},
|
||||
child: Text("Take a picture".tr),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
isDestructiveAction: false,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
XFile? recordedVideo = await controller.imagePicker.pickVideo(source: ImageSource.camera);
|
||||
if (recordedVideo != null) {
|
||||
ChatVideoContainer? videoContainer = await FireStoreUtils.uploadChatVideoToFireStorage(context, File(recordedVideo.path));
|
||||
if (videoContainer != null) {
|
||||
controller.sendMessage('', videoContainer.videoUrl, videoContainer.thumbnailUrl, 'video');
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text("Record video".tr),
|
||||
)
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
child: Text(
|
||||
'Cancel'.tr,
|
||||
),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
);
|
||||
showCupertinoModalPopup(context: context, builder: (context) => action);
|
||||
}
|
||||
}
|
||||
136
lib/app/chat_screens/driver_inbox_screen.dart
Normal file
136
lib/app/chat_screens/driver_inbox_screen.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:driver/app/chat_screens/chat_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/models/inbox_model.dart';
|
||||
import 'package:driver/models/user_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/firebase_pagination/src/firestore_pagination.dart';
|
||||
import 'package:driver/widget/firebase_pagination/src/models/view_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class DriverInboxScreen extends StatelessWidget {
|
||||
const DriverInboxScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return Scaffold(
|
||||
body: FirestorePagination(
|
||||
//item builder type is compulsory.
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemBuilder: (context, documentSnapshots, index) {
|
||||
final data = documentSnapshots[index].data() as Map<String, dynamic>?;
|
||||
InboxModel inboxModel = InboxModel.fromJson(data!);
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(inboxModel.customerId.toString());
|
||||
UserModel? restaurantUser = await FireStoreUtils.getUserProfile(inboxModel.restaurantId.toString());
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer!.fullName(),
|
||||
"restaurantName": restaurantUser!.fullName(),
|
||||
"orderId": inboxModel.orderId,
|
||||
"restaurantId": restaurantUser.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": restaurantUser.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": inboxModel.chatType,
|
||||
});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: inboxModel.customerProfileImage.toString(),
|
||||
fit: BoxFit.cover,
|
||||
height: Responsive.height(6, context),
|
||||
width: Responsive.width(12, context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${inboxModel.customerName}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(inboxModel.createdAt!),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"${inboxModel.lastMessage}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey200 : AppThemeData.grey700,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
shrinkWrap: true,
|
||||
onEmpty: Constant.showEmptyView(message: "No Conversion found".tr,isDark: isDark),
|
||||
// orderBy is compulsory to enable pagination
|
||||
query: FirebaseFirestore.instance.collection('chat_driver').where("restaurantId", isEqualTo: FireStoreUtils.getCurrentUid()).orderBy('createdAt', descending: true),
|
||||
//Change types customerId
|
||||
viewType: ViewType.list,
|
||||
initialLoader: Constant.loader(),
|
||||
// to fetch real-time data
|
||||
isLive: true,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
32
lib/app/chat_screens/full_screen_image_viewer.dart
Normal file
32
lib/app/chat_screens/full_screen_image_viewer.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
|
||||
class FullScreenImageViewer extends StatelessWidget {
|
||||
final String imageUrl;
|
||||
final File? imageFile;
|
||||
|
||||
const FullScreenImageViewer({super.key, required this.imageUrl, this.imageFile});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0.0,
|
||||
backgroundColor: Colors.black,
|
||||
iconTheme: const IconThemeData(color: Colors.white),
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
),
|
||||
body: Container(
|
||||
color: Colors.black,
|
||||
child: Hero(
|
||||
tag: imageUrl,
|
||||
child: PhotoView(
|
||||
imageProvider: imageFile == null ? NetworkImage(imageUrl) : Image.file(imageFile!).image,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
75
lib/app/chat_screens/full_screen_video_viewer.dart
Normal file
75
lib/app/chat_screens/full_screen_video_viewer.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class FullScreenVideoViewer extends StatefulWidget {
|
||||
final String videoUrl;
|
||||
final String heroTag;
|
||||
final File? videoFile;
|
||||
|
||||
const FullScreenVideoViewer({super.key, required this.videoUrl, required this.heroTag, this.videoFile});
|
||||
|
||||
@override
|
||||
_FullScreenVideoViewerState createState() => _FullScreenVideoViewerState();
|
||||
}
|
||||
|
||||
class _FullScreenVideoViewerState extends State<FullScreenVideoViewer> {
|
||||
late VideoPlayerController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = widget.videoFile == null ? VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl)) : VideoPlayerController.file(widget.videoFile!)
|
||||
..initialize().then((_) {
|
||||
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
|
||||
setState(() {});
|
||||
});
|
||||
_controller.setLooping(true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0.0,
|
||||
backgroundColor: Colors.black,
|
||||
iconTheme: const IconThemeData(color: Colors.white),
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
),
|
||||
body: Container(
|
||||
color: Colors.black,
|
||||
child: Hero(
|
||||
tag: widget.videoUrl,
|
||||
child: Center(
|
||||
child: _controller.value.isInitialized
|
||||
? AspectRatio(
|
||||
aspectRatio: _controller.value.aspectRatio,
|
||||
child: VideoPlayer(_controller),
|
||||
)
|
||||
: Container(),
|
||||
),
|
||||
)),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
heroTag: widget.heroTag,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_controller.value.isPlaying ? _controller.pause() : _controller.play();
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
_controller.value.isPlaying ? CupertinoIcons.pause : CupertinoIcons.play_arrow_solid,
|
||||
),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_controller.dispose();
|
||||
}
|
||||
}
|
||||
690
lib/app/dash_board_screen/dash_board_screen.dart
Normal file
690
lib/app/dash_board_screen/dash_board_screen.dart
Normal file
@@ -0,0 +1,690 @@
|
||||
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/home_screen/home_screen.dart';
|
||||
import 'package:driver/app/home_screen/home_screen_multiple_order.dart';
|
||||
import 'package:driver/app/order_list_screen/order_list_screen.dart';
|
||||
import 'package:driver/app/terms_and_condition/terms_and_condition_screen.dart';
|
||||
import 'package:driver/app/verification_screen/verification_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/wallet_screen.dart';
|
||||
import 'package:driver/app/withdraw_method_setup_screens/withdraw_method_setup_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/dash_board_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 DashBoardScreen extends StatelessWidget {
|
||||
const DashBoardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: DashBoardController(),
|
||||
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: [
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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
|
||||
? Constant.singleOrderReceive == true
|
||||
? const HomeScreen(
|
||||
isAppBarShow: false,
|
||||
)
|
||||
: const HomeScreenMultipleOrder()
|
||||
: controller.drawerIndex.value == 1
|
||||
? const OrderListScreen()
|
||||
: 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(() {
|
||||
var isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: DashBoardController(),
|
||||
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;
|
||||
controller.userModel.value.inProgressOrderID = Constant.userModel!.inProgressOrderID;
|
||||
controller.userModel.value.orderRequestData = Constant.userModel!.orderRequestData;
|
||||
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;
|
||||
controller.userModel.value.inProgressOrderID = Constant.userModel!.inProgressOrderID;
|
||||
controller.userModel.value.orderRequestData = Constant.userModel!.orderRequestData;
|
||||
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;
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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;
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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.isDriverVerification == 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
316
lib/app/edit_profile_screen/edit_profile_screen.dart
Normal file
316
lib/app/edit_profile_screen/edit_profile_screen.dart
Normal file
@@ -0,0 +1,316 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/edit_profile_controller.dart';
|
||||
import 'package:driver/models/zone_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.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:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class EditProfileScreen extends StatelessWidget {
|
||||
const EditProfileScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: EditProfileController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text(
|
||||
"Edit Profile".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
controller.profileImage.isEmpty
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
child: Image.asset(
|
||||
Constant.userPlaceHolder,
|
||||
height: Responsive.width(24, context),
|
||||
width: Responsive.width(24, context),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)
|
||||
: Constant().hasValidUrl(controller.profileImage.value) == false
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
child: Image.file(
|
||||
File(controller.profileImage.value),
|
||||
height: Responsive.width(24, context),
|
||||
width: Responsive.width(24, context),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
child: NetworkImageWidget(
|
||||
fit: BoxFit.cover,
|
||||
imageUrl: controller.userModel.value.profilePictureURL.toString(),
|
||||
height: Responsive.width(24, context),
|
||||
width: Responsive.width(24, context),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
buildBottomSheet(context, controller);
|
||||
},
|
||||
child: SvgPicture.asset("assets/icons/ic_edit.svg")))
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'First Name'.tr,
|
||||
controller: controller.firstNameController.value,
|
||||
hintText: 'First Name'.tr,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'Last Name'.tr,
|
||||
controller: controller.lastNameController.value,
|
||||
hintText: 'Last Name'.tr,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Email'.tr,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
controller: controller.emailController.value,
|
||||
hintText: 'Email'.tr,
|
||||
enable: false,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Phone Number'.tr,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
controller: controller.phoneNumberController.value,
|
||||
hintText: 'Phone Number'.tr,
|
||||
enable: false,
|
||||
),
|
||||
controller.userModel.value.isOwner == true ||
|
||||
( controller.userModel.value.vendorID != null && controller.userModel.value.vendorID!.isNotEmpty)
|
||||
? SizedBox()
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Zone".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DropdownButtonFormField<ZoneModel>(
|
||||
hint: Text(
|
||||
'Select zone'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular,
|
||||
),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty
|
||||
? false
|
||||
: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, width: 1),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, width: 1),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.grey900 : AppThemeData.grey50, width: 1),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedZone.value.id == null ? null : controller.selectedZone.value,
|
||||
onChanged:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty
|
||||
? null
|
||||
: (value) {
|
||||
controller.selectedZone.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.zoneList.map((item) {
|
||||
return DropdownMenuItem<ZoneModel>(
|
||||
value: item,
|
||||
child: Text(
|
||||
item.name.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: InkWell(
|
||||
onTap: () async {
|
||||
controller.saveData();
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Save".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future buildBottomSheet(BuildContext context, EditProfileController controller) {
|
||||
return showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return SizedBox(
|
||||
height: Responsive.height(22, context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Text("please select".tr,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
)),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => controller.pickFile(source: ImageSource.camera),
|
||||
icon: const Icon(
|
||||
Icons.camera_alt,
|
||||
size: 32,
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3),
|
||||
child: Text(
|
||||
"camera".tr,
|
||||
style: const TextStyle(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => controller.pickFile(source: ImageSource.gallery),
|
||||
icon: const Icon(
|
||||
Icons.photo_library_sharp,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3),
|
||||
child: Text(
|
||||
"gallery".tr,
|
||||
style: const TextStyle(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
91
lib/app/forgot_password_screen/forgot_password_screen.dart
Normal file
91
lib/app/forgot_password_screen/forgot_password_screen.dart
Normal file
@@ -0,0 +1,91 @@
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/forgot_password_controller.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class ForgotPasswordScreen extends StatelessWidget {
|
||||
const ForgotPasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: ForgotPasswordController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Forgot Password".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
Text(
|
||||
"No worries!! We’ll send you reset instructions".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey400 : AppThemeData.grey500, fontSize: 16, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Email Address'.tr,
|
||||
controller: controller.emailEditingController.value,
|
||||
hintText: 'Enter email address'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_mail.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: InkWell(
|
||||
onTap: () {
|
||||
if (controller.emailEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter valid email".tr);
|
||||
} else {
|
||||
controller.forgotPassword();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Forgot Password".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
379
lib/app/home_screen/deliver_order_screen.dart
Normal file
379
lib/app/home_screen/deliver_order_screen.dart
Normal file
@@ -0,0 +1,379 @@
|
||||
import 'package:driver/app/chat_screens/chat_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/deliver_order_controller.dart';
|
||||
import 'package:driver/models/cart_product_model.dart';
|
||||
import 'package:driver/models/user_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class DeliverOrderScreen extends StatelessWidget {
|
||||
const DeliverOrderScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: DeliverOrderController(),
|
||||
builder: (controller) {
|
||||
return controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
iconTheme: const IconThemeData(color: AppThemeData.grey900, size: 20),
|
||||
title: Text(
|
||||
Constant.orderId(orderId: controller.orderModel.value.id.toString()).tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Deliver to the".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.author!.fullName(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.address!.getFullAddress(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(controller.orderModel.value.authorID.toString());
|
||||
UserModel? driver = await FireStoreUtils.getUserProfile(controller.orderModel.value.driverID.toString());
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer!.fullName(),
|
||||
"restaurantName": driver!.fullName(),
|
||||
"orderId": controller.orderModel.value.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
width: 42,
|
||||
height: 42,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_wechat.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.orderModel.value.products!.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
CartProductModel product = controller.orderModel.value.products![index];
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
child: Stack(
|
||||
children: [
|
||||
NetworkImageWidget(
|
||||
imageUrl: product.photo.toString(),
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Container(
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: const Alignment(-0.00, -1.00),
|
||||
end: const Alignment(0, 1),
|
||||
colors: [Colors.black.withOpacity(0), const Color(0xFF111827)],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${product.name}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"x ${product.quantity}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
product.variantInfo == null || product.variantInfo!.variantOptions!.isEmpty
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Variants".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
product.variantInfo!.variantOptions!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
"${product.variantInfo!.variantOptions!.keys.elementAt(i)} : ${product.variantInfo!.variantOptions![product.variantInfo!.variantOptions!.keys.elementAt(i)]}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
product.extras == null || product.extras!.isEmpty
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Addons".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
product.extras!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
product.extras![i].toString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
side: const BorderSide(
|
||||
color: AppThemeData.success400,
|
||||
width: 1.5,
|
||||
),
|
||||
value: controller.conformPickup.value,
|
||||
activeColor: AppThemeData.success400,
|
||||
focusColor: AppThemeData.success400,
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
controller.conformPickup.value = value;
|
||||
}
|
||||
},
|
||||
),
|
||||
Text(
|
||||
"${'Give'.tr} ${controller.totalQuantity.value.toString()} ${'Items to the customer'.tr}".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: InkWell(
|
||||
onTap: () async {
|
||||
if (controller.conformPickup.value == false) {
|
||||
ShowToastDialog.showToast("Conform Deliver order".tr);
|
||||
} else {
|
||||
await controller.completedOrder();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Make Order Delivered".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
1067
lib/app/home_screen/home_screen.dart
Normal file
1067
lib/app/home_screen/home_screen.dart
Normal file
File diff suppressed because it is too large
Load Diff
1067
lib/app/home_screen/home_screen_multiple_order.dart
Normal file
1067
lib/app/home_screen/home_screen_multiple_order.dart
Normal file
File diff suppressed because it is too large
Load Diff
375
lib/app/home_screen/pickup_order_screen.dart
Normal file
375
lib/app/home_screen/pickup_order_screen.dart
Normal file
@@ -0,0 +1,375 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/pickup_order_controller.dart';
|
||||
import 'package:driver/models/cart_product_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/my_separator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class PickupOrderScreen extends StatelessWidget {
|
||||
const PickupOrderScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: PickupOrderController(),
|
||||
builder: (controller) {
|
||||
return controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
iconTheme: const IconThemeData(color: AppThemeData.grey900, size: 20),
|
||||
title: Text(
|
||||
Constant.orderId(orderId: controller.orderModel.value.id.toString()).tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(child: Image.asset("assets/images/order_pickup.gif")),
|
||||
Text(
|
||||
"Order Ready to pickup".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 22, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"Your order has been ready pickup the order and deliver to the customer’s locations.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey500, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"Item and Deliver to the".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.orderModel.value.products!.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
CartProductModel product = controller.orderModel.value.products![index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
child: Stack(
|
||||
children: [
|
||||
NetworkImageWidget(
|
||||
imageUrl: product.photo.toString(),
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Container(
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: const Alignment(-0.00, -1.00),
|
||||
end: const Alignment(0, 1),
|
||||
colors: [Colors.black.withOpacity(0), const Color(0xFF111827)],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${product.name}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"x ${product.quantity}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
product.variantInfo == null || product.variantInfo!.variantOptions!.isEmpty
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Variants".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
product.variantInfo!.variantOptions!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
"${product.variantInfo!.variantOptions!.keys.elementAt(i)} : ${product.variantInfo!.variantOptions![product.variantInfo!.variantOptions!.keys.elementAt(i)]}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
product.extras == null || product.extras!.isEmpty
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Addons".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
product.extras!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
product.extras![i].toString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
side: const BorderSide(
|
||||
color: AppThemeData.success400,
|
||||
width: 1.5,
|
||||
),
|
||||
value: controller.conformPickup.value,
|
||||
activeColor: AppThemeData.success400,
|
||||
focusColor: AppThemeData.success400,
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
controller.conformPickup.value = value;
|
||||
}
|
||||
},
|
||||
),
|
||||
Text(
|
||||
"Confirm Pickup".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: AppThemeData.carRent50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_location.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Deliver to the".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.author!.fullName(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.address!.getFullAddress(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: InkWell(
|
||||
onTap: () async {
|
||||
if (controller.conformPickup.value == false) {
|
||||
ShowToastDialog.showToast("Conform pickup order".tr);
|
||||
} else {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
controller.orderModel.value.status = Constant.orderInTransit;
|
||||
await FireStoreUtils.setOrder(controller.orderModel.value);
|
||||
ShowToastDialog.closeLoader();
|
||||
Get.back(result: true);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Picked Order".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
46
lib/app/maintenance_mode_screen/maintenance_mode_screen.dart
Normal file
46
lib/app/maintenance_mode_screen/maintenance_mode_screen.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class MaintenanceModeScreen extends StatelessWidget {
|
||||
const MaintenanceModeScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppThemeData.grey100,
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: Image.asset(
|
||||
'assets/images/maintenance.png',
|
||||
height: 200,
|
||||
width: 200,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
"We'll be back soon!".tr,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Text(
|
||||
"Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
140
lib/app/on_boarding_screen.dart
Normal file
140
lib/app/on_boarding_screen.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controllers/on_boarding_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../utils/network_image_widget.dart';
|
||||
import '../../utils/preferences.dart';
|
||||
import '../themes/round_button_fill.dart';
|
||||
import 'auth_screen/login_screen.dart';
|
||||
|
||||
class OnboardingScreen extends StatelessWidget {
|
||||
const OnboardingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetX<OnboardingController>(
|
||||
init: OnboardingController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
body: controller.isLoading.value?Constant.loader():Stack(
|
||||
children: [
|
||||
Image.asset('assets/images/onboarding_bg.png', fit: BoxFit.cover),
|
||||
SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15,
|
||||
vertical: 20,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
style: AppThemeData.regularTextStyle(fontSize: 14),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${controller.currentPage.value + 1}",
|
||||
style: AppThemeData.regularTextStyle(
|
||||
color: AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: "/${controller.onboardingList.length}",
|
||||
style: AppThemeData.regularTextStyle(
|
||||
color: AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: PageView.builder(
|
||||
controller: controller.pageController,
|
||||
onPageChanged: controller.onPageChanged,
|
||||
itemCount: controller.onboardingList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = controller.onboardingList[index];
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
item.title ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
item.description ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: AppThemeData.grey500,
|
||||
fontSize: 14,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
NetworkImageWidget(
|
||||
imageUrl: item.image ?? '',
|
||||
width: Responsive.width(100, context),
|
||||
height: 500,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
controller.currentPage.value == controller.onboardingList.length - 1
|
||||
? RoundedButtonFill(
|
||||
title: "Let’s Get Started".tr,
|
||||
onPress: () {
|
||||
_finish();
|
||||
},
|
||||
color: AppThemeData.grey900,
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Skip".tr,
|
||||
onPress: () => _finish(),
|
||||
color: AppThemeData.grey50,
|
||||
textColor: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Next".tr,
|
||||
onPress: () {
|
||||
controller.nextPage();
|
||||
},
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _finish() async {
|
||||
await Preferences.setBoolean(Preferences.isFinishOnBoardingKey, true);
|
||||
Get.offAll(() => const LoginScreen());
|
||||
}
|
||||
}
|
||||
731
lib/app/order_list_screen/order_details_screen.dart
Normal file
731
lib/app/order_list_screen/order_details_screen.dart
Normal file
@@ -0,0 +1,731 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/order_details_controller.dart';
|
||||
import 'package:driver/models/cart_product_model.dart';
|
||||
import 'package:driver/models/tax_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/my_separator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
class OrderDetailsScreen extends StatelessWidget {
|
||||
const OrderDetailsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: OrderDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text(
|
||||
"Order Details".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${'Order'.tr} ${Constant.orderId(orderId: controller.orderModel.value.id.toString())}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Constant.statusColor(status: controller.orderModel.value.status.toString()),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
||||
child: Text(
|
||||
controller.orderModel.value.status.toString().tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.bold,
|
||||
fontSize: 14,
|
||||
color: Constant.statusText(status: controller.orderModel.value.status.toString()),
|
||||
),
|
||||
),
|
||||
)
|
||||
// RoundedButtonFill(
|
||||
// title: controller.orderModel.value.status.toString().tr,
|
||||
// color: Constant.statusColor(status: controller.orderModel.value.status.toString()),
|
||||
// width: 32,
|
||||
// height: 4.5,
|
||||
// textColor: Constant.statusText(status: controller.orderModel.value.status.toString()),
|
||||
// onPress: () async {},
|
||||
// ),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Timeline.tileBuilder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
theme: TimelineThemeData(
|
||||
nodePosition: 0,
|
||||
// indicatorPosition: 0,
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
contentsAlign: ContentsAlign.basic,
|
||||
indicatorBuilder: (context, index) {
|
||||
return SvgPicture.asset("assets/icons/ic_location.svg");
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return const DashedLineConnector(
|
||||
color: AppThemeData.grey300,
|
||||
gap: 3,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
child: index == 0
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${controller.orderModel.value.vendor!.title}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.orderModel.value.vendor!.location}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${controller.orderModel.value.address!.addressAs}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.author!.fullName(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.orderModel.value.address!.getFullAddress(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 2,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Order Details".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: controller.orderModel.value.products!.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
CartProductModel cartProductModel = controller.orderModel.value.products![index];
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
child: Stack(
|
||||
children: [
|
||||
NetworkImageWidget(
|
||||
imageUrl: cartProductModel.photo.toString(),
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Container(
|
||||
height: Responsive.height(8, context),
|
||||
width: Responsive.width(16, context),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: const Alignment(-0.00, -1.00),
|
||||
end: const Alignment(0, 1),
|
||||
colors: [Colors.black.withOpacity(0), const Color(0xFF111827)],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${cartProductModel.name}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"x ${cartProductModel.quantity}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
double.parse(cartProductModel.discountPrice == null || cartProductModel.discountPrice!.isEmpty
|
||||
? "0.0"
|
||||
: cartProductModel.discountPrice.toString()) <=
|
||||
0
|
||||
? Text(
|
||||
Constant.amountShow(amount: cartProductModel.price),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
Constant.amountShow(amount: cartProductModel.discountPrice.toString()),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: cartProductModel.price),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
decorationColor: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
cartProductModel.variantInfo == null || cartProductModel.variantInfo!.variantOptions!.isEmpty
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Variants".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
cartProductModel.variantInfo!.variantOptions!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
"${cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)} : ${cartProductModel.variantInfo!.variantOptions![cartProductModel.variantInfo!.variantOptions!.keys.elementAt(i)]}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
cartProductModel.extras == null || cartProductModel.extras!.isEmpty
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Addons".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: (double.parse(cartProductModel.extrasPrice.toString()) * double.parse(cartProductModel.quantity.toString()))
|
||||
.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Wrap(
|
||||
spacing: 6.0,
|
||||
runSpacing: 6.0,
|
||||
children: List.generate(
|
||||
cartProductModel.extras!.length,
|
||||
(i) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
|
||||
child: Text(
|
||||
cartProductModel.extras![i].toString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.grey500 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Bill Details".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Item totals".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: controller.subTotal.value.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
controller.orderModel.value.takeAway == true || Constant.userModel?.vendorID?.isNotEmpty == true
|
||||
? const SizedBox()
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Delivery Fee".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: controller.orderModel.value.deliveryCharge == null || controller.orderModel.value.deliveryCharge!.isEmpty
|
||||
? "0.0"
|
||||
: controller.orderModel.value.deliveryCharge.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Coupon Discount".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"- (${Constant.amountShow(amount: controller.orderModel.value.discount.toString())})",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
controller.orderModel.value.specialDiscount != null && controller.orderModel.value.specialDiscount!['special_discount'] != null
|
||||
? Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Special Discount".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"- (${Constant.amountShow(amount: controller.specialDiscountAmount.value.toString())})",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
controller.orderModel.value.takeAway == true || Constant.userModel?.vendorID?.isNotEmpty == true
|
||||
? const SizedBox()
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Delivery Tips".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: controller.orderModel.value.tipAmount.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
ListView.builder(
|
||||
itemCount: controller.orderModel.value.taxSetting!.length,
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
TaxModel taxModel = controller.orderModel.value.taxSetting![index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${taxModel.title.toString()} (${taxModel.type == "fix" ? Constant.amountShow(amount: taxModel.tax) : "${taxModel.tax}%"})",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: Constant.calculateTax(
|
||||
amount: (controller.subTotal.value -
|
||||
double.parse(controller.orderModel.value.discount.toString()) -
|
||||
controller.specialDiscountAmount.value)
|
||||
.toString(),
|
||||
taxModel: taxModel)
|
||||
.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"To Pay".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: controller.totalAmount.value.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
372
lib/app/order_list_screen/order_list_screen.dart
Normal file
372
lib/app/order_list_screen/order_list_screen.dart
Normal file
@@ -0,0 +1,372 @@
|
||||
import 'package:driver/app/order_list_screen/order_details_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/dash_board_controller.dart';
|
||||
import 'package:driver/controllers/order_list_controller.dart';
|
||||
import 'package:driver/models/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/widget/my_separator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
class OrderListScreen extends StatelessWidget {
|
||||
const OrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: OrderListController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
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 {
|
||||
DashBoardController dashBoardController = Get.put(DashBoardController());
|
||||
dashBoardController.drawerIndex.value = 4;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: controller.orderList.isEmpty
|
||||
? Constant.showEmptyView(message: "Order Not found".tr,isDark: isDark)
|
||||
: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.orderList.length,
|
||||
itemBuilder: (context, index) {
|
||||
OrderModel orderModel = controller.orderList[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Get.to(const OrderDetailsScreen(), arguments: {"orderModel": orderModel});
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Order ID".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.orderId(orderId: orderModel.id.toString()),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Status".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
orderModel.status.toString(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: Constant.statusColor(status: orderModel.status),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Date".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDateTime(orderModel.createdAt!),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
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
|
||||
? Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: AppThemeData.primary50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_building.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: AppThemeData.carRent50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_location.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return const DashedLineConnector(
|
||||
color: AppThemeData.grey300,
|
||||
gap: 3,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
child: index == 0
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${orderModel.vendor!.title}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${orderModel.vendor!.location}",
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Deliver to the".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
orderModel.address!.getFullAddress(),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 2,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: (Constant.userModel?.vendorID?.isEmpty == true),
|
||||
child: Column(children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Delivery Charge".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: orderModel.deliveryCharge),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
orderModel.tipAmount == null || orderModel.tipAmount!.isEmpty || double.parse(orderModel.tipAmount.toString()) <= 0
|
||||
? const SizedBox()
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Tips".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.regular,
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: orderModel.tipAmount),
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
807
lib/app/owner_screen/driver_create_screen.dart
Normal file
807
lib/app/owner_screen/driver_create_screen.dart
Normal file
@@ -0,0 +1,807 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/driver_create_controller.dart';
|
||||
import 'package:driver/models/car_makes.dart';
|
||||
import 'package:driver/models/section_model.dart';
|
||||
import 'package:driver/models/vehicle_type.dart';
|
||||
import 'package:driver/models/zone_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../models/car_model.dart' show CarModel;
|
||||
import '../../themes/responsive.dart' show Responsive;
|
||||
|
||||
class DriverCreateScreen extends StatelessWidget {
|
||||
const DriverCreateScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: DriverCreateController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty
|
||||
? 'Update Driver'.tr
|
||||
: 'Create Driver'.tr),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Service".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<String>(
|
||||
hint: Text(
|
||||
'Service Type'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedService.value.isEmpty ? null : controller.selectedService.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedService.value = value!;
|
||||
if (value != "Delivery Service") {
|
||||
controller.getSection();
|
||||
}
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.service.map((item) {
|
||||
return DropdownMenuItem<String>(value: item, child: Text(item.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
controller.selectedService.value == "Cab Service" ||
|
||||
controller.selectedService.value == "Rental Service" ||
|
||||
controller.selectedService.value == "Parcel Service"
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select section".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<SectionModel>(
|
||||
hint: Text(
|
||||
'Service Type'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue:
|
||||
controller.selectedSection.value.id == null ? null : controller.selectedSection.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedSection.value = value!;
|
||||
controller.getVehicleType();
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.sectionList.map((item) {
|
||||
return DropdownMenuItem<SectionModel>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
controller.selectedService.value == "Cab Service" ||
|
||||
controller.selectedService.value == "Rental Service"
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Vehicle Type".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<VehicleType>(
|
||||
hint: Text(
|
||||
'Vehicle Type'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedVehicleType.value.id == null
|
||||
? null
|
||||
: controller.selectedVehicleType.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedVehicleType.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.cabVehicleType.map((item) {
|
||||
return DropdownMenuItem<VehicleType>(
|
||||
value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Select Car Brand".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<CarMakes>(
|
||||
hint: Text(
|
||||
'Car Brand'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedCarMakes.value.id == null
|
||||
? null
|
||||
: controller.selectedCarMakes.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarMakes.value = value!;
|
||||
controller.getCarModel();
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.carMakesList.map((item) {
|
||||
return DropdownMenuItem<CarMakes>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Select car model".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<CarModel>(
|
||||
hint: Text(
|
||||
'Car model'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular),
|
||||
),
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedCarModel.value.id == null
|
||||
? null
|
||||
: controller.selectedCarModel.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarModel.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.carModelList.map((item) {
|
||||
return DropdownMenuItem<CarModel>(value: item, child: Text(item.name.toString()));
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextFieldWidget(
|
||||
title: 'Car Plat Number'.tr,
|
||||
controller: controller.carPlatNumberEditingController.value,
|
||||
hintText: 'Enter Car Plat Number'.tr,
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
],
|
||||
)
|
||||
: SizedBox()
|
||||
],
|
||||
)
|
||||
: SizedBox(),
|
||||
controller.selectedService.value == "Cab Service"
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(top: 10, bottom: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Ride Type".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Obx(
|
||||
() => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text('Ride'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'ride',
|
||||
activeColor: AppThemeData.primary300,
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
activeColor: AppThemeData.primary300,
|
||||
title: Text('Intercity'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'intercity',
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text('Both'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'both',
|
||||
activeColor: AppThemeData.primary300,
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Zone".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DropdownButtonFormField<ZoneModel>(
|
||||
hint: Text(
|
||||
'Select zone'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey700,
|
||||
fontFamily: AppThemeData.regular,
|
||||
),
|
||||
),
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: const TextStyle(color: Colors.red),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.red),
|
||||
),
|
||||
disabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide:
|
||||
BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400, width: 1.2),
|
||||
),
|
||||
),
|
||||
initialValue: controller.selectedZone.value.id == null ? null : controller.selectedZone.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedZone.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
items: controller.zoneList.map((item) {
|
||||
return DropdownMenuItem<ZoneModel>(
|
||||
value: item,
|
||||
child: Text(item.name.toString()),
|
||||
);
|
||||
}).toList()),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'First Name'.tr,
|
||||
controller: controller.firstNameEditingController.value,
|
||||
hintText: 'Enter First Name'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_user.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextFieldWidget(
|
||||
title: 'Last Name'.tr,
|
||||
controller: controller.lastNameEditingController.value,
|
||||
hintText: 'Enter Last Name'.tr,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_user.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Email Address'.tr,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
controller: controller.emailEditingController.value,
|
||||
hintText: 'Enter Email Address'.tr,
|
||||
enable:
|
||||
controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty ? false : true,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_mail.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Phone Number'.tr,
|
||||
controller: controller.phoneNUmberEditingController.value,
|
||||
hintText: 'Enter Phone Number'.tr,
|
||||
textInputType: const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
prefix: CountryCodePicker(
|
||||
onChanged: (value) {
|
||||
controller.countryCodeEditingController.value.text = value.dialCode ?? Constant.defaultCountryCode;
|
||||
},
|
||||
dialogTextStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: AppThemeData.medium),
|
||||
dialogBackgroundColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
initialSelection: controller.countryCodeEditingController.value.text,
|
||||
comparator: (a, b) => b.name!.compareTo(a.name.toString()),
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
searchDecoration: InputDecoration(iconColor: isDark ? AppThemeData.grey50 : AppThemeData.grey900),
|
||||
searchStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.driverModel.value.id != null && controller.driverModel.value.id!.isNotEmpty
|
||||
? SizedBox()
|
||||
: Column(
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Password'.tr,
|
||||
controller: controller.passwordEditingController.value,
|
||||
hintText: 'Enter Password'.tr,
|
||||
obscureText: controller.passwordVisible.value,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_lock.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
suffix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.passwordVisible.value = !controller.passwordVisible.value;
|
||||
},
|
||||
child: controller.passwordVisible.value
|
||||
? SvgPicture.asset(
|
||||
"assets/icons/ic_password_show.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
"assets/icons/ic_password_close.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Confirm Password'.tr,
|
||||
controller: controller.conformPasswordEditingController.value,
|
||||
hintText: 'Enter Confirm Password'.tr,
|
||||
obscureText: controller.conformPasswordVisible.value,
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_lock.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
suffix: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.conformPasswordVisible.value = !controller.conformPasswordVisible.value;
|
||||
},
|
||||
child: controller.conformPasswordVisible.value
|
||||
? SvgPicture.asset(
|
||||
"assets/icons/ic_password_show.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
"assets/icons/ic_password_close.svg",
|
||||
colorFilter: ColorFilter.mode(
|
||||
isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (controller.firstNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter first name".tr);
|
||||
return;
|
||||
} else if (controller.lastNameEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter last name".tr);
|
||||
return;
|
||||
} else if (controller.emailEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter email address".tr);
|
||||
return;
|
||||
} else if (!GetUtils.isEmail(controller.emailEditingController.value.text)) {
|
||||
ShowToastDialog.showToast("Please enter valid email address".tr);
|
||||
return;
|
||||
} else if (controller.phoneNUmberEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter phone number".tr);
|
||||
return;
|
||||
} else if (controller.selectedZone.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select zone".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix: use OR (||) instead of AND (&&)
|
||||
if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
|
||||
controller.passwordEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter password".tr);
|
||||
return;
|
||||
} else if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
|
||||
controller.passwordEditingController.value.text.length < 6) {
|
||||
ShowToastDialog.showToast("Password must be at least 6 characters".tr);
|
||||
return;
|
||||
} else if ((controller.driverModel.value.id == null || controller.driverModel.value.id!.isEmpty) &&
|
||||
controller.conformPasswordEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter confirm password".tr);
|
||||
return;
|
||||
} else if (controller.passwordEditingController.value.text !=
|
||||
controller.conformPasswordEditingController.value.text) {
|
||||
ShowToastDialog.showToast("Password and confirm password do not match".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
//Vehicle validation if service is NOT Parcel Service
|
||||
if (controller.selectedService.value != "Parcel Service") {
|
||||
if (controller.selectedVehicleType.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select vehicle type".tr);
|
||||
return;
|
||||
} else if (controller.selectedCarMakes.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select car brand".tr);
|
||||
return;
|
||||
} else if (controller.selectedCarModel.value.id == null) {
|
||||
ShowToastDialog.showToast("Please select car model".tr);
|
||||
return;
|
||||
} else if (controller.carPlatNumberEditingController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter car plat number".tr);
|
||||
return;
|
||||
} else {
|
||||
//Will work now
|
||||
print("plz come..............");
|
||||
controller.signUp();
|
||||
}
|
||||
} else {
|
||||
//Parcel Service signup
|
||||
print("plz come signUp ..............");
|
||||
controller.signUp();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
'Save'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
86
lib/app/owner_screen/driver_location_screen.dart
Normal file
86
lib/app/owner_screen/driver_location_screen.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/driver_location_controller.dart';
|
||||
import 'package:driver/themes/theme_controller.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';
|
||||
|
||||
class DriverLocationScreen extends StatelessWidget {
|
||||
const DriverLocationScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: DriverLocationController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"Driver Locations",
|
||||
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()
|
||||
: Constant.selectedMapType == "osm"
|
||||
? Obx(() {
|
||||
// Schedule a post-frame callback to ensure the FlutterMap has been built
|
||||
// before we attempt to move the map to the driver's location.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
try {
|
||||
controller.animateToSource();
|
||||
} catch (_) {}
|
||||
});
|
||||
|
||||
return flutterMap.FlutterMap(
|
||||
mapController: controller.osmMapController,
|
||||
options: flutterMap.MapOptions(
|
||||
// center the OSM map on the controller's current position (updated by controller)
|
||||
initialCenter: controller.current.value,
|
||||
initialZoom: 12,
|
||||
),
|
||||
children: [
|
||||
flutterMap.TileLayer(
|
||||
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
subdomains: const ['a', 'b', 'c'],
|
||||
userAgentPackageName: 'com.emart.app',
|
||||
),
|
||||
flutterMap.MarkerLayer(markers: controller.osmMarkers),
|
||||
],
|
||||
);
|
||||
})
|
||||
: GoogleMap(
|
||||
initialCameraPosition: controller.driverList.isNotEmpty
|
||||
? CameraPosition(
|
||||
target: LatLng(controller.driverList.first.location == null ? 12.9716 : controller.driverList.first.location!.latitude!,
|
||||
controller.driverList.first.location == null ? 77.5946 : controller.driverList.first.location!.longitude!),
|
||||
zoom: 14,
|
||||
)
|
||||
: CameraPosition(
|
||||
target: LatLng(12.9716, 77.5946),
|
||||
zoom: 14,
|
||||
),
|
||||
myLocationEnabled: true,
|
||||
myLocationButtonEnabled: true,
|
||||
markers: controller.markers.toSet(),
|
||||
onMapCreated: (GoogleMapController mapController) {
|
||||
controller.mapController.complete(mapController);
|
||||
// Wait for markers to load
|
||||
Future.delayed(const Duration(milliseconds: 500), () async {
|
||||
await controller.moveCameraToFirstDriver(mapController);
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
51
lib/app/owner_screen/driver_order_list.dart
Normal file
51
lib/app/owner_screen/driver_order_list.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controllers/driver_order_controller.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import '../cab_screen/cab_order_list_screen.dart';
|
||||
import '../parcel_screen/parcel_order_list_screen.dart';
|
||||
import '../rental_service/rental_order_list_screen.dart';
|
||||
|
||||
class DriverOrderList extends StatelessWidget {
|
||||
const DriverOrderList({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<DriverOrderListController>(
|
||||
init: DriverOrderListController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"Driver Orders".tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
backgroundColor: isDark ? Colors.black : Colors.white,
|
||||
iconTheme: IconThemeData(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
body: _buildBody(controller.serviceType.value),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(String? serviceType) {
|
||||
switch (serviceType) {
|
||||
case "cab-service":
|
||||
return const CabOrderListScreen();
|
||||
case "parcel_delivery":
|
||||
return const ParcelOrderListScreen();
|
||||
case "rental-service":
|
||||
return const RentalOrderListScreen();
|
||||
default:
|
||||
return const Center(child: Text("Service type not supported"));
|
||||
}
|
||||
}
|
||||
}
|
||||
653
lib/app/owner_screen/owner_dashboard_screen.dart
Normal file
653
lib/app/owner_screen/owner_dashboard_screen.dart
Normal file
@@ -0,0 +1,653 @@
|
||||
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/owner_screen/driver_location_screen.dart';
|
||||
import 'package:driver/app/owner_screen/owner_home_screen.dart';
|
||||
import 'package:driver/app/terms_and_condition/terms_and_condition_screen.dart';
|
||||
import 'package:driver/app/verification_screen/verification_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/wallet_screen.dart';
|
||||
import 'package:driver/app/withdraw_method_setup_screens/withdraw_method_setup_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/owner_dashboard_controller.dart';
|
||||
import 'package:driver/services/audio_player_service.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/custom_dialog_box.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import 'owner_order_list.dart';
|
||||
|
||||
class OwnerDashboardScreen extends StatelessWidget {
|
||||
const OwnerDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: OwnerDashboardController(),
|
||||
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: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => const DriverLocationScreen());
|
||||
},
|
||||
child: SvgPicture.asset("assets/icons/ic_location_pin.svg")),
|
||||
const SizedBox(
|
||||
width: 14,
|
||||
),
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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 OwnerHomeScreen()
|
||||
: controller.drawerIndex.value == 1
|
||||
? OwnerOrderListScreen()
|
||||
: 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(() {
|
||||
var isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: OwnerDashboardController(),
|
||||
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,
|
||||
),
|
||||
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;
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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;
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: Constant.userModel?.vendorID?.isEmpty == true,
|
||||
child: 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.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(),
|
||||
Visibility(
|
||||
visible: false,
|
||||
child: 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
436
lib/app/owner_screen/owner_home_screen.dart
Normal file
436
lib/app/owner_screen/owner_home_screen.dart
Normal file
@@ -0,0 +1,436 @@
|
||||
import 'package:driver/app/owner_screen/driver_create_screen.dart';
|
||||
import 'package:driver/app/owner_screen/view_all_drivers.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/owner_dashboard_controller.dart';
|
||||
import 'package:driver/controllers/owner_home_controller.dart';
|
||||
import 'package:driver/models/user_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/theme_controller.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'driver_order_list.dart';
|
||||
|
||||
class OwnerHomeScreen extends StatelessWidget {
|
||||
const OwnerHomeScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final dashController = Get.put(OwnerDashboardController());
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: OwnerHomeController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Constant.isOwnerVerification == 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: () {
|
||||
OwnerDashboardController dashBoardController = Get.put(OwnerDashboardController());
|
||||
dashBoardController.drawerIndex.value = 4;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
num wallet = dashController.userModel.value.walletAmount ?? 0.0;
|
||||
return wallet < double.parse(Constant.ownerMinimumDepositToRideAccept)
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 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 a minimum of ${Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept.toString())} in your wallet to receive orders to your driver"
|
||||
.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.danger300,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox();
|
||||
}),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.homePageGradiant[0],
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_ride.svg"),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
controller.totalRidesAllDrivers.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
'Total Bookings'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.homePageGradiant[1],
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_total_ride.svg"),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
'${controller.driverList.length} ',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
'Total Drivers'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.homePageGradiant[2],
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_earning.svg"),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
'${Constant.currencyModel!.symbol.toString()}${controller.totalEarningsAllDrivers.toStringAsFixed(2)}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
'Earnings'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
controller.driverList.isEmpty
|
||||
? SizedBox()
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Your Available Drivers'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Real-time status and earnings summary'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(ViewAllDriverScreen())!.then(
|
||||
(value) {
|
||||
controller.getDriverList();
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'View all'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.primary300 : AppThemeData.primary300, decoration: TextDecoration.underline),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
),
|
||||
),
|
||||
child: ListView.builder(
|
||||
// itemCount: controller.driverList.length,
|
||||
// physics: NeverScrollableScrollPhysics(),
|
||||
// shrinkWrap: true,
|
||||
itemCount: controller.driverList.length > 5 ? 5 : controller.driverList.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
UserModel driverModel = controller.driverList[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: driverModel.profilePictureURL.toString(),
|
||||
height: 42,
|
||||
width: 42,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
driverModel.fullName(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${driverModel.countryCode} ${driverModel.phoneNumber}',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: driverModel.isActive == false ? "Offline" : "Online".tr,
|
||||
height: 3.5,
|
||||
width: 18,
|
||||
borderRadius: 10,
|
||||
color: driverModel.isActive == false ? AppThemeData.danger300 : AppThemeData.success300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {},
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
padding: EdgeInsets.zero,
|
||||
onSelected: (value) {
|
||||
if (value == 'Edit Driver') {
|
||||
Get.to(DriverCreateScreen(), arguments: {"driverModel": driverModel})!.then(
|
||||
(value0) {
|
||||
if (value0 == true) {
|
||||
controller.getDriverList();
|
||||
}
|
||||
},
|
||||
);
|
||||
} else if (value == 'Delete Driver') {
|
||||
controller.deleteDriver(driverModel.id.toString());
|
||||
} else if (value == 'View All Order') {
|
||||
print("driver ::::::: ${driverModel.email}");
|
||||
Get.to(() => const DriverOrderList(), arguments: {
|
||||
"driverId": driverModel.id,
|
||||
"serviceType": driverModel.serviceType,
|
||||
});
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||
PopupMenuItem<String>(
|
||||
value: 'Edit Driver',
|
||||
child: Text('Edit Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Delete Driver',
|
||||
child: Text('Delete Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'View All Order',
|
||||
child: Text('View All Order'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
],
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
icon: Icon(Icons.more_vert, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900), // Three dots icon
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
floatingActionButton: Constant.userModel!.isDocumentVerify == true
|
||||
? ClipOval(
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
Get.to(DriverCreateScreen())!.then((value) {
|
||||
if (value == true) {
|
||||
controller.getDriverList();
|
||||
}
|
||||
});
|
||||
},
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: AppThemeData.grey50,
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
669
lib/app/owner_screen/owner_order_list.dart
Normal file
669
lib/app/owner_screen/owner_order_list.dart
Normal file
@@ -0,0 +1,669 @@
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/owner_order_list_controller.dart';
|
||||
import '../../models/cab_order_model.dart';
|
||||
import '../../models/rental_order_model.dart';
|
||||
import '../../models/user_model.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/round_button_fill.dart';
|
||||
import '../cab_screen/cab_order_details.dart';
|
||||
import '../parcel_screen/parcel_order_details.dart';
|
||||
import '../rental_service/rental_order_details_screen.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
class OwnerOrderListScreen extends StatelessWidget {
|
||||
const OwnerOrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<OwnerOrderListController>(
|
||||
init: OwnerOrderListController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Select Service Type", style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonFormField<String>(
|
||||
initialValue: controller.selectedService.value,
|
||||
style: TextStyle(
|
||||
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
dropdownColor: themeController.isDark.value ? AppThemeData.grey800 : AppThemeData.grey50,
|
||||
items: controller.serviceList.map((service) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: service,
|
||||
child: Text(
|
||||
service,
|
||||
style: TextStyle(
|
||||
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
controller.selectedService.value = value!;
|
||||
controller.selectedDriver.value = null;
|
||||
controller.isDriverSelected.value = false;
|
||||
},
|
||||
decoration: _dropdownDecoration(themeController.isDark.value),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text("Select Driver", style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
const SizedBox(height: 5),
|
||||
Obx(() => DropdownButtonFormField<UserModel?>(
|
||||
initialValue: controller.selectedDriver.value,
|
||||
hint: Text("Select Driver",
|
||||
style: TextStyle(
|
||||
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
)),
|
||||
items: [
|
||||
const DropdownMenuItem<UserModel?>(
|
||||
value: null,
|
||||
child: Text("All Drivers"),
|
||||
),
|
||||
...controller.filteredDrivers.map((driver) {
|
||||
return DropdownMenuItem<UserModel?>(
|
||||
value: driver,
|
||||
child: Text(
|
||||
"${driver.firstName ?? ''} ${driver.lastName ?? ''}",
|
||||
style: TextStyle(
|
||||
color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
onChanged: (UserModel? value) {
|
||||
controller.selectedDriver.value = value;
|
||||
},
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
decoration: _dropdownDecoration(themeController.isDark.value),
|
||||
)),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// --- Search Button ---
|
||||
RoundedButtonFill(
|
||||
title: "Search",
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: controller.searchOrders,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
switch (controller.serviceKey.value) {
|
||||
case 'cab-service':
|
||||
return cabListView(controller, isDark);
|
||||
case 'parcel_delivery':
|
||||
return parcleListView(controller, isDark);
|
||||
case 'rental-service':
|
||||
return rentalListView(controller, isDark);
|
||||
default:
|
||||
return const Center(child: Text("Service type not supported"));
|
||||
}
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
InputDecoration _dropdownDecoration(bool isDark) {
|
||||
return InputDecoration(
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: AppThemeData.primary300, width: 1.2),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DefaultTabController cabListView(OwnerOrderListController controller, bool isDark) {
|
||||
return DefaultTabController(
|
||||
length: controller.cabTabTitles.length,
|
||||
initialIndex: controller.cabTabTitles.indexOf(controller.cabSelectedTab.value),
|
||||
child: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.cabSelectedTab(controller.cabTabTitles[index]);
|
||||
},
|
||||
// isScrollable: true,
|
||||
indicatorColor: AppThemeData.primary300,
|
||||
labelColor: AppThemeData.primary300,
|
||||
dividerColor: Colors.transparent,
|
||||
unselectedLabelColor: AppThemeData.primary300.withOpacity(0.60),
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 14),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 14),
|
||||
tabs: controller.cabTabTitles.map((title) => Tab(child: Center(child: Text(title)))).toList(),
|
||||
),
|
||||
|
||||
// Body: loader or TabBarView
|
||||
Expanded(
|
||||
child: controller.isLoadingCab.value
|
||||
? Constant.loader()
|
||||
: TabBarView(
|
||||
children: controller.cabTabTitles.map((title) {
|
||||
final orders = controller.getCabOrdersForTab(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.only(top: 10),
|
||||
itemCount: orders.length,
|
||||
itemBuilder: (context, index) {
|
||||
CabOrderModel order = orders[index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() => CabOrderDetails(), arguments: {"cabOrderModel": 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: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Icon(Icons.stop_circle_outlined, color: Colors.green),
|
||||
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: 55),
|
||||
),
|
||||
Icon(Icons.radio_button_checked, color: Colors.red),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Source Location Name
|
||||
Expanded(
|
||||
child: Text(
|
||||
order.sourceLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: AppThemeData.warning300, width: 1),
|
||||
color: AppThemeData.warning50,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
child: Text(
|
||||
order.status.toString(),
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.warning500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
DottedBorder(
|
||||
options: CustomPathDottedBorderOptions(
|
||||
color: Colors.grey.shade400,
|
||||
strokeWidth: 2,
|
||||
dashPattern: [4, 4],
|
||||
customPath: (size) => Path()
|
||||
..moveTo(0, size.height / 2) // start from left center
|
||||
..lineTo(size.width, size.height / 2), // draw to right center
|
||||
),
|
||||
child: const SizedBox(width: 295, height: 3),
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
Text(
|
||||
order.destinationLocationName.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DefaultTabController parcleListView(OwnerOrderListController controller, bool isDark) {
|
||||
return DefaultTabController(
|
||||
length: controller.parcelTabTitles.length,
|
||||
initialIndex: controller.parcelTabTitles.indexOf(controller.parcelSelectedTab.value),
|
||||
child: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.parcelSelectedTab(controller.parcelTabTitles[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.parcelTabTitles.map((title) => Tab(child: Text(title))).toList(),
|
||||
),
|
||||
|
||||
// Body: loader or TabBarView
|
||||
Expanded(
|
||||
child: controller.isLoadingParcel.value
|
||||
? Constant.loader()
|
||||
: TabBarView(
|
||||
children: controller.parcelTabTitles.map((title) {
|
||||
// filter by tab using controller helper
|
||||
final orders = controller.getParcelOrdersForTab(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.only(top: 10),
|
||||
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)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
DefaultTabController rentalListView(OwnerOrderListController controller, bool isDark) {
|
||||
return DefaultTabController(
|
||||
length: controller.rentalTabTitles.length,
|
||||
initialIndex: controller.rentalTabTitles.indexOf(controller.rentalSelectedTab.value),
|
||||
child: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.rentalSelectedTab(controller.rentalTabTitles[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.rentalTabTitles.map((title) => Tab(child: Text(title))).toList(),
|
||||
),
|
||||
|
||||
// Body: loader or TabBarView
|
||||
Expanded(
|
||||
child: controller.isLoadingRental.value
|
||||
? Constant.loader()
|
||||
: TabBarView(
|
||||
children: controller.rentalTabTitles.map((title) {
|
||||
// filter by tab using controller helper
|
||||
final orders = controller.getRentalOrdersForTab(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.only(top: 10),
|
||||
itemCount: orders.length,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel order = orders[index]; //use this
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(), arguments: {"rentalOrder": order.id});
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Image.asset("assets/icons/pickup.png", height: 18, width: 18)),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
//prevents overflow
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
//text wraps if too long
|
||||
child: Text(
|
||||
order.sourceLocationName ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
overflow: TextOverflow.ellipsis, //safe cutoff
|
||||
maxLines: 2,
|
||||
),
|
||||
),
|
||||
if (order.status != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.info50,
|
||||
border: Border.all(color: AppThemeData.info300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(order.status ?? '',
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
if (order.bookingDateTime != null)
|
||||
Text(
|
||||
Constant.timestampToDateTime(order.bookingDateTime!),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text("Vehicle Type :".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: order.rentalVehicleType?.rentalVehicleIcon ?? Constant.placeHolderImage,
|
||||
height: 60,
|
||||
width: 60,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(AppThemeData.primary300),
|
||||
),
|
||||
),
|
||||
errorWidget: (context, url, error) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${order.rentalVehicleType!.name}",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2.0),
|
||||
child: Text(
|
||||
"${order.rentalVehicleType!.shortDescription}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Package info :",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
order.rentalPackageModel!.name.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
order.rentalPackageModel!.description.toString(),
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
Constant.amountShow(amount: order.rentalPackageModel!.baseFare.toString()),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
127
lib/app/owner_screen/view_all_drivers.dart
Normal file
127
lib/app/owner_screen/view_all_drivers.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
import 'package:driver/app/owner_screen/driver_create_screen.dart';
|
||||
import 'package:driver/app/owner_screen/driver_order_list.dart';
|
||||
import 'package:driver/controllers/owner_home_controller.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:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class ViewAllDriverScreen extends StatelessWidget {
|
||||
const ViewAllDriverScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<OwnerHomeController>(
|
||||
init: Get.find<OwnerHomeController>(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("All Drivers".tr),
|
||||
),
|
||||
body: controller.driverList.isEmpty
|
||||
? Center(child: Text("No drivers found".tr))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.all(10),
|
||||
itemCount: controller.driverList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final driver = controller.driverList[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: driver.profilePictureURL ?? '',
|
||||
height: 42,
|
||||
width: 42,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
driver.fullName(),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${driver.countryCode ?? ''} ${driver.phoneNumber ?? ''}',
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: driver.isActive == false ? "Offline" : "Online".tr,
|
||||
height: 3.5,
|
||||
width: 18,
|
||||
borderRadius: 10,
|
||||
color: driver.isActive == false ? AppThemeData.danger300 : AppThemeData.success300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () {},
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) {
|
||||
if (value == 'Edit Driver') {
|
||||
Get.to(() => const DriverCreateScreen(), arguments: {"driverModel": driver})?.then((value0) {
|
||||
if (value0 == true) controller.getDriverList();
|
||||
});
|
||||
} else if (value == 'Delete Driver') {
|
||||
controller.deleteDriver(driver.id.toString());
|
||||
} else if (value == 'View All Order') {
|
||||
Get.to(() => const DriverOrderList(), arguments: {
|
||||
"driverId": driver.id,
|
||||
"serviceType": driver.serviceType,
|
||||
});
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||
PopupMenuItem<String>(
|
||||
value: 'Edit Driver',
|
||||
child: Text('Edit Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Delete Driver',
|
||||
child: Text('Delete Driver'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'View All Order',
|
||||
child: Text('View All Order'.tr, style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.greyDark50)),
|
||||
),
|
||||
],
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
icon: Icon(Icons.more_vert, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
336
lib/app/rental_service/rental_booking_search_screen.dart
Normal file
336
lib/app/rental_service/rental_booking_search_screen.dart
Normal file
@@ -0,0 +1,336 @@
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/rental_booking_search_controller.dart';
|
||||
import 'package:driver/models/rental_order_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/round_button_fill.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
class RentalBookingSearchScreen extends StatelessWidget {
|
||||
const RentalBookingSearchScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalBookingSearchController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
titleSpacing: 0,
|
||||
centerTitle: false,
|
||||
),
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: controller.rentalBookingData.isEmpty
|
||||
? Constant.showEmptyView(message: "No Rental booking available", isDark: isDark)
|
||||
: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.rentalBookingData.length,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel rentalBookingData = controller.rentalBookingData[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(), arguments: {"rentalOrder": rentalBookingData.id});
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
ClipOval(
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: rentalBookingData.author!.profilePictureURL.toString(),
|
||||
width: 52,
|
||||
height: 52,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${rentalBookingData.author!.firstName} ${rentalBookingData.author!.lastName}'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Timeline.tileBuilder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
theme: TimelineThemeData(
|
||||
nodePosition: 0,
|
||||
// indicatorPosition: 0,
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
contentsAlign: ContentsAlign.basic,
|
||||
indicatorBuilder: (context, index) {
|
||||
return SvgPicture.asset("assets/icons/ic_location.svg");
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return DashedLineConnector(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
gap: 4,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
child: Text(
|
||||
"${rentalBookingData.sourceLocationName}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Package Details:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.name}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Distance:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedDistance} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Duration:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedHours} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_amount.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: rentalBookingData.subTotal).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_date.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(rentalBookingData.bookingDateTime!).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Reject".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
textColor: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500,
|
||||
onPress: () async {
|
||||
ShowToastDialog.showLoader("Rejecting booking...".tr);
|
||||
rentalBookingData.rejectedByDrivers!.add(FireStoreUtils.getCurrentUid());
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking rejected successfully".tr);
|
||||
controller.getRentalSearchBooking();
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Accept".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.driverModel.value.ownerId != null &&
|
||||
controller.driverModel.value.ownerId!.isNotEmpty) {
|
||||
if (controller.ownerModel.value.walletAmount != null &&
|
||||
controller.ownerModel.value.walletAmount! >=
|
||||
double.parse(Constant.minimumDepositToRideAccept)) {
|
||||
ShowToastDialog.showLoader("Accepting booking...".tr);
|
||||
rentalBookingData.status = Constant.driverAccepted;
|
||||
rentalBookingData.driverId = FireStoreUtils.getCurrentUid();
|
||||
rentalBookingData.driver = Constant.userModel;
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking accepted successfully".tr);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum ${Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)} wallet balance to accept the rental booking. Please contact your owner"
|
||||
.tr);
|
||||
}
|
||||
} else {
|
||||
if (controller.driverModel.value.walletAmount! >=
|
||||
double.parse(Constant.minimumDepositToRideAccept)) {
|
||||
ShowToastDialog.showLoader("Accepting booking...".tr);
|
||||
rentalBookingData.status = Constant.driverAccepted;
|
||||
rentalBookingData.driverId = FireStoreUtils.getCurrentUid();
|
||||
rentalBookingData.driver = Constant.userModel;
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData);
|
||||
Get.back(result: true);
|
||||
ShowToastDialog.showToast("Booking accepted successfully".tr);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Your owner has to maintain minimum @amount wallet balance to accept the rental booking. Please contact your owner"
|
||||
.trParams({"amount": Constant.amountShow(amount: Constant.ownerMinimumDepositToRideAccept)}));
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
700
lib/app/rental_service/rental_dashboard_screen.dart
Normal file
700
lib/app/rental_service/rental_dashboard_screen.dart
Normal file
@@ -0,0 +1,700 @@
|
||||
import 'package:driver/app/auth_screen/login_screen.dart';
|
||||
import 'package:driver/app/change%20langauge/change_language_screen.dart';
|
||||
import 'package:driver/app/chat_screens/driver_inbox_screen.dart';
|
||||
import 'package:driver/app/edit_profile_screen/edit_profile_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_home_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_order_list_screen.dart';
|
||||
import 'package:driver/app/terms_and_condition/terms_and_condition_screen.dart';
|
||||
import 'package:driver/app/verification_screen/verification_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/wallet_screen.dart';
|
||||
import 'package:driver/app/withdraw_method_setup_screens/withdraw_method_setup_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/rental_dashboard_controller.dart';
|
||||
import 'package:driver/services/audio_player_service.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/custom_dialog_box.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import '../vehicle_information_screen/vehicle_information_screen.dart';
|
||||
|
||||
class RentalDashboardScreen extends StatelessWidget {
|
||||
const RentalDashboardScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalDashboardController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
drawerEnableOpenDragGesture: false,
|
||||
appBar: AppBar(
|
||||
//backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
titleSpacing: 5,
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Welcome Back 👋'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.userModel!.fullName().tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: InkWell(
|
||||
onTap: () {
|
||||
Get.to(const WalletScreen(isAppBarShow: true));
|
||||
},
|
||||
child: SvgPicture.asset("assets/icons/ic_wallet_home.svg")),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(const EditProfileScreen());
|
||||
},
|
||||
child: SvgPicture.asset("assets/icons/ic_user_business.svg")),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
],
|
||||
leading: Builder(builder: (context) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.carRent600 : AppThemeData.carRent50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: SvgPicture.asset("assets/icons/ic_drawer_open.svg"),
|
||||
)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
drawer: const DrawerView(),
|
||||
body: controller.drawerIndex.value == 0
|
||||
? const RentalHomeScreen()
|
||||
: controller.drawerIndex.value == 1
|
||||
? RentalOrderListScreen()
|
||||
: controller.drawerIndex.value == 2
|
||||
? const WalletScreen(
|
||||
isAppBarShow: false,
|
||||
)
|
||||
: controller.drawerIndex.value == 3
|
||||
? const WithdrawMethodSetupScreen()
|
||||
: controller.drawerIndex.value == 4
|
||||
? const VerificationScreen()
|
||||
: controller.drawerIndex.value == 5
|
||||
? const DriverInboxScreen()
|
||||
: controller.drawerIndex.value == 6
|
||||
? const VehicleInformationScreen()
|
||||
: controller.drawerIndex.value == 7
|
||||
? const ChangeLanguageScreen()
|
||||
: controller.drawerIndex.value == 8
|
||||
? const TermsAndConditionScreen(type: "temsandcondition")
|
||||
: const TermsAndConditionScreen(type: "privacy"),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerView extends StatelessWidget {
|
||||
const DrawerView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
var isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalDashboardController(),
|
||||
builder: (controller) {
|
||||
return Drawer(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top + 20, left: 16, right: 16),
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: [
|
||||
ClipOval(
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: Constant.userModel == null ? "" : Constant.userModel!.profilePictureURL.toString(),
|
||||
height: 55,
|
||||
width: 55,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
Constant.userModel!.fullName().tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 18,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${Constant.userModel!.email}'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.regular,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
trailing: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: CupertinoSwitch(
|
||||
value: controller.userModel.value.isActive ?? false,
|
||||
activeTrackColor: AppThemeData.primary300,
|
||||
onChanged: (value) async {
|
||||
if (Constant.isDriverVerification == true) {
|
||||
if (controller.userModel.value.isDocumentVerify == true) {
|
||||
controller.userModel.value.isActive = value;
|
||||
if (controller.userModel.value.isActive == true) {
|
||||
controller.updateCurrentLocation();
|
||||
}
|
||||
await FireStoreUtils.updateUser(controller.userModel.value);
|
||||
} else {
|
||||
ShowToastDialog.showToast("Document verification is pending. Please proceed to set up your document verification.".tr);
|
||||
}
|
||||
} else {
|
||||
controller.userModel.value.isActive = value;
|
||||
if (controller.userModel.value.isActive == true) {
|
||||
controller.updateCurrentLocation();
|
||||
}
|
||||
await FireStoreUtils.updateUser(controller.userModel.value);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Available Status'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'About App'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_home_add.svg",
|
||||
width: 20,
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Home'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 0;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_shoping_cart.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Orders'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 1;
|
||||
},
|
||||
),
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_wallet.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Wallet'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 2;
|
||||
},
|
||||
),
|
||||
Constant.userModel!.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty
|
||||
? SizedBox()
|
||||
: ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_settings.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Withdrawal Method'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 3;
|
||||
},
|
||||
),
|
||||
(((Constant.userModel?.ownerId == null || Constant.userModel!.ownerId!.isEmpty) && Constant.isDriverVerification == true) &&
|
||||
!((Constant.userModel?.ownerId != null && Constant.userModel!.ownerId!.isNotEmpty && Constant.isOwnerVerification == true)))
|
||||
? ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset("assets/icons/ic_notes.svg"),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Document Verification'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 4;
|
||||
},
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: Icon(Icons.car_crash),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Vehicle Information'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 6;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_chat.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Inbox'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 5;
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'App Preferences'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_change_language.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Change Language'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 7;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_light_dark.svg",
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: CupertinoSwitch(
|
||||
value: controller.isDarkModeSwitch.value,
|
||||
activeTrackColor: AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.toggleDarkMode(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Dark Mode'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Social'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_share.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Share app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Share.share(
|
||||
'${'Check out eMart, your ultimate food delivery application!'.tr} \n\n${'Google Play:'.tr} ${Constant.googlePlayLink} \n\n${'App Store:'.tr} ${Constant.appStoreLink}',
|
||||
subject: 'Look what I made!'.tr);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_rate.svg",
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Rate the app'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
final InAppReview inAppReview = InAppReview.instance;
|
||||
inAppReview.requestReview();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Legal'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey400 : AppThemeData.grey500,
|
||||
fontSize: 12,
|
||||
fontFamily: AppThemeData.medium,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_terms_condition.svg",
|
||||
colorFilter: ColorFilter.mode(AppThemeData.primary300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Terms and Conditions'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 8;
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_privacyPolicy.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right_rounded, size: 24),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Privacy Policy'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
controller.drawerIndex.value = 8;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: const VisualDensity(horizontal: 0, vertical: -2),
|
||||
contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0),
|
||||
leading: SvgPicture.asset(
|
||||
"assets/icons/ic_logout.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
trailing: const Icon(
|
||||
Icons.keyboard_arrow_right_rounded,
|
||||
size: 24,
|
||||
color: AppThemeData.danger300,
|
||||
),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'Log out'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CustomDialogBox(
|
||||
title: "Log out".tr,
|
||||
descriptions: "Are you sure you want to log out? You will need to enter your credentials to log back in.".tr,
|
||||
positiveString: "Log out".tr,
|
||||
negativeString: "Cancel".tr,
|
||||
positiveClick: () async {
|
||||
await AudioPlayerService.playSound(false);
|
||||
Constant.userModel!.fcmToken = "";
|
||||
await FireStoreUtils.updateUser(Constant.userModel!);
|
||||
await FirebaseAuth.instance.signOut();
|
||||
Get.offAll(const LoginScreen());
|
||||
},
|
||||
negativeClick: () {
|
||||
Get.back();
|
||||
},
|
||||
img: Image.asset(
|
||||
'assets/images/ic_logout.gif',
|
||||
height: 50,
|
||||
width: 50,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CustomDialogBox(
|
||||
title: "Delete Account".tr,
|
||||
descriptions: "Are you sure you want to delete your account? This action is irreversible and will permanently remove all your data.".tr,
|
||||
positiveString: "Delete".tr,
|
||||
negativeString: "Cancel".tr,
|
||||
positiveClick: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
await FireStoreUtils.deleteUser().then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
if (value == true) {
|
||||
ShowToastDialog.showToast("Account deleted successfully".tr);
|
||||
Get.offAll(const LoginScreen());
|
||||
} else {
|
||||
ShowToastDialog.showToast("Contact Administrator".tr);
|
||||
}
|
||||
});
|
||||
},
|
||||
negativeClick: () {
|
||||
Get.back();
|
||||
},
|
||||
img: Image.asset(
|
||||
'assets/icons/delete_dialog.gif',
|
||||
height: 50,
|
||||
width: 50,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/icons/ic_delete.svg",
|
||||
colorFilter: const ColorFilter.mode(AppThemeData.danger300, BlendMode.srcIn),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
'Delete Account'.tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.danger300 : AppThemeData.danger300,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
"V : ${Constant.appVersion}",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
902
lib/app/rental_service/rental_home_screen.dart
Normal file
902
lib/app/rental_service/rental_home_screen.dart
Normal file
@@ -0,0 +1,902 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:driver/app/rental_service/rental_booking_search_screen.dart';
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:driver/app/wallet_screen/payment_list_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/send_notification.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/rental_dashboard_controller.dart';
|
||||
import 'package:driver/controllers/rental_home_controller.dart';
|
||||
import 'package:driver/models/rental_order_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/round_button_fill.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:driver/widget/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
import 'package:timelines_plus/timelines_plus.dart';
|
||||
|
||||
import '../../models/user_model.dart';
|
||||
import '../chat_screens/chat_screen.dart';
|
||||
|
||||
class RentalHomeScreen extends StatelessWidget {
|
||||
const RentalHomeScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalHomeController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Constant.isDriverVerification == true && Constant.userModel!.isDocumentVerify == false
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: SvgPicture.asset("assets/icons/ic_document.svg"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text(
|
||||
"Document Verification in Pending".tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontSize: 22,
|
||||
fontFamily: AppThemeData.semiBold),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"Your documents are being reviewed. We will notify you once the verification is complete.".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey500,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "View Status".tr,
|
||||
width: 55,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
RentalDashboardController dashBoardController = Get.put(RentalDashboardController());
|
||||
dashBoardController.drawerIndex.value = 4;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: controller.userModel.value.isActive == false
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/empty_parcel.svg"),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'You’re Currently Offline'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
'Switch to online mode to accept and deliver rental orders.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: controller.rentalBookingData.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
final user = controller.userModel.value;
|
||||
final controllerOwner = controller.ownerModel.value;
|
||||
|
||||
final num wallet = user.walletAmount ?? 0.0;
|
||||
final num ownerWallet = controllerOwner.walletAmount ?? 0.0;
|
||||
final String? ownerId = user.ownerId;
|
||||
|
||||
final num minDeposit = double.parse(Constant.minimumDepositToRideAccept);
|
||||
|
||||
// 🧠 Logic:
|
||||
// If individual driver → check driver's own wallet
|
||||
// If owner driver → check owner's wallet
|
||||
if ((ownerId == null || ownerId.isEmpty) && wallet < minDeposit) {
|
||||
// Individual driver case
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.danger50,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"${'You must have at least'.tr} ${Constant.amountShow(amount: Constant.minimumDepositToRideAccept.toString())} ${'in your wallet to receive orders'.tr}",
|
||||
style: TextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (ownerId != null && ownerId.isNotEmpty && ownerWallet < minDeposit) {
|
||||
// Owner-driver case
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.danger50,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Your owner doesn't have the minimum wallet amount to receive orders. Please contact your owner."
|
||||
.tr,
|
||||
style: TextStyle(
|
||||
color: AppThemeData.grey900,
|
||||
fontSize: 14,
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
}),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/empty_parcel.svg"),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
'No rental requests available in your selected zone.'.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 18,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Search Rental Booking".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () {
|
||||
Get.to(RentalBookingSearchScreen());
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(RentalBookingSearchScreen());
|
||||
},
|
||||
child: TextFieldWidget(
|
||||
hintText: 'Search new ride'.tr,
|
||||
enable: false,
|
||||
controller: null,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.getBookingData();
|
||||
},
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: controller.rentalBookingData.length,
|
||||
padding: EdgeInsetsGeometry.zero,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel rentalBookingData = controller.rentalBookingData[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(),
|
||||
arguments: {"rentalOrder": rentalBookingData.id});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
// Author profile image
|
||||
ClipOval(
|
||||
child: rentalBookingData.author?.profilePictureURL != null
|
||||
? NetworkImageWidget(
|
||||
imageUrl: rentalBookingData.author!.profilePictureURL!,
|
||||
width: 52,
|
||||
height: 52,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey300,
|
||||
child: Icon(Icons.person, color: Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${rentalBookingData.author?.firstName ?? ''} ${rentalBookingData.author?.lastName ?? ''}'
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
// Phone and Chat buttons if status matches
|
||||
if (rentalBookingData.status == Constant.driverAccepted ||
|
||||
rentalBookingData.status == Constant.orderShipped)
|
||||
Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (rentalBookingData.author?.phoneNumber != null) {
|
||||
Constant.makePhoneCall(rentalBookingData.author!.phoneNumber!);
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
"assets/icons/ic_phone_dial.svg",
|
||||
width: 36,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer = await FireStoreUtils.getUserProfile(
|
||||
rentalBookingData.authorID ?? '');
|
||||
UserModel? driver = await FireStoreUtils.getUserProfile(
|
||||
rentalBookingData.driverId ?? '');
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
if (customer != null && driver != null) {
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer.fullName(),
|
||||
"restaurantName": driver.fullName(),
|
||||
"orderId": rentalBookingData.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
} else {
|
||||
ShowToastDialog.showToast("User not found");
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 42,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_wechat.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.greyDark100 : AppThemeData.grey100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Timeline.tileBuilder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
theme: TimelineThemeData(
|
||||
nodePosition: 0,
|
||||
// indicatorPosition: 0,
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
contentsAlign: ContentsAlign.basic,
|
||||
indicatorBuilder: (context, index) {
|
||||
return SvgPicture.asset("assets/icons/ic_location.svg");
|
||||
},
|
||||
connectorBuilder: (context, index, connectorType) {
|
||||
return DashedLineConnector(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300,
|
||||
gap: 4,
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
child: Text(
|
||||
"${rentalBookingData.sourceLocationName}",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
DottedLine(
|
||||
dashColor: Colors.grey,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashGapLength: 3.0,
|
||||
direction: Axis.horizontal,
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Package Details:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.name}".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Distance:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedDistance} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Including Duration:".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${rentalBookingData.rentalPackageModel!.includedHours} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color:
|
||||
isDark ? AppThemeData.primary300 : AppThemeData.primary300),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_amount.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(amount: rentalBookingData.subTotal).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/icons/ic_date.svg"),
|
||||
SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
Constant.timestampToDate(rentalBookingData.bookingDateTime!).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
rentalBookingData.status == Constant.driverAccepted
|
||||
? RoundedButtonFill(
|
||||
title: "Reached Location".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
showVerifyRentalPassengerDialog(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
},
|
||||
)
|
||||
: rentalBookingData.status == Constant.orderInTransit &&
|
||||
double.parse(rentalBookingData.endKitoMetersReading.toString()) <
|
||||
double.parse(rentalBookingData.startKitoMetersReading.toString())
|
||||
? RoundedButtonFill(
|
||||
title: "Set Final kilometers".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
setFinalKilometerDialog(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
},
|
||||
)
|
||||
: rentalBookingData.paymentStatus == true
|
||||
? RoundedButtonFill(
|
||||
title: "Complete Booking".tr,
|
||||
height: 5.5,
|
||||
color: isDark ? AppThemeData.success500 : AppThemeData.success500,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
controller.completeParcel(rentalBookingData);
|
||||
},
|
||||
)
|
||||
: RoundedButtonFill(
|
||||
title: rentalBookingData.paymentMethod == PaymentGateway.cod.name
|
||||
? "Confirm cash payment".tr
|
||||
: "Payment Pending".tr,
|
||||
height: 5.5,
|
||||
color: rentalBookingData.paymentMethod == PaymentGateway.cod.name
|
||||
? AppThemeData.success500
|
||||
: isDark
|
||||
? AppThemeData.dangerDark300
|
||||
: AppThemeData.dangerDark300,
|
||||
textColor: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (rentalBookingData.paymentMethod == PaymentGateway.cod.name) {
|
||||
conformCashPayment(
|
||||
context, isDark, controller, rentalBookingData);
|
||||
} else {
|
||||
ShowToastDialog.showToast(
|
||||
"Please collect the payment from the customer through the app.");
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void showVerifyRentalPassengerDialog(
|
||||
BuildContext context,
|
||||
bool isDark,
|
||||
RentalHomeController controller,
|
||||
RentalOrderModel rentalBookingData,
|
||||
) {
|
||||
Rx<TextEditingController> otpController = TextEditingController().obs;
|
||||
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(90, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
Constant.enableOTPTripStartForRental == false ? "Trip Start" : "Verify Passenger".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 22,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () => Get.back(),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Constant.enableOTPTripStartForRental == false
|
||||
? const SizedBox()
|
||||
: Text(
|
||||
"Enter the OTP shared by the customer to begin the trip".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey600,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
TextFieldWidget(
|
||||
controller: controller.currentKilometerController.value,
|
||||
hintText: 'Enter Current Kilometer reading'.tr,
|
||||
title: 'Current Kilometer reading'.tr,
|
||||
enable: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Constant.enableOTPTripStartForRental == false
|
||||
? const SizedBox()
|
||||
: PinCodeTextField(
|
||||
length: 4,
|
||||
appContext: context,
|
||||
keyboardType: const TextInputType.numberWithOptions(signed: true, decimal: true),
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
enablePinAutofill: true,
|
||||
hintCharacter: "-",
|
||||
hintStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey700,
|
||||
),
|
||||
textStyle: TextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
pinTheme: PinTheme(
|
||||
fieldHeight: 50,
|
||||
fieldWidth: 50,
|
||||
inactiveFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
selectedFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
activeFillColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
inactiveColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
disabledColor: isDark ? AppThemeData.grey800 : AppThemeData.grey100,
|
||||
selectedColor: AppThemeData.primary300,
|
||||
activeColor: AppThemeData.primary300,
|
||||
shape: PinCodeFieldShape.box,
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
cursorColor: AppThemeData.primary300,
|
||||
enableActiveFill: true,
|
||||
controller: otpController.value,
|
||||
onCompleted: (v) async {},
|
||||
onChanged: (value) {},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
RoundedButtonFill(
|
||||
title: "Start Ride".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.currentKilometerController.value.text.isEmpty ||
|
||||
double.parse(controller.currentKilometerController.value.text) < 10) {
|
||||
ShowToastDialog.showToast("Please enter current kilometer reading".tr);
|
||||
return;
|
||||
}
|
||||
if (Constant.enableOTPTripStartForRental == true &&
|
||||
otpController.value.text.isEmpty &&
|
||||
otpController.value.text.length < 6) {
|
||||
ShowToastDialog.showToast("Please enter valid OTP".tr);
|
||||
return;
|
||||
}
|
||||
if (Constant.enableOTPTripStartForRental == true && rentalBookingData.otpCode != otpController.value.text.trim()) {
|
||||
ShowToastDialog.showToast("Invalid OTP".tr);
|
||||
return;
|
||||
}
|
||||
|
||||
rentalBookingData.startKitoMetersReading = controller.currentKilometerController.value.text.trim();
|
||||
rentalBookingData.startTime = Timestamp.now();
|
||||
rentalBookingData.status = Constant.orderInTransit;
|
||||
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Ride started successfully".tr);
|
||||
controller.currentKilometerController.value.clear();
|
||||
otpController.value.clear();
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
|
||||
void setFinalKilometerDialog(BuildContext context, bool isDark, RentalHomeController controller, RentalOrderModel rentalBookingData) {
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(80, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text("Enter Kilometer Reading",
|
||||
style:
|
||||
AppThemeData.boldTextStyle(fontSize: 22, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Icon(Icons.close),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
TextFieldWidget(
|
||||
controller: controller.completeKilometerController.value,
|
||||
hintText: 'Enter Current Kilometer reading',
|
||||
title: ' Current Kilometer reading',
|
||||
inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.completeKilometerController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter current kilometer reading".tr);
|
||||
return;
|
||||
} else if (double.parse(controller.completeKilometerController.value.text.toString().trim()) <
|
||||
double.parse(rentalBookingData.startKitoMetersReading.toString())) {
|
||||
ShowToastDialog.showToast("Final kilometer reading cannot be less than starting kilometer reading".tr);
|
||||
return;
|
||||
} else {
|
||||
rentalBookingData.endKitoMetersReading = controller.completeKilometerController.value.text.toString().trim();
|
||||
rentalBookingData.endTime = Timestamp.now();
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Kilometer updated successfully".tr);
|
||||
controller.completeKilometerController.value.clear();
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
|
||||
void conformCashPayment(BuildContext context, bool isDark, RentalHomeController controller, RentalOrderModel rentalBookingData) {
|
||||
Get.dialog(
|
||||
Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
backgroundColor: isDark
|
||||
? AppThemeData.greyDark50 // 👈 dark background
|
||||
: AppThemeData.grey50, // 👈 light background
|
||||
child: SizedBox(
|
||||
width: Responsive.width(80, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text("Confirm Cash Collection",
|
||||
style:
|
||||
AppThemeData.boldTextStyle(fontSize: 20, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900))),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
"Please confirm that you have received the full cash amount from the customer before continuing.",
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500, fontSize: 14),
|
||||
),
|
||||
SizedBox(height: 25),
|
||||
RoundedButtonFill(
|
||||
title: "Ride Completed".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
ShowToastDialog.showLoader("Updating...".tr);
|
||||
rentalBookingData.status = Constant.orderCompleted;
|
||||
rentalBookingData.paymentStatus = true;
|
||||
await controller.updateCabWalletAmount(rentalBookingData);
|
||||
await FireStoreUtils.rentalOrderPlace(rentalBookingData).then((value) {
|
||||
Map<String, dynamic> payLoad = <String, dynamic>{"type": "rental_order", "orderId": rentalBookingData.id};
|
||||
SendNotification.sendFcmMessage(Constant.rentalCompleted, rentalBookingData.author!.fcmToken.toString(), payLoad);
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Ride completed successfully".tr);
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierDismissible: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
650
lib/app/rental_service/rental_order_details_screen.dart
Normal file
650
lib/app/rental_service/rental_order_details_screen.dart
Normal file
@@ -0,0 +1,650 @@
|
||||
import 'package:driver/app/chat_screens/chat_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/models/user_model.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/utils/network_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../controllers/rental_order_details_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/responsive.dart';
|
||||
|
||||
class RentalOrderDetailsScreen extends StatelessWidget {
|
||||
const RentalOrderDetailsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: RentalOrderDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"Order Details".tr,
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
backgroundColor: isDark ? Colors.black : Colors.white,
|
||||
iconTheme: IconThemeData(
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
),
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Center(child: Constant.loader())
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Booking Id : ${controller.order.value.id}",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: controller.order.value.id.toString()));
|
||||
ShowToastDialog.showToast("Booking ID copied to clipboard".tr);
|
||||
},
|
||||
child: Icon(Icons.copy),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Image.asset("assets/icons/pickup.png", height: 15, width: 15),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.sourceLocationName ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
if (controller.order.value.bookingDateTime != null)
|
||||
Text(
|
||||
Constant.timestampToDate(controller.order.value.bookingDateTime!),
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
if (controller.order.value.rentalPackageModel != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Your Preference",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.name ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.description ?? "",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
Constant.amountShow(amount: controller.order.value.rentalPackageModel!.baseFare.toString()),
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
if (controller.order.value.author != null)
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("About Customer".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 52,
|
||||
height: 52,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadiusGeometry.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.userData.value?.profilePictureURL ?? '',
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.userData.value?.fullName() ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900, fontSize: 18),
|
||||
),
|
||||
Text(
|
||||
controller.userData.value?.email ?? '',
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.userData.value?.phoneNumber ?? '',
|
||||
style: AppThemeData.boldTextStyle(
|
||||
color: isDark ? AppThemeData.greyDark700 : AppThemeData.grey700, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
ShowToastDialog.showLoader("Please wait".tr);
|
||||
|
||||
UserModel? customer =
|
||||
await FireStoreUtils.getUserProfile(controller.order.value.authorID.toString());
|
||||
UserModel? driver =
|
||||
await FireStoreUtils.getUserProfile(controller.order.value.driverId.toString());
|
||||
|
||||
ShowToastDialog.closeLoader();
|
||||
|
||||
Get.to(const ChatScreen(), arguments: {
|
||||
"customerName": customer!.fullName(),
|
||||
"restaurantName": driver!.fullName(),
|
||||
"orderId": controller.order.value.id,
|
||||
"restaurantId": driver.id,
|
||||
"customerId": customer.id,
|
||||
"customerProfileImage": customer.profilePictureURL ?? "",
|
||||
"restaurantProfileImage": driver.profilePictureURL ?? "",
|
||||
"token": customer.fcmToken,
|
||||
"chatType": "Driver",
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
width: 42,
|
||||
height: 42,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_wechat.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// Visibility(
|
||||
// visible: controller.order.value?.status == Constant.orderCompleted ? true : false,
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
// child: RoundedButtonFill(
|
||||
// title: 'Add Review'.tr,
|
||||
// onPress: () async {
|
||||
// final result = await Get.to(() => RentalReviewScreen(), arguments: {'order': controller.order.value});
|
||||
//
|
||||
// // If review was submitted successfully
|
||||
// if (result == true) {
|
||||
// await controller.fetchCustomerDetails();
|
||||
// }
|
||||
// },
|
||||
// height: 5,
|
||||
// borderRadius: 15,
|
||||
// color: Colors.orange,
|
||||
// textColor: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
),
|
||||
if (controller.order.value.rentalVehicleType != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Vehicle Type",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.greyDark500 : AppThemeData.grey500)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: NetworkImageWidget(
|
||||
imageUrl: controller.order.value.rentalVehicleType!.rentalVehicleIcon ?? "",
|
||||
height: 50,
|
||||
width: 50),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
controller.order.value.rentalVehicleType!.name ?? "",
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
Text(
|
||||
controller.order.value.rentalVehicleType!.shortDescription ?? "",
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Rental Details".tr,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
Divider(color: isDark ? AppThemeData.greyDark300 : AppThemeData.grey300),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Rental Package'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.order.value.rentalPackageModel!.name.toString().tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Rental Package Price'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Constant.amountShow(
|
||||
amount: controller.order.value.rentalPackageModel!.baseFare.toString(),
|
||||
).tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Including ${Constant.distanceType.tr}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.rentalPackageModel!.includedDistance.toString()} ${Constant.distanceType}"
|
||||
.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Including Hours'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.rentalPackageModel!.includedHours.toString()} Hr".tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Extra ${Constant.distanceType}',
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.getExtraKm(),
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Text(
|
||||
// 'Extra ${Constant.distanceType}',
|
||||
// textAlign: TextAlign.start,
|
||||
// style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// "${(double.parse(controller.order.value.endKitoMetersReading!.toString()) - double.parse(controller.order.value.startKitoMetersReading!.toString()) - double.parse(controller.order.value.rentalPackageModel!.includedDistance!.toString()))} ${Constant.distanceType}",
|
||||
// textAlign: TextAlign.start,
|
||||
// style: AppThemeData.boldTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
controller.order.value.endTime == null
|
||||
? SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Extra Minutes'.tr,
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.mediumTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${controller.order.value.endTime == null ? "0" : (((controller.order.value.endTime!.toDate().difference(controller.order.value.startTime!.toDate()).inMinutes) - (int.parse(controller.order.value.rentalPackageModel!.includedHours.toString()) * 60)).clamp(0, double.infinity).toInt().toString())} Min",
|
||||
textAlign: TextAlign.start,
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Order Summary".tr,
|
||||
style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.grey500),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_summaryTile(
|
||||
"Subtotal".tr,
|
||||
Constant.amountShow(amount: controller.subTotal.value.toString()),
|
||||
isDark,
|
||||
null,
|
||||
),
|
||||
_summaryTile(
|
||||
"Discount".tr,
|
||||
Constant.amountShow(amount: controller.discount.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.dangerDark300,
|
||||
),
|
||||
...List.generate(controller.order.value.taxSetting?.length ?? 0, (index) {
|
||||
final taxModel = controller.order.value.taxSetting![index];
|
||||
final taxTitle =
|
||||
"${taxModel.title} ${taxModel.type == 'fix' ? '(${Constant.amountShow(amount: taxModel.tax)})' : '(${taxModel.tax}%)'}";
|
||||
return _summaryTile(
|
||||
taxTitle,
|
||||
Constant.amountShow(
|
||||
amount: Constant.getTaxValue(
|
||||
amount: (controller.subTotal.value - controller.discount.value).toString(),
|
||||
taxModel: taxModel,
|
||||
).toString(),
|
||||
),
|
||||
isDark,
|
||||
null,
|
||||
);
|
||||
}),
|
||||
const Divider(),
|
||||
_summaryTile(
|
||||
"Order Total".tr,
|
||||
Constant.amountShow(amount: controller.totalAmount.value.toString()),
|
||||
isDark,
|
||||
null,
|
||||
),
|
||||
_summaryTile(
|
||||
"Admin Commission (${controller.order.value.adminCommission}${controller.order.value.adminCommissionType == "Percentage" || controller.order.value.adminCommissionType == "percentage" ? "%" : Constant.currencyModel!.symbol})"
|
||||
.tr,
|
||||
Constant.amountShow(amount: controller.adminCommission.value.toString()),
|
||||
isDark,
|
||||
AppThemeData.danger300,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
controller.order.value.driver != null && controller.order.value.driver!.ownerId != null && controller.order.value.driver!.ownerId!.isNotEmpty ||
|
||||
controller.order.value.status == Constant.orderPlaced
|
||||
? SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Container(
|
||||
width: Responsive.width(100, context),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: isDark ? AppThemeData.danger50 : AppThemeData.danger50),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Note : Admin commission will be debited from your wallet balance. \n \nAdmin commission will apply on your booking Amount minus Discount(if applicable).",
|
||||
style: AppThemeData.boldTextStyle(
|
||||
fontSize: 16, color: isDark ? AppThemeData.danger300 : AppThemeData.danger300),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _summaryTile(String title, String value, bool isDark, Color? colors) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(title, style: AppThemeData.mediumTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark800 : AppThemeData.grey800)),
|
||||
Text(
|
||||
value,
|
||||
style: AppThemeData.semiBoldTextStyle(
|
||||
fontSize: title == "Order Total" ? 18 : 16, color: colors ?? (isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
233
lib/app/rental_service/rental_order_list_screen.dart
Normal file
233
lib/app/rental_service/rental_order_list_screen.dart
Normal file
@@ -0,0 +1,233 @@
|
||||
import 'package:driver/app/rental_service/rental_order_details_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/rental_order_list_controller.dart';
|
||||
import '../../models/rental_order_model.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/round_button_fill.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
class RentalOrderListScreen extends StatelessWidget {
|
||||
const RentalOrderListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<RentalOrderListController>(
|
||||
init: RentalOrderListController(),
|
||||
builder: (controller) {
|
||||
return DefaultTabController(
|
||||
length: controller.tabTitles.length,
|
||||
initialIndex: controller.tabTitles.indexOf(controller.selectedTab.value),
|
||||
child: Column(
|
||||
children: [
|
||||
// TabBar
|
||||
TabBar(
|
||||
onTap: (index) {
|
||||
controller.selectTab(controller.tabTitles[index]);
|
||||
},
|
||||
indicatorColor: AppThemeData.parcelService500,
|
||||
labelColor: AppThemeData.parcelService500,
|
||||
dividerColor: isDark ? Colors.black : Colors.white,
|
||||
unselectedLabelColor: AppThemeData.grey500,
|
||||
labelStyle: AppThemeData.boldTextStyle(fontSize: 16),
|
||||
unselectedLabelStyle: AppThemeData.mediumTextStyle(fontSize: 16),
|
||||
tabs: controller.tabTitles.map((title) => Tab(child: Text(title))).toList(),
|
||||
),
|
||||
|
||||
// Body: loader or TabBarView
|
||||
Expanded(
|
||||
child: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: TabBarView(
|
||||
children: controller.tabTitles.map((title) {
|
||||
// filter by tab using controller helper
|
||||
final orders = controller.getOrdersForTab(title);
|
||||
|
||||
if (orders.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
"No orders found".tr,
|
||||
style: AppThemeData.mediumTextStyle(color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: orders.length,
|
||||
itemBuilder: (context, index) {
|
||||
RentalOrderModel order = orders[index]; //use this
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => RentalOrderDetailsScreen(), arguments: {"rentalOrder": order.id});
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
border: Border.all(color: isDark ? AppThemeData.greyDark200 : AppThemeData.grey200),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: const EdgeInsets.only(top: 5), child: Image.asset("assets/icons/pickup.png", height: 18, width: 18)),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
//prevents overflow
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
//text wraps if too long
|
||||
child: Text(
|
||||
order.sourceLocationName ?? "-",
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
overflow: TextOverflow.ellipsis, //safe cutoff
|
||||
maxLines: 2,
|
||||
),
|
||||
),
|
||||
if (order.status != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppThemeData.info50,
|
||||
border: Border.all(color: AppThemeData.info300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(order.status ?? '', style: AppThemeData.boldTextStyle(fontSize: 14, color: AppThemeData.info500)),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
if (order.bookingDateTime != null)
|
||||
Text(
|
||||
Constant.timestampToDateTime(order.bookingDateTime!),
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 12, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text("Vehicle Type :".tr, style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: order.rentalVehicleType?.rentalVehicleIcon ?? Constant.placeHolderImage,
|
||||
height: 60,
|
||||
width: 60,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(AppThemeData.primary300),
|
||||
),
|
||||
),
|
||||
errorWidget: (context, url, error) => Image.network(
|
||||
Constant.placeHolderImage,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${order.rentalVehicleType!.name}",
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2.0),
|
||||
child: Text(
|
||||
"${order.rentalVehicleType!.shortDescription}",
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Package info :".tr, style: AppThemeData.boldTextStyle(fontSize: 16, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
order.rentalPackageModel!.name.toString(),
|
||||
style: AppThemeData.semiBoldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
order.rentalPackageModel!.description.toString(),
|
||||
style: AppThemeData.mediumTextStyle(fontSize: 14, color: isDark ? AppThemeData.greyDark600 : AppThemeData.grey600),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
Constant.amountShow(amount: order.rentalPackageModel!.baseFare.toString()),
|
||||
style: AppThemeData.boldTextStyle(fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (order.status == Constant.orderPlaced || order.status == Constant.driverAccepted) ...[
|
||||
SizedBox(height: 10),
|
||||
if (order.status == Constant.orderPlaced || order.status == Constant.driverAccepted)
|
||||
Expanded(
|
||||
child: RoundedButtonFill(
|
||||
title: "Cancel Booking".tr,
|
||||
onPress: () {
|
||||
// controller.cancelRentalRequest(order);
|
||||
},
|
||||
color: AppThemeData.danger300,
|
||||
textColor: AppThemeData.surface,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
167
lib/app/rental_service/rental_review_screen.dart
Normal file
167
lib/app/rental_service/rental_review_screen.dart
Normal file
@@ -0,0 +1,167 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/rental_review_controller.dart';
|
||||
import '../../themes/app_them_data.dart';
|
||||
import '../../themes/round_button_fill.dart';
|
||||
import '../../themes/text_field_widget.dart';
|
||||
import '../../themes/theme_controller.dart';
|
||||
import '../../utils/network_image_widget.dart';
|
||||
|
||||
class RentalReviewScreen extends StatelessWidget {
|
||||
const RentalReviewScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
|
||||
return GetX<RentalReviewController>(
|
||||
init: RentalReviewController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
elevation: 0,
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Icon(Icons.arrow_back_ios, color: isDark ? Colors.white : Colors.black),
|
||||
),
|
||||
title: Text(
|
||||
controller.ratingModel.value != null ? "Update Review".tr : "Add Review".tr,
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black, fontSize: 16),
|
||||
),
|
||||
),
|
||||
body: Obx(
|
||||
() => controller.customerUser.value == null
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, top: 50, bottom: 20),
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
color: isDark ? AppThemeData.greyDark50 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 65),
|
||||
child: Column(
|
||||
children: [
|
||||
// Customer Name
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"${controller.customerUser.value?.firstName ?? ''} ${controller.customerUser.value?.lastName ?? ''}",
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black87, fontFamily: AppThemeData.medium, fontSize: 18),
|
||||
),
|
||||
),
|
||||
// Customer Email & Phone
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.customerUser.value?.email ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black87, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
controller.customerUser.value?.phoneNumber ?? '',
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black38, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Divider(color: Colors.grey),
|
||||
),
|
||||
|
||||
// Title
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
child: Text(
|
||||
'How was your customer?'.tr,
|
||||
style: TextStyle(fontSize: 18, color: isDark ? Colors.white : Colors.black, fontWeight: FontWeight.bold, letterSpacing: 1),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
"Share your feedback about the customer.".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8),
|
||||
),
|
||||
),
|
||||
|
||||
// Rating
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
'Rate the Customer'.tr,
|
||||
style: TextStyle(fontSize: 16, color: isDark ? Colors.white : Colors.black.withOpacity(0.60), letterSpacing: 0.8),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: RatingBar.builder(
|
||||
initialRating: controller.ratings.value,
|
||||
minRating: 1,
|
||||
direction: Axis.horizontal,
|
||||
allowHalfRating: true,
|
||||
itemCount: 5,
|
||||
itemBuilder: (context, _) => const Icon(Icons.star, color: Colors.amber),
|
||||
unratedColor: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400,
|
||||
onRatingUpdate: (rating) => controller.ratings.value = rating,
|
||||
),
|
||||
),
|
||||
|
||||
// Comment
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: TextFieldWidget(hintText: "Type comment....".tr, controller: controller.comment.value, maxLine: 5),
|
||||
),
|
||||
|
||||
// Submit
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: RoundedButtonFill(
|
||||
title: controller.ratingModel.value != null ? "Update Review".tr : "Add Review".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: isDark ? Colors.white : Colors.black,
|
||||
onPress: controller.submitReview,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.15), blurRadius: 8, spreadRadius: 6)],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
child: NetworkImageWidget(imageUrl: controller.customerUser.value?.profilePictureURL ?? '', fit: BoxFit.cover, height: 110, width: 110),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
46
lib/app/splash_screen.dart
Normal file
46
lib/app/splash_screen.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:driver/controllers/splash_controller.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class SplashScreen extends StatelessWidget {
|
||||
const SplashScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetBuilder<SplashController>(
|
||||
init: SplashController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppThemeData.primary300,
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/images/ic_logo.png",
|
||||
height: 150,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text(
|
||||
"Welcome to eMart Driver".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50, fontSize: 24, fontFamily: AppThemeData.bold),
|
||||
),
|
||||
Text(
|
||||
"Your Favorite Ride, Parcel, Rental & Item Delivered Fast!".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey50),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
26
lib/app/terms_and_condition/terms_and_condition_screen.dart
Normal file
26
lib/app/terms_and_condition/terms_and_condition_screen.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
|
||||
class TermsAndConditionScreen extends StatelessWidget {
|
||||
final String? type;
|
||||
|
||||
const TermsAndConditionScreen({super.key, this.type});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppThemeData.grey50,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: SingleChildScrollView(
|
||||
child: Html(
|
||||
shrinkWrap: true,
|
||||
data: type == "privacy" ? Constant.privacyPolicy : Constant.termsAndConditions,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
import 'package:driver/models/car_makes.dart';
|
||||
import 'package:driver/models/car_model.dart';
|
||||
import 'package:driver/models/section_model.dart';
|
||||
import 'package:driver/models/vehicle_type.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../constant/constant.dart';
|
||||
import '../../controllers/vehicle_information_controller.dart';
|
||||
|
||||
class VehicleInformationScreen extends StatelessWidget {
|
||||
const VehicleInformationScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx(() {
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetBuilder<VehicleInformationController>(
|
||||
init: VehicleInformationController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
buildDropdown<String>(
|
||||
context: context,
|
||||
title: "Service".tr,
|
||||
value: controller.selectedService.value,
|
||||
items: controller.service,
|
||||
isDark: isDark,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
// keep true for theme styling
|
||||
absorb: true,
|
||||
// new param
|
||||
onChanged: (value) async {
|
||||
if (controller.userModel.value.isOwner == false) {
|
||||
controller.selectedService.value = value!;
|
||||
await controller.getSection();
|
||||
controller.update();
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
buildDropdown<SectionModel>(
|
||||
context: context,
|
||||
title: "Select Section".tr,
|
||||
value: controller.selectedSection.value,
|
||||
items: controller.sectionList,
|
||||
isDark: isDark,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
// theme visible
|
||||
absorb: true,
|
||||
// make non-editable
|
||||
onChanged: (value) {
|
||||
if (controller.userModel.value.isOwner == false) {
|
||||
controller.selectedSection.value = value!;
|
||||
controller.getVehicleType(controller.selectedSection.value.id.toString());
|
||||
controller.update();
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
buildDropdown<VehicleType>(
|
||||
context: context,
|
||||
title: "Select Vehicle Type".tr,
|
||||
value: controller.selectedVehicleType.value,
|
||||
items: controller.cabVehicleType,
|
||||
isDark: isDark,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
onChanged: (value) {
|
||||
controller.selectedVehicleType.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
buildDropdown<CarMakes>(
|
||||
context: context,
|
||||
title: "Select Car Brand".tr,
|
||||
value: controller.selectedCarMakes.value,
|
||||
items: controller.carMakesList,
|
||||
isDark: isDark,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarMakes.value = value!;
|
||||
controller.getCarModel();
|
||||
controller.update();
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
buildDropdown<CarModel>(
|
||||
context: context,
|
||||
title: "Select Car Model".tr,
|
||||
value: controller.selectedCarModel.value,
|
||||
items: controller.carModelList,
|
||||
isDark: isDark,
|
||||
enabled:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
onChanged: (value) {
|
||||
controller.selectedCarModel.value = value!;
|
||||
controller.update();
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextFieldWidget(
|
||||
title: 'Car Plat Number'.tr,
|
||||
controller: controller.carPlatNumberEditingController.value,
|
||||
hintText: 'Enter Car Plat Number'.tr,
|
||||
textInputAction: TextInputAction.next,
|
||||
enable:
|
||||
controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty ? false : true,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
controller.selectedService.value == "Cab Service"
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Ride Type".tr,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Obx(
|
||||
() => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
controller.selectedSection.value.rideType == "both" ||
|
||||
controller.selectedSection.value.rideType == "ride"
|
||||
? Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text('Ride'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'ride',
|
||||
activeColor: AppThemeData.primary300,
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
controller.selectedSection.value.rideType == "both" ||
|
||||
controller.selectedSection.value.rideType == "intercity"
|
||||
? Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
activeColor: AppThemeData.primary300,
|
||||
title: Text('Intercity'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'intercity',
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
controller.selectedSection.value.rideType == "both"
|
||||
? Expanded(
|
||||
child: RadioListTile<String>(
|
||||
dense: true,
|
||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text('Both'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: isDark ? AppThemeData.grey100 : AppThemeData.grey800)),
|
||||
value: 'both',
|
||||
activeColor: AppThemeData.primary300,
|
||||
groupValue: controller.selectedValue.value,
|
||||
onChanged: (value) {
|
||||
controller.selectedValue.value = value!;
|
||||
},
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: SizedBox.shrink()
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: controller.userModel.value.ownerId != null && controller.userModel.value.ownerId!.isNotEmpty
|
||||
? const SizedBox.shrink()
|
||||
: controller.isLoading.value
|
||||
? const SizedBox.shrink()
|
||||
: InkWell(
|
||||
onTap: () => controller.saveVehicleInformation(),
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Save".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildDropdown<T>({
|
||||
required BuildContext context,
|
||||
required String title,
|
||||
required T value,
|
||||
required List<T> items,
|
||||
required bool isDark,
|
||||
required bool enabled,
|
||||
bool absorb = false,
|
||||
required Function(T?) onChanged,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.semiBold,
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
AbsorbPointer(
|
||||
absorbing: absorb,
|
||||
child: DropdownButtonFormField<T>(
|
||||
initialValue: value,
|
||||
onChanged: enabled ? onChanged : null,
|
||||
isExpanded: true,
|
||||
dropdownColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
// 👈 dropdown theme
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12),
|
||||
filled: true,
|
||||
fillColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(
|
||||
color: isDark ? AppThemeData.greyDark400 : AppThemeData.grey400,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
icon: Icon(
|
||||
Icons.keyboard_arrow_down,
|
||||
size: 18,
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey900,
|
||||
),
|
||||
items: items.map((item) {
|
||||
String text = '';
|
||||
if (item is String) text = item;
|
||||
if (item is SectionModel) text = item.name ?? '';
|
||||
if (item is VehicleType) text = item.name ?? '';
|
||||
if (item is CarMakes) text = item.name ?? '';
|
||||
if (item is CarModel) text = item.name ?? '';
|
||||
return DropdownMenuItem<T>(
|
||||
value: item,
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/verification_details_upload_controller.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/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class VerificationDetailsUploadScreen extends StatelessWidget {
|
||||
const VerificationDetailsUploadScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX<DetailsUploadController>(
|
||||
init: DetailsUploadController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
centerTitle: false,
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 0,
|
||||
leading: InkWell(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.chevron_left_outlined,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
"${controller.documentModel.value.title}",
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 18),
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${'Upload'.tr} ${controller.documentModel.value.title} ${'for Verification'.tr}",
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 22),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"${'Please upload a valid'.tr} ${controller.documentModel.value.title} ${'to verify your identity complete the registration process.'.tr}".tr,
|
||||
style: TextStyle(fontSize: 16, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.documentModel.value.frontSide == true ? true : false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${'Front Side of'} ${controller.documentModel.value.title.toString()}",
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
controller.frontImage.value.isNotEmpty
|
||||
? InkWell(
|
||||
onTap: () {
|
||||
if (controller.documents.value.status != "uploaded" || controller.documents.value.status == "rejected") {
|
||||
buildBottomSheet(context, controller, "front");
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(90, context),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: Constant().hasValidUrl(controller.frontImage.value) == false
|
||||
? Image.file(
|
||||
File(controller.frontImage.value),
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(80, context),
|
||||
fit: BoxFit.fill,
|
||||
)
|
||||
: CachedNetworkImage(
|
||||
imageUrl: controller.frontImage.value.toString(),
|
||||
fit: BoxFit.fill,
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(80, context),
|
||||
placeholder: (context, url) => Constant.loader(),
|
||||
errorWidget: (context, url, error) => Image.network(
|
||||
'https://firebasestorage.googleapis.com/v0/b/goride-1a752.appspot.com/o/placeholderImages%2Fuser-placeholder.jpeg?alt=media&token=34a73d67-ba1d-4fe4-a29f-271d3e3ca115'),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
radius: const Radius.circular(12),
|
||||
dashPattern: const [6, 6, 6, 6],
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(12),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: Responsive.height(22, context),
|
||||
width: Responsive.width(90, context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/ic_folder.svg',
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Choose a image and upload here".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium,
|
||||
fontSize: 16),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"JPEG, PNG".tr,
|
||||
style: TextStyle(
|
||||
fontSize: 12, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Brows Image".tr,
|
||||
color: AppThemeData.carRent50,
|
||||
textColor: AppThemeData.primary300,
|
||||
width: 30,
|
||||
height: 5,
|
||||
onPress: () async {
|
||||
buildBottomSheet(context, controller, "front");
|
||||
},
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.documentModel.value.backSide == true ? true : false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${'Back side of'.tr} ${controller.documentModel.value.title.toString()}",
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
controller.backImage.value.isNotEmpty
|
||||
? InkWell(
|
||||
onTap: () {
|
||||
if (controller.documents.value.status != "uploaded" || controller.documents.value.status == "rejected") {
|
||||
buildBottomSheet(context, controller, "back");
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(90, context),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: Constant().hasValidUrl(controller.backImage.value) == false
|
||||
? Image.file(
|
||||
File(controller.backImage.value),
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(80, context),
|
||||
fit: BoxFit.fill,
|
||||
)
|
||||
: CachedNetworkImage(
|
||||
imageUrl: controller.backImage.value.toString(),
|
||||
fit: BoxFit.fill,
|
||||
height: Responsive.height(20, context),
|
||||
width: Responsive.width(80, context),
|
||||
placeholder: (context, url) => Constant.loader(),
|
||||
errorWidget: (context, url, error) => Image.network(
|
||||
'https://firebasestorage.googleapis.com/v0/b/goride-1a752.appspot.com/o/placeholderImages%2Fuser-placeholder.jpeg?alt=media&token=34a73d67-ba1d-4fe4-a29f-271d3e3ca115'),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: DottedBorder(
|
||||
options: RoundedRectDottedBorderOptions(
|
||||
radius: const Radius.circular(12),
|
||||
dashPattern: const [6, 6, 6, 6],
|
||||
color: isDark ? AppThemeData.grey700 : AppThemeData.grey200,
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(12),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: Responsive.height(22, context),
|
||||
width: Responsive.width(90, context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/ic_folder.svg',
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Choose a image and upload here".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.medium,
|
||||
fontSize: 16),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"JPEG, PNG".tr,
|
||||
style: TextStyle(
|
||||
fontSize: 12, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Brows Image".tr,
|
||||
color: AppThemeData.carRent50,
|
||||
textColor: AppThemeData.primary300,
|
||||
width: 30,
|
||||
height: 5,
|
||||
onPress: () async {
|
||||
buildBottomSheet(context, controller, "back");
|
||||
},
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: controller.documents.value.status == "approved" || controller.documents.value.status == "uploaded"
|
||||
? const SizedBox()
|
||||
: InkWell(
|
||||
onTap: () {
|
||||
if (controller.documentModel.value.frontSide == true && controller.frontImage.value.isEmpty) {
|
||||
ShowToastDialog.showToast("Please upload front side of document.".tr);
|
||||
} else if (controller.documentModel.value.backSide == true && controller.backImage.value.isEmpty) {
|
||||
ShowToastDialog.showToast("Please upload back side of document.".tr);
|
||||
} else {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
controller.uploadDocument();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Upload Document".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future buildBottomSheet(BuildContext context, DetailsUploadController controller, String type) {
|
||||
return showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return StatefulBuilder(builder: (context, setState) {
|
||||
return SizedBox(
|
||||
height: Responsive.height(22, context),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Text(
|
||||
"Please Select".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontFamily: AppThemeData.bold, fontSize: 16),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => controller.pickFile(source: ImageSource.camera, type: type),
|
||||
icon: const Icon(
|
||||
Icons.camera_alt,
|
||||
size: 32,
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3),
|
||||
child: Text("Camera".tr),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => controller.pickFile(source: ImageSource.gallery, type: type),
|
||||
icon: const Icon(
|
||||
Icons.photo_library_sharp,
|
||||
size: 32,
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3),
|
||||
child: Text("Gallery".tr),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
152
lib/app/verification_screen/verification_screen.dart
Normal file
152
lib/app/verification_screen/verification_screen.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/controllers/verification_controller.dart';
|
||||
import 'package:driver/models/document_model.dart';
|
||||
import 'package:driver/models/driver_document_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'verification_details_upload_screen.dart';
|
||||
|
||||
class VerificationScreen extends StatelessWidget {
|
||||
const VerificationScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
return Obx((){
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetBuilder<VerificationController>(
|
||||
init: VerificationController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Document Verification".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey100 : AppThemeData.grey800, fontFamily: AppThemeData.bold, fontSize: 22),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"Upload your ID Proof to complete the verification process and ensure compliance.".tr,
|
||||
style: TextStyle(fontSize: 14, color: isDark ? AppThemeData.grey200 : AppThemeData.grey700, fontFamily: AppThemeData.regular),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
child: ListView.separated(
|
||||
itemCount: controller.documentList.length,
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
itemBuilder: (context, index) {
|
||||
DocumentModel documentModel = controller.documentList[index];
|
||||
Documents documents = Documents();
|
||||
|
||||
var contain = controller.driverDocumentList.where((element) => element.documentId == documentModel.id);
|
||||
if (contain.isNotEmpty) {
|
||||
documents = controller.driverDocumentList.firstWhere((itemToCheck) => itemToCheck.documentId == documentModel.id);
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(const VerificationDetailsUploadScreen(), arguments: {'documentModel': documentModel})!.then(
|
||||
(value) {
|
||||
if (value == true) {
|
||||
controller.getDocument();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${documentModel.title}",
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey100 : AppThemeData.grey800,
|
||||
fontFamily: AppThemeData.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"${documentModel.frontSide == true ? "Front" : ""} ${documentModel.backSide == true ? "And Back" : ""} ${'Photo'.tr}",
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey300 : AppThemeData.grey600,
|
||||
fontFamily: AppThemeData.regular,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
child: Text(
|
||||
documents.status == "approved"
|
||||
? "Verified".tr
|
||||
: documents.status == "rejected"
|
||||
? "Rejected".tr
|
||||
: documents.status == "uploaded"
|
||||
? "Uploaded".tr
|
||||
: "Pending".tr,
|
||||
style: TextStyle(
|
||||
color: documents.status == "approved"
|
||||
? Colors.green
|
||||
: documents.status == "rejected"
|
||||
? Colors.red
|
||||
: documents.status == "uploaded"
|
||||
? AppThemeData.primary300
|
||||
: Colors.orange,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16),
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
size: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Divider(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
238
lib/app/wallet_screen/payment_list_screen.dart
Normal file
238
lib/app/wallet_screen/payment_list_screen.dart
Normal file
@@ -0,0 +1,238 @@
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/wallet_controller.dart';
|
||||
import 'package:driver/payment/createRazorPayOrderModel.dart';
|
||||
import 'package:driver/payment/rozorpayConroller.dart';
|
||||
import 'package:driver/themes/app_them_data.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:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class PaymentListScreen extends StatelessWidget {
|
||||
const PaymentListScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: WalletController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
titleSpacing: 0,
|
||||
title: Text(
|
||||
"Top up Wallet".tr,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: TextFieldWidget(
|
||||
title: 'Amount'.tr,
|
||||
hintText: 'Enter Amount'.tr,
|
||||
controller: controller.topUpAmountController.value,
|
||||
textInputType: const TextInputType.numberWithOptions(decimal: true, signed: true),
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Text(Constant.currencyModel!.symbol.toString(), style: TextStyle(fontSize: 20, color: isDark ? AppThemeData.grey50 : AppThemeData.grey900)),
|
||||
),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
textInputAction: TextInputAction.done,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(20)), color: isDark ? AppThemeData.grey900 : AppThemeData.grey50),
|
||||
child: Column(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: controller.stripeModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.stripe, isDark, "assets/images/stripe.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.payPalModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.paypal, isDark, "assets/images/paypal.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.payStackModel.value.isEnable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.payStack, isDark, "assets/images/paystack.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.mercadoPagoModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.mercadoPago, isDark, "assets/images/mercado-pago.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.flutterWaveModel.value.isEnable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.flutterWave, isDark, "assets/images/flutterwave_logo.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.payFastModel.value.isEnable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.payFast, isDark, "assets/images/payfast.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.razorPayModel.value.isEnabled == true,
|
||||
child: cardDecoration(controller, PaymentGateway.razorpay, isDark, "assets/images/razorpay.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.midTransModel.value.enable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.midTrans, isDark, "assets/images/midtrans.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.orangeMoneyModel.value.enable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.orangeMoney, isDark, "assets/images/orange_money.png"),
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.xenditModel.value.enable == true,
|
||||
child: cardDecoration(controller, PaymentGateway.xendit, isDark, "assets/images/xendit.png"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Container(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
child: RoundedButtonFill(
|
||||
title: "Top-up".tr,
|
||||
height: 5.5,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
fontSizes: 16,
|
||||
onPress: () async {
|
||||
if (controller.topUpAmountController.value.text.trim().isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter amount".tr);
|
||||
} else if ((double.tryParse(controller.topUpAmountController.value.text.trim()) ?? 0) <= 0) {
|
||||
ShowToastDialog.showToast("Please enter amount greater than 0".tr);
|
||||
} else if ((double.tryParse(controller.topUpAmountController.value.text.trim()) ?? 0) < double.parse(Constant.minimumAmountToDeposit.toString())) {
|
||||
ShowToastDialog.showToast(
|
||||
"${'Please enter minimum amount of'.tr} ${Constant.amountShow(amount: Constant.minimumAmountToDeposit)}".tr,
|
||||
);
|
||||
} else {
|
||||
if (double.parse(controller.topUpAmountController.value.text) >= double.parse(Constant.minimumAmountToDeposit.toString())) {
|
||||
if (controller.selectedPaymentMethod.value == PaymentGateway.stripe.name) {
|
||||
controller.stripeMakePayment(amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.paypal.name) {
|
||||
controller.paypalPaymentSheet(controller.topUpAmountController.value.text, context);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.payStack.name) {
|
||||
controller.payStackPayment(controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.mercadoPago.name) {
|
||||
controller.mercadoPagoMakePayment(context: context, amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.flutterWave.name) {
|
||||
controller.flutterWaveInitiatePayment(context: context, amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.payFast.name) {
|
||||
controller.payFastPayment(context: context, amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.midTrans.name) {
|
||||
controller.midtransMakePayment(context: context, amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.orangeMoney.name) {
|
||||
controller.orangeMakePayment(context: context, amount: controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.xendit.name) {
|
||||
controller.xenditPayment(context, controller.topUpAmountController.value.text);
|
||||
} else if (controller.selectedPaymentMethod.value == PaymentGateway.razorpay.name) {
|
||||
RazorPayController()
|
||||
.createOrderRazorPay(amount: double.parse(controller.topUpAmountController.value.text), razorpayModel: controller.razorPayModel.value)
|
||||
.then((value) {
|
||||
if (value == null) {
|
||||
Get.back();
|
||||
ShowToastDialog.showToast("Something went wrong, please contact admin.".tr);
|
||||
} else {
|
||||
CreateRazorPayOrderModel result = value;
|
||||
controller.openCheckout(amount: controller.topUpAmountController.value.text, orderId: result.id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ShowToastDialog.showToast("Please select payment method".tr);
|
||||
}
|
||||
} else {
|
||||
ShowToastDialog.showToast("${'Please Enter minimum amount of'.tr} ${Constant.amountShow(amount: Constant.minimumAmountToDeposit)}".tr);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Obx cardDecoration(WalletController controller, PaymentGateway value, isDark, String image) {
|
||||
return Obx(
|
||||
() => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
controller.selectedPaymentMethod.value = value.name;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: const BorderSide(width: 1, color: Color(0xFFE5E7EB)),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(value.name == "payFast" ? 0 : 8.0),
|
||||
child: Image.asset(
|
||||
image,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontSize: 16,
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Expanded(
|
||||
child: SizedBox(),
|
||||
),
|
||||
Radio(
|
||||
value: value.name,
|
||||
groupValue: controller.selectedPaymentMethod.value,
|
||||
activeColor: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
||||
onChanged: (value) {
|
||||
controller.selectedPaymentMethod.value = value.toString();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum PaymentGateway { payFast, mercadoPago, paypal, stripe, flutterWave, payStack, paytm, razorpay, cod, wallet, midTrans, orangeMoney, xendit }
|
||||
1403
lib/app/wallet_screen/wallet_screen.dart
Normal file
1403
lib/app/wallet_screen/wallet_screen.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,99 @@
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/bank_details_controller.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/responsive.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BankDetailsScreen extends StatelessWidget {
|
||||
const BankDetailsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: BankDetailsController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
appBar: AppBar(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
centerTitle: false,
|
||||
title: Text(
|
||||
"Bank Setup".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 18, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Bank Name'.tr,
|
||||
controller: controller.bankNameController.value,
|
||||
hintText: 'Enter Bank Name'.tr,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Branch Name'.tr,
|
||||
controller: controller.branchNameController.value,
|
||||
hintText: 'Enter Branch Name'.tr,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Holder Name'.tr,
|
||||
controller: controller.holderNameController.value,
|
||||
hintText: 'Enter Holder Name'.tr,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Account Number'.tr,
|
||||
controller: controller.accountNoController.value,
|
||||
hintText: 'Enter Account Number'.tr,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Other Information'.tr,
|
||||
controller: controller.otherInfoController.value,
|
||||
hintText: 'Enter Other Information'.tr,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: InkWell(
|
||||
onTap: () {
|
||||
if (controller.bankNameController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter bank name".tr);
|
||||
} else if (controller.branchNameController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter branch name".tr);
|
||||
} else if (controller.holderNameController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter holder name".tr);
|
||||
} else if (controller.accountNoController.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter account number".tr);
|
||||
} else {
|
||||
controller.saveBank();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: AppThemeData.primary300,
|
||||
width: Responsive.width(100, context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(
|
||||
"Save Details".tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,964 @@
|
||||
import 'package:driver/app/withdraw_method_setup_screens/bank_details_screen.dart';
|
||||
import 'package:driver/constant/constant.dart';
|
||||
import 'package:driver/constant/show_toast_dialog.dart';
|
||||
import 'package:driver/controllers/withdraw_method_setup_controller.dart';
|
||||
import 'package:driver/models/withdraw_method_model.dart';
|
||||
import 'package:driver/themes/app_them_data.dart';
|
||||
import 'package:driver/themes/round_button_fill.dart';
|
||||
import 'package:driver/themes/text_field_widget.dart';
|
||||
import 'package:driver/themes/theme_controller.dart';
|
||||
import 'package:driver/utils/fire_store_utils.dart';
|
||||
import 'package:driver/widget/my_separator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class WithdrawMethodSetupScreen extends StatelessWidget {
|
||||
const WithdrawMethodSetupScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeController = Get.find<ThemeController>();
|
||||
final isDark = themeController.isDark.value;
|
||||
return GetX(
|
||||
init: WithdrawMethodSetupController(),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
body: controller.isLoading.value
|
||||
? Constant.loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 52,
|
||||
width: 52,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SvgPicture.asset("assets/icons/ic_building_four.svg"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Bank Transfer".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(const BankDetailsScreen());
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_edit_coupon.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
controller.isBankDetailsAdded.value == false
|
||||
? Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your Setup is pending".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Get.to(const BankDetailsScreen());
|
||||
},
|
||||
child: Text(
|
||||
"Setup now".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.secondary300,
|
||||
color: isDark ? AppThemeData.secondary300 : AppThemeData.secondary300,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Setup was done.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 52,
|
||||
width: 52,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.asset("assets/images/flutterwave.png"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Flutter wave".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.withdrawMethodModel.value.flutterWave != null
|
||||
? Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return flutterWaveDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_edit_coupon.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
controller.withdrawMethodModel.value.flutterWave = null;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method remove successfully".tr);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_delete-one.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
controller.withdrawMethodModel.value.flutterWave == null
|
||||
? Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your Setup is pending".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return flutterWaveDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Setup now".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.secondary300,
|
||||
color: isDark ? AppThemeData.secondary300 : AppThemeData.secondary300,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Setup was done.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 52,
|
||||
width: 52,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.asset("assets/images/paypal.png"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"PayPal".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.withdrawMethodModel.value.paypal != null
|
||||
? Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return payPalDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_edit_coupon.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
controller.withdrawMethodModel.value.paypal = null;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method remove successfully".tr);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_delete-one.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
controller.withdrawMethodModel.value.paypal == null
|
||||
? Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your Setup is pending".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return payPalDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Setup now".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.secondary300,
|
||||
color: isDark ? AppThemeData.secondary300 : AppThemeData.secondary300,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Setup was done.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 52,
|
||||
width: 52,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.asset("assets/images/razorpay.png"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"RazorPay".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.withdrawMethodModel.value.razorpay != null
|
||||
? Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return razorPayDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_edit_coupon.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
controller.withdrawMethodModel.value.razorpay = null;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method remove successfully".tr);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_delete-one.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
controller.withdrawMethodModel.value.razorpay == null
|
||||
? Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your Setup is pending".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return razorPayDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Setup now".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.secondary300,
|
||||
color: isDark ? AppThemeData.secondary300 : AppThemeData.secondary300,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Setup was done.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 52,
|
||||
width: 52,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.asset("assets/images/stripe.png"),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Stripe".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
controller.withdrawMethodModel.value.stripe != null
|
||||
? Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return stripeDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_edit_coupon.svg"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
controller.withdrawMethodModel.value.stripe = null;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method remove successfully".tr);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 1, color: isDark ? AppThemeData.grey800 : AppThemeData.grey100),
|
||||
borderRadius: BorderRadius.circular(120),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset("assets/icons/ic_delete-one.svg"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: MySeparator(color: isDark ? AppThemeData.grey700 : AppThemeData.grey200),
|
||||
),
|
||||
controller.withdrawMethodModel.value.stripe == null
|
||||
? Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your Setup is pending".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.grey50 : AppThemeData.grey900, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return stripeDialog(controller, isDark);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Setup now".tr,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: AppThemeData.secondary300,
|
||||
color: isDark ? AppThemeData.secondary300 : AppThemeData.secondary300,
|
||||
fontSize: 16,
|
||||
fontFamily: AppThemeData.medium),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Setup was done.".tr,
|
||||
style: TextStyle(color: isDark ? AppThemeData.success400 : AppThemeData.success400, fontSize: 16, fontFamily: AppThemeData.medium),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Dialog flutterWaveDialog(WithdrawMethodSetupController controller, isDark) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
insetPadding: const EdgeInsets.all(10),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Account Number'.tr,
|
||||
controller: controller.accountNumberFlutterWave.value,
|
||||
hintText: 'Account Number'.tr,
|
||||
),
|
||||
TextFieldWidget(
|
||||
title: 'Bank Code'.tr,
|
||||
controller: controller.bankCodeFlutterWave.value,
|
||||
hintText: 'Bank Code'.tr,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.accountNumberFlutterWave.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter account Number".tr);
|
||||
} else if (controller.bankCodeFlutterWave.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter bank code".tr);
|
||||
} else {
|
||||
FlutterWave? flutterWave = controller.withdrawMethodModel.value.flutterWave;
|
||||
if (flutterWave != null) {
|
||||
flutterWave.accountNumber = controller.accountNumberFlutterWave.value.text;
|
||||
flutterWave.bankCode = controller.bankCodeFlutterWave.value.text;
|
||||
} else {
|
||||
flutterWave =
|
||||
FlutterWave(accountNumber: controller.accountNumberFlutterWave.value.text, bankCode: controller.bankCodeFlutterWave.value.text, name: "FlutterWave");
|
||||
}
|
||||
controller.withdrawMethodModel.value.flutterWave = flutterWave;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method save successfully".tr);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Dialog payPalDialog(WithdrawMethodSetupController controller, isDark) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
insetPadding: const EdgeInsets.all(10),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Paypal Email'.tr,
|
||||
controller: controller.emailPaypal.value,
|
||||
hintText: 'Paypal Email'.tr,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.emailPaypal.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter Paypal email".tr);
|
||||
} else {
|
||||
Paypal? payPal = controller.withdrawMethodModel.value.paypal;
|
||||
if (payPal != null) {
|
||||
payPal.email = controller.emailPaypal.value.text;
|
||||
} else {
|
||||
payPal = Paypal(email: controller.emailPaypal.value.text, name: "PayPal");
|
||||
}
|
||||
controller.withdrawMethodModel.value.paypal = payPal;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method save successfully".tr);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Dialog razorPayDialog(WithdrawMethodSetupController controller, isDark) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
insetPadding: const EdgeInsets.all(10),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Razorpay account Id'.tr,
|
||||
controller: controller.accountIdRazorPay.value,
|
||||
hintText: 'Razorpay account Id'.tr,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text(
|
||||
"Add your Account ID. For example, acc_GLGeLkU2JUeyDZ".tr,
|
||||
style: TextStyle(fontWeight: FontWeight.bold, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.accountIdRazorPay.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter RazorPay account Id".tr);
|
||||
} else {
|
||||
RazorpayModel? razorPay = controller.withdrawMethodModel.value.razorpay;
|
||||
if (razorPay != null) {
|
||||
razorPay.accountId = controller.accountIdRazorPay.value.text;
|
||||
} else {
|
||||
razorPay = RazorpayModel(accountId: controller.accountIdRazorPay.value.text, name: "RazorPay");
|
||||
}
|
||||
controller.withdrawMethodModel.value.razorpay = razorPay;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method save successfully".tr);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Dialog stripeDialog(WithdrawMethodSetupController controller, isDark) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
insetPadding: const EdgeInsets.all(10),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
backgroundColor: isDark ? AppThemeData.surfaceDark : AppThemeData.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFieldWidget(
|
||||
title: 'Stripe Account Id'.tr,
|
||||
controller: controller.accountIdStripe.value,
|
||||
hintText: 'Stripe Account Id'.tr,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text(
|
||||
"Go to your Stripe account settings > Account details > Copy your account ID on the right-hand side. For example, acc_GLGeLkU2JUeyDZ".tr,
|
||||
style: TextStyle(fontWeight: FontWeight.bold, color: isDark ? AppThemeData.grey500 : AppThemeData.grey400),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
RoundedButtonFill(
|
||||
title: "Save".tr,
|
||||
color: AppThemeData.primary300,
|
||||
textColor: AppThemeData.grey50,
|
||||
onPress: () async {
|
||||
if (controller.accountIdStripe.value.text.isEmpty) {
|
||||
ShowToastDialog.showToast("Please enter stripe account Id".tr);
|
||||
} else {
|
||||
Stripe? stripe = controller.withdrawMethodModel.value.stripe;
|
||||
if (stripe != null) {
|
||||
stripe.accountId = controller.accountIdStripe.value.text;
|
||||
} else {
|
||||
stripe = Stripe(accountId: controller.accountIdStripe.value.text, name: "Stripe");
|
||||
}
|
||||
controller.withdrawMethodModel.value.stripe = stripe;
|
||||
await FireStoreUtils.setWithdrawMethod(controller.withdrawMethodModel.value).then(
|
||||
(value) async {
|
||||
ShowToastDialog.showLoader("Please wait.".tr);
|
||||
|
||||
await controller.getPaymentMethod();
|
||||
ShowToastDialog.closeLoader();
|
||||
ShowToastDialog.showToast("Payment Method save successfully".tr);
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user