From c1b01c156561a2ef606c6bbd1aa2148b8e90d38e Mon Sep 17 00:00:00 2001 From: Aamir Date: Thu, 24 Oct 2024 14:39:09 +0300 Subject: [PATCH 01/11] changes --- lib/classes/app_state.dart | 2 +- .../subscription_model.dart | 4 + lib/services/common_auth_service.dart | 15 +- lib/services/payments_service.dart | 50 ++-- lib/utils/enums.dart | 6 +- lib/view_models/payment_view_model.dart | 3 +- lib/view_models/service_view_model.dart | 3 +- .../setting_options_language.dart | 252 +++++++++--------- lib/views/user/login_with_password_page.dart | 37 +-- pubspec.yaml | 30 +-- 10 files changed, 213 insertions(+), 189 deletions(-) diff --git a/lib/classes/app_state.dart b/lib/classes/app_state.dart index d8e4dce..ee491de 100644 --- a/lib/classes/app_state.dart +++ b/lib/classes/app_state.dart @@ -65,7 +65,7 @@ class AppState { List? _providerSubscription; - List get getproviderSubscription => _providerSubscription!; + List get getproviderSubscription => _providerSubscription ?? [new Subscription(name: "")]; set setproviderSubscription(List value) { _providerSubscription = value; diff --git a/lib/models/subscriptions_models/subscription_model.dart b/lib/models/subscriptions_models/subscription_model.dart index fc77955..9697266 100644 --- a/lib/models/subscriptions_models/subscription_model.dart +++ b/lib/models/subscriptions_models/subscription_model.dart @@ -69,6 +69,7 @@ class Subscription { this.totalAds, this.branchesRemaining, this.subUsersRemaining, + this.subscriptionType, this.adsRemaining}); int? id; @@ -90,6 +91,7 @@ class Subscription { SubscriptionTypeEnum? subscriptionTypeEnum; bool? isMyCurrentPackage; bool? isRenewable; + int? subscriptionType; int? subscriptionBranches; int? subscriptionSubUsers; @@ -130,6 +132,7 @@ class Subscription { branchesRemaining: json["branchesRemaining"], subUsersRemaining: json["subUsersRemaining"], adsRemaining: json["adsRemaining"], + subscriptionType: json["subscriptionType"], ); Map toJson() => { @@ -159,5 +162,6 @@ class Subscription { "branchesRemaining": branchesRemaining, "subUsersRemaining": subUsersRemaining, "adsRemaining": adsRemaining, + "subscriptionType": subscriptionType, }; } diff --git a/lib/services/common_auth_service.dart b/lib/services/common_auth_service.dart index 1f52e02..c1b5969 100644 --- a/lib/services/common_auth_service.dart +++ b/lib/services/common_auth_service.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/services.dart'; -import 'package:huawei_fido/huawei_fido.dart'; import 'package:local_auth/local_auth.dart'; import 'package:local_auth_android/local_auth_android.dart'; import 'package:local_auth_darwin/types/auth_messages_ios.dart'; @@ -61,11 +60,11 @@ class CommonAuthImp implements CommonAuthServices { return await localAuth.getAvailableBiometrics(); } - Future getHuaweiAuth() async { - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - // if (androidInfo.brand == "HUAWEI") { - // huawei.canAuth(); - // } - } +// Future getHuaweiAuth() async { +// DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); +// AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; +// // if (androidInfo.brand == "HUAWEI") { +// // huawei.canAuth(); +// // } +// } } diff --git a/lib/services/payments_service.dart b/lib/services/payments_service.dart index aed50b8..51df85a 100644 --- a/lib/services/payments_service.dart +++ b/lib/services/payments_service.dart @@ -26,13 +26,25 @@ abstract class PaymentService { class PaymentServiceImp implements PaymentService { MyInAppBrowser? myInAppBrowser; - var inAppBrowserOptions = InAppBrowserClassOptions( - inAppWebViewGroupOptions: - InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), - crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black), - android: AndroidInAppBrowserOptions(), - ios: - IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); + + var inAppBrowserOptions = InAppBrowserClassSettings( + webViewSettings: InAppWebViewSettings( + useShouldOverrideUrlLoading: false, + transparentBackground: false, + isInspectable: false, + applePayAPIEnabled: true, + cacheEnabled: false, + ), + browserSettings: InAppBrowserSettings( + hideUrlBar: true, + hideTitleBar: true, + hideDefaultMenuItems: false, + toolbarBottomBackgroundColor: Colors.black, + closeButtonColor: Colors.white, + presentationStyle: ModalPresentationStyle.OVER_FULL_SCREEN, + // toolbarTopBackgroundColor: Colors.black + ), + ); @override Future placePayment({ @@ -75,15 +87,23 @@ class PaymentServiceImp implements PaymentService { break; } log("PaymentUrl: $urlRequest"); - myInAppBrowser = MyInAppBrowser(onExitCallback: () { - log("Browser Exited"); - }, onLoadStartCallback: (String url) { - log("Browser LoadStart for : $url"); - onBrowserLoadStart(onFailure: onFailure, onSuccess: onSuccess, url: url); - }); + myInAppBrowser = MyInAppBrowser( + onExitCallback: () { + log("Browser Exited"); + }, + onLoadStartCallback: (String url) { + log("Browser LoadStart for : $url"); + onBrowserLoadStart(onFailure: onFailure, onSuccess: onSuccess, url: url); + }, + ); await myInAppBrowser!.openUrlRequest( - urlRequest: URLRequest(url: Uri.parse(urlRequest)), - options: inAppBrowserOptions, + urlRequest: URLRequest( + url: WebUri('${Uri.parse(urlRequest)}', forceToStringRawValue: true), + allowsCellularAccess: true, + allowsConstrainedNetworkAccess: true, + allowsExpensiveNetworkAccess: true, + ), + settings: inAppBrowserOptions, ); } diff --git a/lib/utils/enums.dart b/lib/utils/enums.dart index b214b10..980ae1b 100644 --- a/lib/utils/enums.dart +++ b/lib/utils/enums.dart @@ -187,9 +187,9 @@ enum ChatTypeEnum { } enum SubscriptionTypeEnum { - current, - upgrade, - downgrade, + current, //1 + upgrade, //2 + downgrade, //3 } enum SubscriptionActionTypeEnum { diff --git a/lib/view_models/payment_view_model.dart b/lib/view_models/payment_view_model.dart index 89fba48..af993fd 100644 --- a/lib/view_models/payment_view_model.dart +++ b/lib/view_models/payment_view_model.dart @@ -213,9 +213,8 @@ class PaymentVM extends ChangeNotifier { onSubscriptionPaymentSuccess(BuildContext context) { pop(context); - // context.read().getMySubscriptions(AppState().getUser.data?.userInfo?.providerId.toString() ?? ""); - context.read().getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true); + // context.read().getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true); // context.read().mySubscriptionsBySp = []; // context.read().getMySubscriptionsBySP(); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index a7e9715..11ba597 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -272,7 +272,8 @@ class ServiceVM extends BaseVM { Future getBranchAndServices() async { setState(ViewState.busy); branches = await branchRepo.getBranchAndServices(); - homePageBranches = branches!.data!.serviceProviderBranch!.where((element) => element.branchStatus == BranchStatusEnum.approvedOrActive).toList(); + if (branches!.data != null) + homePageBranches = branches!.data!.serviceProviderBranch!.where((element) => element.branchStatus == BranchStatusEnum.approvedOrActive).toList(); setState(ViewState.idle); } diff --git a/lib/views/setting_options/setting_options_language.dart b/lib/views/setting_options/setting_options_language.dart index d58628a..34f9053 100644 --- a/lib/views/setting_options/setting_options_language.dart +++ b/lib/views/setting_options/setting_options_language.dart @@ -40,141 +40,141 @@ class _SettingOptionsLanguageState extends State { // ? Expanded( child: ListView( - shrinkWrap: true, - padding: EdgeInsets.zero, - children: [ - Column( + shrinkWrap: true, + padding: EdgeInsets.zero, children: [ - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.quickreply_outlined, size: 20), - titleText: LocaleKeys.requests.tr(), - needBorderBelow: true, - onTap: () { - context.read().onNavbarTapped(4); - Navigator.pop(context); - }), - if (AppState().currentAppType == AppType.customer) ...[ - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.favorite, size: 20), - titleText: LocaleKeys.favoriteList.tr(), - needBorderBelow: true, - onTap: () => navigateWithName(context, AppRoutes.favoriteListView), - ), - ], - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.settings, size: 20), - titleText: LocaleKeys.settings.tr(), - needBorderBelow: true, - onTap: () {}, - //navigateWithName(context, AppRoutes.settingOptionsInviteFriends), - ), - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.question_mark_outlined, size: 20), - titleText: LocaleKeys.help.tr(), - needBorderBelow: true, - onTap: () => navigateWithName(context, AppRoutes.settingOptionsHelp), - ), - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.person, size: 20), - titleText: LocaleKeys.account.tr(), - needBorderBelow: false, - onTap: () { - navigateWithName(context, AppRoutes.profileView); - // context.read().onNavbarTapped(4); - // Navigator.pop(context); - }), - ], - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), - 10.height, - CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.translate, size: 20), - titleText: LocaleKeys.language.tr(), - isForLanguage: true, - onTap: () { - context.read().changeLanguage(context); - Future.delayed(Duration(seconds: 1), () { - setState(() {}); - }); - }, - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), - 10.height, - (AppState().currentAppType == AppType.provider) - ? Column( - children: [ - CustomSettingOptionsTile( - leadingWidget: SizedBox( - width: 16, - height: 16, - child: SvgPicture.asset( - MyAssets.icStar, - color: MyColors.primaryColor, - ), - ), - titleText: LocaleKeys.mySubscription.tr(), - subTitle: AppState().getproviderSubscription.first.name ?? "Silver", - isForLanguage: false, + Column( + children: [ + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.quickreply_outlined, size: 20), + titleText: LocaleKeys.requests.tr(), needBorderBelow: true, onTap: () { - navigateWithName(context, AppRoutes.mySubscriptionsPage); - }, - ), + context.read().onNavbarTapped(4); + Navigator.pop(context); + }), + if (AppState().currentAppType == AppType.customer) ...[ CustomSettingOptionsTile( - leadingWidget: SizedBox( - width: 16, - height: 16, - child: SvgPicture.asset( - MyAssets.icGroupStar, - // color: MyColors.primaryColor, - ), - ), - titleText: LocaleKeys.subscriptions.tr(), - subTitle: null, - isForLanguage: false, + leadingWidget: const Icon(Icons.favorite, size: 20), + titleText: LocaleKeys.favoriteList.tr(), needBorderBelow: true, - onTap: () { - navigateWithName(context, AppRoutes.subscriptionsPage); - }, + onTap: () => navigateWithName(context, AppRoutes.favoriteListView), ), - CustomSettingOptionsTile( - leadingWidget: SizedBox( - width: 16, - height: 16, - child: SvgPicture.asset( - MyAssets.icGroupStar, - // color: MyColors.primaryColor, - ), - ), - titleText: LocaleKeys.defineLicenses.tr(), - subTitle: null, - isForLanguage: false, + ], + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.settings, size: 20), + titleText: LocaleKeys.settings.tr(), + needBorderBelow: true, + onTap: () {}, + //navigateWithName(context, AppRoutes.settingOptionsInviteFriends), + ), + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.question_mark_outlined, size: 20), + titleText: LocaleKeys.help.tr(), + needBorderBelow: true, + onTap: () => navigateWithName(context, AppRoutes.settingOptionsHelp), + ), + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.person, size: 20), + titleText: LocaleKeys.account.tr(), needBorderBelow: false, onTap: () { - navigateWithName(context, AppRoutes.providerLicensePage); - }, + navigateWithName(context, AppRoutes.profileView); + // context.read().onNavbarTapped(4); + // Navigator.pop(context); + }), + ], + ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), + 10.height, + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.translate, size: 20), + titleText: LocaleKeys.language.tr(), + isForLanguage: true, + onTap: () { + context.read().changeLanguage(context); + Future.delayed(Duration(seconds: 1), () { + setState(() {}); + }); + }, + ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), + 10.height, + (AppState().currentAppType == AppType.provider) + ? Column( + children: [ + CustomSettingOptionsTile( + leadingWidget: SizedBox( + width: 16, + height: 16, + child: SvgPicture.asset( + MyAssets.icStar, + color: MyColors.primaryColor, + ), ), - // CustomSettingOptionsTile( - // leadingWidget: SizedBox( - // width: 16, - // height: 16, - // child: SvgPicture.asset( - // MyAssets.providersIcon, - // // color: MyColors.primaryColor, - // ), - // ), - // titleText: "Users", - // subTitle: null, - // isForLanguage: false, - // needBorderBelow: false, - // onTap: () { - // navigateWithName(context, AppRoutes.dealerUser, arguments: AppState().getUser.data!.userInfo!.id.toString()); - // }, - // ) - ], - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0) - : const SizedBox(), - (AppState().currentAppType == AppType.provider) ? 10.height : const SizedBox(), - ], - )), + titleText: LocaleKeys.mySubscription.tr(), + subTitle: AppState().getproviderSubscription.first.name, + isForLanguage: false, + needBorderBelow: true, + onTap: () { + navigateWithName(context, AppRoutes.mySubscriptionsPage); + }, + ), + CustomSettingOptionsTile( + leadingWidget: SizedBox( + width: 16, + height: 16, + child: SvgPicture.asset( + MyAssets.icGroupStar, + // color: MyColors.primaryColor, + ), + ), + titleText: LocaleKeys.subscriptions.tr(), + subTitle: null, + isForLanguage: false, + needBorderBelow: true, + onTap: () { + navigateWithName(context, AppRoutes.subscriptionsPage); + }, + ), + CustomSettingOptionsTile( + leadingWidget: SizedBox( + width: 16, + height: 16, + child: SvgPicture.asset( + MyAssets.icGroupStar, + // color: MyColors.primaryColor, + ), + ), + titleText: LocaleKeys.defineLicenses.tr(), + subTitle: null, + isForLanguage: false, + needBorderBelow: false, + onTap: () { + navigateWithName(context, AppRoutes.providerLicensePage); + }, + ), + // CustomSettingOptionsTile( + // leadingWidget: SizedBox( + // width: 16, + // height: 16, + // child: SvgPicture.asset( + // MyAssets.providersIcon, + // // color: MyColors.primaryColor, + // ), + // ), + // titleText: "Users", + // subTitle: null, + // isForLanguage: false, + // needBorderBelow: false, + // onTap: () { + // navigateWithName(context, AppRoutes.dealerUser, arguments: AppState().getUser.data!.userInfo!.id.toString()); + // }, + // ) + ], + ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0) + : const SizedBox(), + (AppState().currentAppType == AppType.provider) ? 10.height : const SizedBox(), + ], + )), // : Expanded( // child: ListView( // children: [ diff --git a/lib/views/user/login_with_password_page.dart b/lib/views/user/login_with_password_page.dart index 4f25a70..094ba2d 100644 --- a/lib/views/user/login_with_password_page.dart +++ b/lib/views/user/login_with_password_page.dart @@ -34,7 +34,8 @@ class _LoginWithPasswordState extends State { //TODO: ONLY FOR DEVELOPMENT PURPOSE // String phoneNum = "966504278212", password = "Fa@1234"; - String phoneNum = "966504278213", password = "Fa@1234"; + // String phoneNum = "966504278213", password = "Fa@1234"; + String phoneNum = "", password = ""; // String phoneNum = "", password = ""; String email = ""; @@ -51,23 +52,23 @@ class _LoginWithPasswordState extends State { scheduleMicrotask(() { userVM = Provider.of(context, listen: false); context.read().getAvailBio(); - if (AppState().currentAppType == AppType.provider) { - phoneNum = "966530896018"; - password = "Amir@1234"; - // - // // phoneNum = "966569755630"; - // // password = "Amir12345@"; //AAmir Sal - // - // // phoneNum = "966598646795"; - // // password = "Zahoor@123"; - // - // // User Details - // // phoneNum = "966554870506"; - // // password = "Sikander123@"; // "lastName": "sik", - // // "email": "sikander@gmail.com", - // // phoneNum = "966569755630"; - // // password = "Amir12345@"; - } + // if (AppState().currentAppType == AppType.provider) { + // phoneNum = "966530896018"; + // password = "Amir@1234"; + // // + // // // phoneNum = "966569755630"; + // // // password = "Amir12345@"; //AAmir Sal + // // + // // // phoneNum = "966598646795"; + // // // password = "Zahoor@123"; + // // + // // // User Details + // // // phoneNum = "966554870506"; + // // // password = "Sikander123@"; // "lastName": "sik", + // // // "email": "sikander@gmail.com", + // // // phoneNum = "966569755630"; + // // // password = "Amir12345@"; + // } getCountryList(); }); diff --git a/pubspec.yaml b/pubspec.yaml index b85f5e6..77d9a49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,28 +13,28 @@ dependencies: cupertino_icons: ^1.0.2 path_provider: ^2.0.4 - injector: ^2.0.0 + injector: ^4.0.0 provider: ^6.0.0 easy_localization: ^3.0.3 http: ^0.13.3 permission_handler: ^11.3.1 - flutter_svg: ^1.0.3 - sizer: ^2.0.15 + flutter_svg: ^2.0.9 + sizer: any fluttertoast: ^8.0.8 shared_preferences: ^2.0.6 - file_picker: ^6.1.1 - image_picker: ^0.8.4+4 + file_picker: ^8.1.2 + image_picker: ^1.1.2 equatable: ^2.0.3 - logger: 2.3.0 + logger: ^2.4.0 auto_size_text: any - shimmer: ^2.0.0 + shimmer: ^3.0.0 hexcolor: ^3.0.1 cached_network_image: any url_launcher: ^6.1.14 badges: ^3.0.2 carousel_slider: 5.0.0 dropdown_button2: ^2.0.0 - flutter_inappwebview: ^5.7.2+3 + flutter_inappwebview: ^6.1.5 country_code_picker: ^3.0.0 table_calendar: ^3.0.9 intl: any @@ -46,9 +46,9 @@ dependencies: # Firebase Packages - firebase_messaging: ^15.0.4 - firebase_core: ^3.3.0 - flutter_local_notifications: ^17.2.1+2 + firebase_messaging: ^15.1.3 + firebase_core: ^3.6.0 + flutter_local_notifications: ^17.2.3 # google @@ -60,15 +60,15 @@ dependencies: # Auth local_auth: ^2.2.0 - huawei_fido: ^6.3.0+305 - device_info_plus: ^10.1.0 - + #huawei_fido: ^6.3.0+305 + device_info_plus: ^11.0.0 + flutter_lints: any dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter: From 327f9d41b7c5fd760518c1ec2fbd50d1d291edfc Mon Sep 17 00:00:00 2001 From: Aamir Date: Thu, 24 Oct 2024 16:11:04 +0300 Subject: [PATCH 02/11] changes --- .../profile/document.dart | 39 ++--- lib/services/payments_service.dart | 8 +- .../provider_license_page.dart | 135 +++++++++--------- 3 files changed, 98 insertions(+), 84 deletions(-) diff --git a/lib/models/provider_branches_models/profile/document.dart b/lib/models/provider_branches_models/profile/document.dart index eb6d2f8..d82aa02 100644 --- a/lib/models/provider_branches_models/profile/document.dart +++ b/lib/models/provider_branches_models/profile/document.dart @@ -21,14 +21,16 @@ class Document { int? messageStatus; String? message; - factory Document.fromJson(Map json) => Document( + factory Document.fromJson(Map json) => + Document( totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : List.from(json["data"].map((x) => DocumentData.fromJson(x))), messageStatus: json["messageStatus"], message: json["message"], ); - Map toJson() => { + Map toJson() => + { "totalItemsCount": totalItemsCount, "data": data == null ? null : List.from(data!.map((x) => x.toJson())), "messageStatus": messageStatus, @@ -50,6 +52,7 @@ class DocumentData { this.fileExt, this.documentName, this.isLocalFile, + this.description, }); int? id; @@ -64,22 +67,26 @@ class DocumentData { String? statusText; String? documentName; bool? isLocalFile; + String? description; - factory DocumentData.fromJson(Map json) => DocumentData( - id: json["id"], - serviceProviderId: json["serviceProviderID"], - documentId: json["documentID"], - documentUrl: json["documentURL"], - status: json["status"], - statusText: json["statusText"], - comment: json["comment"], - isActive: json["isActive"], - document: null, - fileExt: null, - documentName: json["documentName"], - isLocalFile: false); + factory DocumentData.fromJson(Map json) => + DocumentData( + id: json["id"], + serviceProviderId: json["serviceProviderID"], + documentId: json["documentID"], + documentUrl: json["documentURL"], + status: json["status"], + statusText: json["statusText"], + comment: json["comment"], + isActive: json["isActive"], + document: null, + fileExt: null, + documentName: json["documentName"], + isLocalFile: false, + description: null); - Map toJson() => { + Map toJson() => + { "id": id, "serviceProviderID": serviceProviderId, "documentID": documentId, diff --git a/lib/services/payments_service.dart b/lib/services/payments_service.dart index 36f5c91..4f8901d 100644 --- a/lib/services/payments_service.dart +++ b/lib/services/payments_service.dart @@ -27,10 +27,12 @@ abstract class PaymentService { class PaymentServiceImp implements PaymentService { MyInAppBrowser? myInAppBrowser; var inAppBrowserOptions = InAppBrowserClassOptions( - inAppWebViewGroupOptions: InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), + inAppWebViewGroupOptions: + InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black), android: AndroidInAppBrowserOptions(), - ios: IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); + ios: + IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); String getUrlRequestByPaymentId({required int id, List? appointmentIds, required PaymentTypes paymentType}) { String urlRequest = ""; @@ -87,7 +89,7 @@ class PaymentServiceImp implements PaymentService { onBrowserLoadStart(onFailure: onFailure, onSuccess: onSuccess, url: url); }); await myInAppBrowser!.openUrlRequest( - urlRequest: URLRequest(url: Uri.parse(urlRequest)), + urlRequest: URLRequest(url: WebUri(urlRequest, forceToStringRawValue: true)), options: inAppBrowserOptions, ); } diff --git a/lib/views/setting_options/provider_license_page.dart b/lib/views/setting_options/provider_license_page.dart index 9d17e99..6ae4eea 100644 --- a/lib/views/setting_options/provider_license_page.dart +++ b/lib/views/setting_options/provider_license_page.dart @@ -130,72 +130,77 @@ class _ProviderLicensePageState extends State { return serviceVM.document!.data!.isEmpty ? Text(LocaleKeys.somethingWrong.tr()) : ListView.separated( - separatorBuilder: (context, index) { - return 20.height; - }, - itemCount: serviceVM.document!.data!.length, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: const EdgeInsets.symmetric(horizontal: 20), - itemBuilder: (context, index) { - DocumentData? document = serviceVM.document?.data![index]; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (document!.documentName!).toText(fontSize: 16, letterSpacing: -0.56, fontWeight: MyFonts.SemiBold), - if (document.statusText != null && document.statusText!.isNotEmpty) ...[ - 10.width, - Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status ?? 1)), - ], - ], - ), - if (document.status != 1 && document.status != 3) ...[ - Padding( - padding: const EdgeInsets.only(top: 4, bottom: 8), - child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor), - ), - TxtField( - hint: LocaleKeys.description.tr(), - maxLines: 3, - isBackgroundEnabled: true, - ), - ], - 10.height, - if (isNeedToShow(model: serviceVM, document: document)) ...[ - PickedFilesContainer( - isReview: document.status == 4, - allowAdButton: false, - pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document), - onCrossPressedPrimary: isNetworkImage(document: document) - ? serviceVM.removeNetworkImage - : document.documentId == 1 - ? serviceVM.commerceRemove - : document.documentId == 2 - ? serviceVM.commercialRemove - : serviceVM.vatRemove, - isPdf: serviceVM.document!.data![index].fileExt == "pdf", - isFromNetwork: !(document.isLocalFile ?? false), - onAddFilePressed: () { - serviceVM.pickPdfReceiptFile(context, document.documentId!, index); - }, - ), - buildCommentContainer(document: document), - ] else ...[ - 10.height, - DottedRectContainer( - onTap: () => serviceVM.pickPdfReceiptFile(context, document.documentId!, index) ?? "", - text: LocaleKeys.attachImage.tr(), - icon: MyAssets.attachmentIcon.buildSvg(), - ), - ], + separatorBuilder: (context, index) { + return 20.height; + }, + itemCount: serviceVM.document!.data!.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.symmetric(horizontal: 20), + itemBuilder: (context, index) { + DocumentData? document = serviceVM.document?.data![index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (document!.documentName!).toText(fontSize: 16, letterSpacing: -0.56, fontWeight: MyFonts.SemiBold), + if (document.statusText != null && document.statusText!.isNotEmpty) ...[ + 10.width, + Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status ?? 1)), ], - ); - }, - ); + ], + ), + if (document.status != 1 && document.status != 3) ...[ + Padding( + padding: const EdgeInsets.only(top: 4, bottom: 8), + child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor), + ), + TxtField( + hint: LocaleKeys.description.tr(), + maxLines: 3, + isBackgroundEnabled: true, + value: document.description != null ? document.description : "", + onChanged: (val) { + document.description = val; + }, + ), + ], + 10.height, + if (isNeedToShow(model: serviceVM, document: document)) ...[ + PickedFilesContainer( + isReview: document.status == 4, + allowAdButton: false, + pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document), + onCrossPressedPrimary: isNetworkImage(document: document) + ? serviceVM.removeNetworkImage + : document.documentId == 1 + ? serviceVM.commerceRemove + : document.documentId == 2 + ? serviceVM.commercialRemove + : serviceVM.vatRemove, + isPdf: serviceVM.document!.data![index].fileExt == "pdf", + isFromNetwork: !(document.isLocalFile ?? false), + onAddFilePressed: () { + serviceVM.pickPdfReceiptFile(context, document.documentId!, index); + }, + ), + buildCommentContainer(document: document), + ] else + ...[ + 10.height, + DottedRectContainer( + onTap: () => serviceVM.pickPdfReceiptFile(context, document.documentId!, index) ?? "", + text: LocaleKeys.attachImage.tr(), + icon: MyAssets.attachmentIcon.buildSvg(), + ), + ], + ], + ); + }, + ); } List isLocalOrNetworkFiles({required ServiceVM model, required DocumentData document}) { From 73080483fcd09d15621632e131d539056443063d Mon Sep 17 00:00:00 2001 From: Aamir Date: Sun, 3 Nov 2024 10:18:24 +0300 Subject: [PATCH 03/11] changes --- assets/langs/ar-SA.json | 3 +- assets/langs/en-US.json | 3 +- lib/config/dependency_injection.dart | 2 + lib/generated/codegen_loader.g.dart | 6 +- lib/generated/locale_keys.g.dart | 1 + lib/services/common_services.dart | 1 + lib/services/payments_service.dart | 39 +++- lib/utils/location/Location.dart | 44 +++- lib/view_models/payment_view_model.dart | 2 +- lib/view_models/service_view_model.dart | 46 +++- lib/view_models/subscriptions_view_model.dart | 18 +- .../location_views/map_selection_widget.dart | 4 +- .../location_views/pick_location_page.dart | 39 ++-- .../provider_license_page.dart | 218 ++++++++++-------- 14 files changed, 268 insertions(+), 158 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 0e1df59..9556085 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -679,5 +679,6 @@ "inviteFriendsByWhatsApp": "دعوة الأصدقاء عبر واتساب", "inviteFriendsByEmail": "دعوة الأصدقاء عبر البريد الإلكتروني", "noFAQsToShow": "لا توجد أسئلة شائعة في الوقت الحالي. يرجى الاتصال بنا إذا كان لديك أي استفسار.", - "appInfo": "معلومات التطبيق" + "appInfo": "معلومات التطبيق", + "attachPDF": "إرفاق قوات الدفاع الشعبي" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index a4cf2bd..f2508db 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -677,5 +677,6 @@ "inviteFriendsByWhatsApp": "Invite Friends By WhatsApp", "inviteFriendsByEmail": "Invite Friends By Email", "noFAQsToShow": "There are no Frequently asked Questions Right now. Please contact us if you have any query.", - "appInfo": "App Info" + "appInfo": "App Info", + "attachPDF": "Attach PDF" } \ No newline at end of file diff --git a/lib/config/dependency_injection.dart b/lib/config/dependency_injection.dart index 8a42acd..f79770c 100644 --- a/lib/config/dependency_injection.dart +++ b/lib/config/dependency_injection.dart @@ -18,6 +18,7 @@ import 'package:mc_common_app/repositories/user_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; import 'package:mc_common_app/services/firebase_service.dart'; import 'package:mc_common_app/services/payments_service.dart'; +import 'package:mc_common_app/utils/location/Location.dart'; import '../repositories/request_repo.dart'; @@ -46,6 +47,7 @@ class AppDependencies { injector.registerSingleton(() => BranchRepoImp()); injector.registerSingleton(() => ShippingRepoImp()); injector.registerSingleton(() => SettingOptionsRepoImp()); + injector.registerSingleton(() => LocationService()); // } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 5e42c42..5317da0 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -695,7 +695,8 @@ class CodegenLoader extends AssetLoader{ "inviteFriendsByWhatsApp": "دعوة الأصدقاء عبر واتساب", "inviteFriendsByEmail": "دعوة الأصدقاء عبر البريد الإلكتروني", "noFAQsToShow": "لا توجد أسئلة شائعة في الوقت الحالي. يرجى الاتصال بنا إذا كان لديك أي استفسار.", - "appInfo": "معلومات التطبيق" + "appInfo": "معلومات التطبيق", + "attachPDF": "إرفاق قوات الدفاع الشعبي" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1376,7 +1377,8 @@ static const Map en_US = { "inviteFriendsByWhatsApp": "Invite Friends By WhatsApp", "inviteFriendsByEmail": "Invite Friends By Email", "noFAQsToShow": "There are no Frequently asked Questions Right now. Please contact us if you have any query.", - "appInfo": "App Info" + "appInfo": "App Info", + "attachPDF": "Attach PDF" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 9734eae..92b01c9 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -659,5 +659,6 @@ abstract class LocaleKeys { static const inviteFriendsByEmail = 'inviteFriendsByEmail'; static const noFAQsToShow = 'noFAQsToShow'; static const appInfo = 'appInfo'; + static const attachPDF = 'attachPDF'; } diff --git a/lib/services/common_services.dart b/lib/services/common_services.dart index 53ffe31..b1788e5 100644 --- a/lib/services/common_services.dart +++ b/lib/services/common_services.dart @@ -6,6 +6,7 @@ import 'package:geolocator/geolocator.dart'; import 'package:image_picker/image_picker.dart'; import 'package:mc_common_app/main.dart'; import 'package:mc_common_app/utils/app_permission_handler.dart'; +import 'package:mc_common_app/utils/utils.dart'; abstract class CommonAppServices { Future> pickMultipleImages(); diff --git a/lib/services/payments_service.dart b/lib/services/payments_service.dart index 4f8901d..1a495f8 100644 --- a/lib/services/payments_service.dart +++ b/lib/services/payments_service.dart @@ -26,13 +26,29 @@ abstract class PaymentService { class PaymentServiceImp implements PaymentService { MyInAppBrowser? myInAppBrowser; - var inAppBrowserOptions = InAppBrowserClassOptions( - inAppWebViewGroupOptions: - InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), - crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black), - android: AndroidInAppBrowserOptions(), - ios: - IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); + var inAppBrowserOptions = InAppBrowserClassSettings( + + webViewSettings: InAppWebViewSettings( + useShouldOverrideUrlLoading: false, + transparentBackground: false, + isInspectable: false, + applePayAPIEnabled: true, + cacheEnabled: false, + ), + browserSettings: InAppBrowserSettings( + hideUrlBar: true, + hideTitleBar: true, + hideDefaultMenuItems: true, + hideToolbarBottom: true, + hideToolbarTop: false, + hideCloseButton: false, + allowGoBackWithBackButton: true, + toolbarBottomBackgroundColor: Colors.black, + closeButtonColor: Colors.white, + presentationStyle: ModalPresentationStyle.FULL_SCREEN, + // toolbarTopBackgroundColor: Colors.black + ), + ); String getUrlRequestByPaymentId({required int id, List? appointmentIds, required PaymentTypes paymentType}) { String urlRequest = ""; @@ -89,8 +105,13 @@ class PaymentServiceImp implements PaymentService { onBrowserLoadStart(onFailure: onFailure, onSuccess: onSuccess, url: url); }); await myInAppBrowser!.openUrlRequest( - urlRequest: URLRequest(url: WebUri(urlRequest, forceToStringRawValue: true)), - options: inAppBrowserOptions, + urlRequest: URLRequest( + url: WebUri(urlRequest, forceToStringRawValue: true), + allowsCellularAccess: true, + allowsConstrainedNetworkAccess: true, + allowsExpensiveNetworkAccess: true, + ), + settings: inAppBrowserOptions, ); } diff --git a/lib/utils/location/Location.dart b/lib/utils/location/Location.dart index bdb67b4..0c6b6a7 100644 --- a/lib/utils/location/Location.dart +++ b/lib/utils/location/Location.dart @@ -7,17 +7,29 @@ import 'package:flutter/rendering.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/utils/app_permission_handler.dart'; import 'package:mc_common_app/utils/utils.dart'; // import 'package:geodesy/geodesy.dart' as geodesy; -//Created By Mr.Zohaib -class Location { +abstract class Location { + void handleLocationPermission(); + + void havePermission(Function(bool) callback); + + void isEnabled(Function(bool) callback); + + void listenGPS({bool change = true, Function(bool)? onChange}); + + void getCurrentLocation(Function(LatLng?) callback); +} + +class LocationService implements Location { static _Map map = _Map(); - static void havePermission(Function(bool) callback) { + void havePermission(Function(bool) callback) { Geolocator.checkPermission().then((value) async { if (value == LocationPermission.denied) { value = await Geolocator.requestPermission(); @@ -28,13 +40,26 @@ class Location { }); } - static void isEnabled(Function(bool) callback) { + void isEnabled(Function(bool) callback) { Geolocator.isLocationServiceEnabled().then((value) => callback(value)); } + void handleLocationPermission() { + havePermission((val) { + if (val) { + print(val); + getCurrentLocation((LatLng? latlng) { + print(latlng); + AppState().currentLocation = latlng ?? const LatLng(0, 0); + print("App State Location" + AppState().currentLocation.toJson().toString()); + }); + } + }); + } + static bool _listeningSettingChange = true; - static void listenGPS({bool change = true, Function(bool)? onChange}) async { + void listenGPS({bool change = true, Function(bool)? onChange}) async { _listeningSettingChange = change; if (change == false) return; @@ -46,10 +71,8 @@ class Location { }); } - static void getCurrentLocation(Function(LatLng?) callback) { + void getCurrentLocation(Function(LatLng?) callback) { void done(Position position) { - //AppStorage.sp.saveLocation(position); - LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude); callback(myCurrentLocation); } @@ -88,8 +111,7 @@ class Location { } class _Map { - Marker createMarker( - String id, { + Marker createMarker(String id, { required LatLng coordinates, BitmapDescriptor? icon, VoidCallback? onTap, @@ -139,7 +161,7 @@ class _Map { } void goToCurrentLocation({Completer? mapController, double? direction = 0.0, bool? animation}) { - Location.getCurrentLocation((location) { + LocationService().getCurrentLocation((location) { moveTo(location!, zoom: 17, mapController: mapController!, animation: animation, direction: direction!); }); } diff --git a/lib/view_models/payment_view_model.dart b/lib/view_models/payment_view_model.dart index 96a9af7..db53fb0 100644 --- a/lib/view_models/payment_view_model.dart +++ b/lib/view_models/payment_view_model.dart @@ -199,7 +199,7 @@ class PaymentVM extends ChangeNotifier { void onAppointmentSuccess(BuildContext context) { context.read().onNavbarTapped(1); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); - } + } Future onVisaCardSelected(BuildContext context, PaymentTypes paymentType) async { currentPaymentType = paymentType; diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index 90ad442..7644d40 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -93,15 +93,34 @@ class ServiceVM extends BaseVM { Future getServiceProviderDocument(int providerId) async { setState(ViewState.busy); + commerceCertificates.clear(); + commercialCertificates.clear(); + vatCertificates.clear(); + // 0 Need To Upload + //1 Pending + //2 + //3 Approved + //4 Rejected + // document = await branchRepo.getServiceProviderDocument(providerId); + // if (document != null && document!.data != null && document!.data!.isNotEmpty) { + // print(document!.data!.length); + // for (var doc in document!.data!) { + // print("doc: ${doc.status}"); + // if (doc.status != 3 || doc.status == 1) { + // updateIsAllDocsApproved(false); + // } + // } + // } + + // + document = await branchRepo.getServiceProviderDocument(providerId); - if (document != null && document!.data != null && document!.data!.isNotEmpty) { - for (var doc in document!.data!) { - log("doc: ${doc.status}"); - if (doc.status != 3) { - updateIsAllDocsApproved(false); - } - } - } + + // 0 Need To Upload + //1 Pending + //2 + //3 Approved + //4 Rejected setState(ViewState.idle); } @@ -210,10 +229,10 @@ class ServiceVM extends BaseVM { // return null; // } - bool isAllDocsApproved = false; + bool isShowContinue = true; - updateIsAllDocsApproved(var value) { - isAllDocsApproved = value; + updateIsShowContinue(var value) { + isShowContinue = value; notifyListeners(); } @@ -223,7 +242,12 @@ class ServiceVM extends BaseVM { context, allowMultiple: false, ); + if (files != null && files.any((file) => file.path.split('.').last.toLowerCase() != 'pdf')) { + Utils.showToast("Only PDF files are allowed"); + return; + } if (files == null) return; + for (var element in files) { imageModels.add(ImageModel( filePath: element.path, diff --git a/lib/view_models/subscriptions_view_model.dart b/lib/view_models/subscriptions_view_model.dart index deefeef..ddc0f84 100644 --- a/lib/view_models/subscriptions_view_model.dart +++ b/lib/view_models/subscriptions_view_model.dart @@ -3,6 +3,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart'; import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart'; import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/base_view_model.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import '../repositories/subscription_repo.dart'; @@ -61,21 +62,22 @@ class SubscriptionsVM extends BaseVM { monthlyTabs.first.isEnabled = true; selectedMonthlyTab = monthlyTabs.first; - filterSubscriptions(); - getMySubscriptionsBySP(); + await filterSubscriptions(); + await getMySubscriptionsBySP(); setState(ViewState.idle); } else { setState(ViewState.error); } } - String newPrice = ""; + String newPrice = "0.0"; calculationUpgradePrice(String? serviceProviderID, String? newSubscription) async { setState(ViewState.busy); GenericRespModel genericRespModel = await subscriptionRepo.calculationUpgradePrice(serviceProviderID, newSubscription); if (genericRespModel.messageStatus == 1) { setState(ViewState.idle); + print("=========== ${genericRespModel.data.toString()}================="); newPrice = genericRespModel.data.toString(); } else { setState(ViewState.error); @@ -114,7 +116,12 @@ class SubscriptionsVM extends BaseVM { } Future createSubscriptionOrder(int subscriptionId, bool isStartNow, bool isRenew, {bool isDegrade = false, List? listOfBranches, List? listOfUsers}) async { - Map map = {"providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", "subscriptionID": subscriptionId.toString(), "isStartNow": isStartNow.toString(), "isRenew": isRenew.toString()}; + Map map = { + "providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + "subscriptionID": subscriptionId.toString(), + "isStartNow": isStartNow.toString(), + "isRenew": isRenew.toString() + }; GenericRespModel genericRespModel = await subscriptionRepo.payForProviderSubscription(map); return genericRespModel; } @@ -185,6 +192,7 @@ class SubscriptionsVM extends BaseVM { // My Provider Subscription getMySubscriptionsBySP() async { setState(ViewState.busy); + mySubscriptionsBySp.clear(); if (mySubscriptionsBySp.isEmpty) { // allSubscriptions.data for (var element in allSubscriptions.data!) { @@ -192,9 +200,9 @@ class SubscriptionsVM extends BaseVM { mySubscriptionsBySp.add(element); } } - // mySubscriptionsBySp = await subscriptionRepo.getProviderSubscription(serviceProviderID: serviceProviderID); AppState().setproviderSubscription = mySubscriptionsBySp; } setState(ViewState.idle); } + } diff --git a/lib/views/location_views/map_selection_widget.dart b/lib/views/location_views/map_selection_widget.dart index dc28656..2275466 100644 --- a/lib/views/location_views/map_selection_widget.dart +++ b/lib/views/location_views/map_selection_widget.dart @@ -7,13 +7,14 @@ import 'package:google_maps_flutter/google_maps_flutter.dart'; class AppMap extends StatefulWidget { final CameraPositionCallback onCameraMove; + final VoidCallback onCameraIdle; Map initialCamera; late AppMapState _state; final Function onMapCreated; AppMap(this.initialCamera, - {required this.onCameraMove, required this.onMapCreated}); + {required this.onCameraMove, required this.onCameraIdle, required this.onMapCreated}); @override State createState() => _state = AppMapState(); @@ -59,6 +60,7 @@ class AppMapState extends State { const CameraPosition( target: LatLng(-26.1711459, 27.9002758), zoom: 2.0), onCameraMove: widget.onCameraMove, + onCameraIdle: widget.onCameraIdle, onMapCreated: (GoogleMapController controller) { googleMapController = controller; _googleMapControllerComp.complete(controller); diff --git a/lib/views/location_views/pick_location_page.dart b/lib/views/location_views/pick_location_page.dart index a4d4176..516b6a0 100644 --- a/lib/views/location_views/pick_location_page.dart +++ b/lib/views/location_views/pick_location_page.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; @@ -32,12 +33,11 @@ class _PickLocationPageState extends State { final Set markers = {}; late AppMap appMap; - static CameraPosition _kGooglePlex = const CameraPosition( - target: LatLng(37.42796133580664, -122.085749655962), + static CameraPosition _kGooglePlex = CameraPosition( + target: AppState().currentLocation, zoom: 14.4746, ); late LatLng currentPosition; - Completer mapController = Completer(); final ValueNotifier _counter = ValueNotifier(""); @override @@ -47,11 +47,15 @@ class _PickLocationPageState extends State { onCameraMove: (camera) { _updatePosition(camera); }, + onCameraIdle: (){ + print("===== Idle Triggered ====="); + updateAddress(latitude, longitude); + }, onMapCreated: () { - // goToCurrentLocation(); _getUserLocation(); setState(() {}); }, + ); super.initState(); } @@ -125,9 +129,7 @@ class _PickLocationPageState extends State { Future _updatePosition(CameraPosition position) async { latitude = position.target.latitude; longitude = position.target.longitude; - log(latitude.toString()); - log(latitude.toString()); - updateAddress(latitude, longitude); + // updateAddress(latitude, longitude); } void _getUserLocation() async { @@ -152,21 +154,28 @@ class _PickLocationPageState extends State { }, ); } + setState(() {}); } updateAddress(double latitude, double longitude) async { - List placemarks = await placemarkFromCoordinates(latitude, longitude); + print("========="); + List placemarks = await placemarkFromCoordinates(latitude, longitude).catchError((e) { + print(e); + }); + print(placemarks.length); + print("====end====="); _counter.value = '${placemarks.first.street}, ${placemarks.first.subLocality}, ${placemarks.first.locality}, ${placemarks.first.postalCode}, ${placemarks.first.country}'; + } setMap() { - setState(() { - _kGooglePlex = CameraPosition( - target: currentPosition, - zoom: 14.4746, - ); - appMap.moveTo(cameraPostion: _kGooglePlex); - }); + // setState(() { + _kGooglePlex = CameraPosition( + target: currentPosition, + zoom: 14.4746, + ); + appMap.moveTo(cameraPostion: _kGooglePlex); + // }); } Future getCurrentAddress() async { diff --git a/lib/views/setting_options/provider_license_page.dart b/lib/views/setting_options/provider_license_page.dart index 6ae4eea..ab535bd 100644 --- a/lib/views/setting_options/provider_license_page.dart +++ b/lib/views/setting_options/provider_license_page.dart @@ -58,40 +58,43 @@ class _ProviderLicensePageState extends State { child: CircularProgressIndicator(), ); } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: SingleChildScrollView(child: buildContent(serviceVM)), - ), - if (!serviceVM.isAllDocsApproved) ...[ - Padding( - padding: const EdgeInsets.all(12.0), - child: ShowFillButton( - title: LocaleKeys.continu.tr(), - maxWidth: double.infinity, - onPressed: () async { - bool status = false; - if (AppState().getUser.data!.userInfo!.roleId == 5) { - if (validateDocuments(serviceVM)) { - status = await updateDocument(serviceVM); + return GestureDetector( + onTap: () => FocusScope.of(context).focusedChild?.unfocus(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: SingleChildScrollView(child: buildContent(serviceVM)), + ), + if (isAllowContinue(serviceVM)) ...[ + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: LocaleKeys.continu.tr(), + maxWidth: double.infinity, + onPressed: () async { + bool status = false; + if (AppState().getUser.data!.userInfo!.roleId == 5) { + if (validateDocuments(serviceVM)) { + status = await updateDocument(serviceVM); + } else { + Utils.showToast(LocaleKeys.allDocumentMandatoryDealershipProvider.tr()); + return; + } } else { - Utils.showToast(LocaleKeys.allDocumentMandatoryDealershipProvider.tr()); - return; - } - } else { - status = await updateDocument(serviceVM); - } - Future.delayed(const Duration(seconds: 1), () { - if (status) { - pop(context); + status = await updateDocument(serviceVM); } - }); - }, + Future.delayed(const Duration(seconds: 1), () { + if (status != null && status) { + pop(context); + } + }); + }, + ), ), - ), + ], ], - ], + ), ); }), ); @@ -108,6 +111,19 @@ class _ProviderLicensePageState extends State { return valid; } + bool isAllowContinue(ServiceVM model) { + bool isShow = false; + if (model.document != null && model.document!.data != null && model.document!.data!.isNotEmpty) { + for (var doc in model.document!.data!) { + print("doc: ${doc.status}"); + if (doc.status == 4 || doc.status == 0) { + isShow = true; + } + } + } + return isShow; + } + Future updateDocument(ServiceVM model) async { try { Utils.showLoading(context); @@ -115,7 +131,7 @@ class _ProviderLicensePageState extends State { Utils.hideLoading(context); if (res.messageStatus == 1) { Utils.showToast(LocaleKeys.documentsUploadedSuccessfully.tr()); - Navigator.of(context).pop(); + // Navigator.of(context).pop(); return true; } else { Utils.showToast(res.message ?? ""); @@ -130,77 +146,77 @@ class _ProviderLicensePageState extends State { return serviceVM.document!.data!.isEmpty ? Text(LocaleKeys.somethingWrong.tr()) : ListView.separated( - separatorBuilder: (context, index) { - return 20.height; - }, - itemCount: serviceVM.document!.data!.length, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: const EdgeInsets.symmetric(horizontal: 20), - itemBuilder: (context, index) { - DocumentData? document = serviceVM.document?.data![index]; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (document!.documentName!).toText(fontSize: 16, letterSpacing: -0.56, fontWeight: MyFonts.SemiBold), - if (document.statusText != null && document.statusText!.isNotEmpty) ...[ - 10.width, - Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status ?? 1)), + separatorBuilder: (context, index) { + return 20.height; + }, + itemCount: serviceVM.document!.data!.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.symmetric(horizontal: 20), + itemBuilder: (context, index) { + DocumentData? document = serviceVM.document?.data![index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (document!.documentName!).toText(fontSize: 16, letterSpacing: -0.56, fontWeight: MyFonts.SemiBold), + if (document.statusText != null && document.statusText!.isNotEmpty) ...[ + 10.width, + Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status ?? 1)), + ], + ], + ), + if (document.status != 1 && document.status != 3) ...[ + Padding( + padding: const EdgeInsets.only(top: 4, bottom: 8), + child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor), + ), + // TxtField( + // hint: LocaleKeys.description.tr(), + // maxLines: 3, + // isBackgroundEnabled: true, + // value: document.description != null ? document.description : "", + // onChanged: (val) { + // document.description = val; + // }, + // ), + ], + 10.height, + if (isNeedToShow(model: serviceVM, document: document)) ...[ + PickedFilesContainer( + //|| document.status == 3 || document.status != 4 + isReview: document.status != 0 && document.status == 1 || document.status == 3, + allowAdButton: false, + pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document), + onCrossPressedPrimary: isNetworkImage(document: document) + ? serviceVM.removeNetworkImage + : document.documentId == 1 + ? serviceVM.commerceRemove + : document.documentId == 2 + ? serviceVM.commercialRemove + : serviceVM.vatRemove, + isPdf: true, + isFromNetwork: !(document.isLocalFile ?? false), + onAddFilePressed: () { + serviceVM.pickPdfReceiptFile(context, document.documentId!, index); + }, + ), + buildCommentContainer(document: document), + ] else ...[ + 10.height, + DottedRectContainer( + onTap: () => serviceVM.pickPdfReceiptFile(context, document.documentId!, index) ?? "", + text: LocaleKeys.attachPDF.tr(), + icon: MyAssets.attachmentIcon.buildSvg(), + ), + ], ], - ], - ), - if (document.status != 1 && document.status != 3) ...[ - Padding( - padding: const EdgeInsets.only(top: 4, bottom: 8), - child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor), - ), - TxtField( - hint: LocaleKeys.description.tr(), - maxLines: 3, - isBackgroundEnabled: true, - value: document.description != null ? document.description : "", - onChanged: (val) { - document.description = val; - }, - ), - ], - 10.height, - if (isNeedToShow(model: serviceVM, document: document)) ...[ - PickedFilesContainer( - isReview: document.status == 4, - allowAdButton: false, - pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document), - onCrossPressedPrimary: isNetworkImage(document: document) - ? serviceVM.removeNetworkImage - : document.documentId == 1 - ? serviceVM.commerceRemove - : document.documentId == 2 - ? serviceVM.commercialRemove - : serviceVM.vatRemove, - isPdf: serviceVM.document!.data![index].fileExt == "pdf", - isFromNetwork: !(document.isLocalFile ?? false), - onAddFilePressed: () { - serviceVM.pickPdfReceiptFile(context, document.documentId!, index); - }, - ), - buildCommentContainer(document: document), - ] else - ...[ - 10.height, - DottedRectContainer( - onTap: () => serviceVM.pickPdfReceiptFile(context, document.documentId!, index) ?? "", - text: LocaleKeys.attachImage.tr(), - icon: MyAssets.attachmentIcon.buildSvg(), - ), - ], - ], - ); - }, - ); + ); + }, + ); } List isLocalOrNetworkFiles({required ServiceVM model, required DocumentData document}) { From 900d32f5bb44f9fcdfb5304bd4a149ab731f82be Mon Sep 17 00:00:00 2001 From: Aamir Date: Tue, 12 Nov 2024 14:49:28 +0300 Subject: [PATCH 04/11] changes --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 2911386..36040d2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: injector: ^4.0.0 provider: ^6.0.0 easy_localization: ^3.0.3 - http: ^1.2.2 + http: ^0.13.6 permission_handler: ^11.3.1 flutter_svg: ^2.0.9 sizer: any From d4ebcf998f22bf9f7f343252358ca6b9470d6201 Mon Sep 17 00:00:00 2001 From: Aamir Date: Wed, 13 Nov 2024 11:11:02 +0300 Subject: [PATCH 05/11] changes --- lib/config/dependency_injection.dart | 1 - lib/view_models/user_view_model.dart | 13 ++++++++----- lib/views/profile/profile_view.dart | 4 ++-- pubspec.yaml | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/config/dependency_injection.dart b/lib/config/dependency_injection.dart index b7f4909..970a88a 100644 --- a/lib/config/dependency_injection.dart +++ b/lib/config/dependency_injection.dart @@ -48,7 +48,6 @@ class AppDependencies { injector.registerSingleton(() => BranchRepoImp()); injector.registerSingleton(() => ShippingRepoImp()); injector.registerSingleton(() => SettingOptionsRepoImp()); - injector.registerSingleton(() => LocationService()); // } diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 51cf91b..3e5e691 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -24,6 +24,7 @@ import 'package:mc_common_app/models/user_models/confirm_password.dart'; import 'package:mc_common_app/models/user_models/country.dart'; import 'package:mc_common_app/models/user_models/forget_password_otp_compare.dart'; import 'package:mc_common_app/models/user_models/forget_password_otp_request.dart'; +import 'package:mc_common_app/models/user_models/image_response.dart'; import 'package:mc_common_app/models/user_models/login_password.dart'; import 'package:mc_common_app/models/user_models/register_user.dart'; import 'package:mc_common_app/models/user_models/user.dart'; @@ -435,7 +436,6 @@ class UserVM extends BaseVM { } } else { Utils.showToast("Please verify your credentials and role type."); - } } else { Utils.showToast(verifiedUser.message ?? ""); @@ -560,7 +560,8 @@ class UserVM extends BaseVM { return await userRepo.getAllCountries(); } - Future performBasicOtpRegisterPage(BuildContext context, {required String countryCode, required String phoneNum, required int role, bool isNeedToPassToken = false, VoidCallback? reloadPage}) async { + Future performBasicOtpRegisterPage(BuildContext context, + {required String countryCode, required String phoneNum, required int role, bool isNeedToPassToken = false, VoidCallback? reloadPage}) async { Utils.showLoading(context); BasicOtpRespModel basicOtp = await userRepo.basicOtp(countryCode + phoneNum, roleId: role, isNeedToPassToken: isNeedToPassToken); Utils.hideLoading(context); @@ -626,13 +627,15 @@ class UserVM extends BaseVM { Future updateUserImage(BuildContext context) async { File? myPick = await commanServices.pickFile(context, fileType: FileType.image); if (myPick != null) { - userRepo.updateUserImage(encodeBase64Image(myPick)).whenComplete(() { - AppState().getUser.data!.userInfo!.userLocalImage = myPick; - }); + await userRepo.updateUserImage(encodeBase64Image(myPick)); + AppState().getUser.data!.userInfo!.userLocalImage = myPick; + notifyListeners(); } notifyListeners(); } + + String encodeBase64Image(File file) { List imageBytes = file.readAsBytesSync(); print(imageBytes); diff --git a/lib/views/profile/profile_view.dart b/lib/views/profile/profile_view.dart index dfb243b..9f3178b 100644 --- a/lib/views/profile/profile_view.dart +++ b/lib/views/profile/profile_view.dart @@ -196,8 +196,8 @@ class _ProfileScreenState extends State { decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), child: MyAssets.icEdit.buildSvg(), ).onPress( - () async { - await model.updateUserImage(context).whenComplete(() => setState(() {})); + () async { + await model.updateUserImage(context); }, ), ), diff --git a/pubspec.yaml b/pubspec.yaml index 36040d2..affefda 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: http: ^0.13.6 permission_handler: ^11.3.1 flutter_svg: ^2.0.9 - sizer: any + sizer: ^3.0.4 fluttertoast: ^8.0.8 shared_preferences: ^2.0.6 file_picker: ^8.1.2 From 7ab3caa364492c629cd1b726cd31a1ef9fd469c8 Mon Sep 17 00:00:00 2001 From: Aamir Date: Wed, 13 Nov 2024 16:11:04 +0300 Subject: [PATCH 06/11] CMA 246, 247 --- lib/repositories/user_repo.dart | 9 +++++++ lib/view_models/user_view_model.dart | 15 ++++++++++-- lib/views/profile/profile_view.dart | 35 ++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/lib/repositories/user_repo.dart b/lib/repositories/user_repo.dart index 5f5bd31..79fe915 100644 --- a/lib/repositories/user_repo.dart +++ b/lib/repositories/user_repo.dart @@ -55,6 +55,8 @@ abstract class UserRepo { Future changePassword(String currentPassword, String newPassword); + //Future updateUserInfo(String firstName, String lastName); + Future changeMobileNoOTPRequest(countryID, String mobileNo, String password); Future changeMobileNo(String userToken, String userOTP); @@ -254,6 +256,13 @@ class UserRepoImp implements UserRepo { return await injector.get().postJsonForObject((json) => ConfirmEmailRespModel.fromJson(json), ApiConsts.ChangeEmail, postParams, token: t); } + // @override + // Future updateUserInfo(String firstName, String lastName) async { + // var postParams = {"userID": "${AppState().getUser.data!.userInfo!.id}", "firstName": "${firstName}", "lastName": "${lastName}", "genderID": 0, "cityID": 0}; + // String t = AppState().getUser.data!.accessToken ?? ""; + // return await injector.get().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.update, postParams, token: t); + // } + @override Future emailVerify(String email, String userID) async { var postParams = { diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 3e5e691..2ac2825 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -164,6 +164,19 @@ class UserVM extends BaseVM { } } + // Future userDetailsUpdate(BuildContext context, String firstName, String lastName) async { + // Utils.showLoading(context); + // GenericRespModel res = await userRepo.changePassword(currentPassword, newPassword); + // Utils.hideLoading(context); + // if (res.messageStatus == 1) { + // Utils.showToast(LocaleKeys.passwordIsUpdated.tr()); + // + // Navigator.of(context).pushNamedAndRemoveUntil(AppRoutes.profileView, (Route route) => true); + // } else { + // Utils.showToast(res.message ?? ""); + // } + // } + Future performCompleteProfile( BuildContext context, { required String password, @@ -634,8 +647,6 @@ class UserVM extends BaseVM { notifyListeners(); } - - String encodeBase64Image(File file) { List imageBytes = file.readAsBytesSync(); print(imageBytes); diff --git a/lib/views/profile/profile_view.dart b/lib/views/profile/profile_view.dart index 9f3178b..2db0dee 100644 --- a/lib/views/profile/profile_view.dart +++ b/lib/views/profile/profile_view.dart @@ -54,8 +54,12 @@ class _ProfileScreenState extends State { if (mySubscription!.id == 1) { freeTrialName = mySubscription!.name ?? ""; } else { - startDate = (mySubscription!.dateStart != null && mySubscription!.dateStart!.isNotEmpty) ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateStart!))) : ""; - endDate = (mySubscription!.dateEnd != null && mySubscription!.dateEnd!.isNotEmpty) ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateEnd!))) : ""; + startDate = (mySubscription!.dateStart != null && mySubscription!.dateStart!.isNotEmpty) + ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateStart!))) + : ""; + endDate = (mySubscription!.dateEnd != null && mySubscription!.dateEnd!.isNotEmpty) + ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateEnd!))) + : ""; } } return Stack( @@ -101,13 +105,34 @@ class _ProfileScreenState extends State { child: ListView( children: [ 60.height, - "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25), + Container( + height: 40, + width: 40, + padding: const EdgeInsets.all(8), + decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), + child: MyAssets.icEdit.buildSvg(), + ).onPress( + () async { + await model.updateUserImage(context); + }, + ), + ], + ).margin(left: 0, top: 0, right: 24, bottom: 0).onPress(() { + print("Change User Name Here"); + }), Column( children: [ if (AppState().currentAppType == AppType.provider && mySubscription != null) ...[ CustomProfileOptionsTile( titleText: LocaleKeys.mySubscription.tr(), - subtitleText: freeTrialName.isNotEmpty ? freeTrialName : "${startDate.isNotEmpty ? "${LocaleKeys.startDate.tr()}: $startDate" : ""} ${endDate.isNotEmpty ? "${LocaleKeys.expiresOn.tr()}: $endDate" : ""}", + subtitleText: freeTrialName.isNotEmpty + ? freeTrialName + : "${startDate.isNotEmpty ? "${LocaleKeys.startDate.tr()}: $startDate" : ""} ${endDate.isNotEmpty ? "${LocaleKeys.expiresOn.tr()}: $endDate" : ""}", needBorderBelow: true, needEditButton: false, onTap: () {}, @@ -196,7 +221,7 @@ class _ProfileScreenState extends State { decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), child: MyAssets.icEdit.buildSvg(), ).onPress( - () async { + () async { await model.updateUserImage(context); }, ), From cef48cb1cba57c95be75ba02c9f21fb3a66791fc Mon Sep 17 00:00:00 2001 From: Aamir Date: Sun, 1 Dec 2024 14:52:41 +0300 Subject: [PATCH 07/11] CMA 246, 247 --- assets/langs/ar-SA.json | 6 +- assets/langs/en-US.json | 6 +- lib/classes/consts.dart | 1 + lib/config/routes.dart | 3 + lib/generated/codegen_loader.g.dart | 12 ++- lib/generated/locale_keys.g.dart | 4 + lib/repositories/user_repo.dart | 14 +-- lib/view_models/user_view_model.dart | 70 ++++++------ lib/views/profile/profile_view.dart | 138 +++++++++++++----------- lib/views/user/update_user_details.dart | 68 ++++++++++++ 10 files changed, 217 insertions(+), 105 deletions(-) create mode 100644 lib/views/user/update_user_details.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 5a53e2e..0237366 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -706,5 +706,9 @@ "customerLocation": "موقع العميل", "deliveryAvailable": "التوصيل متاح", "viewed": "تم المشاهدة", - "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا." + "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.", + "updateUserDetails": "تحديث تفاصيل المستخدم", + "enterNewFirstName": "أدخل الاسم الأول", + "enterNewLastName": "أدخل الاسم الأخير", + "userDetailsUpdated": "يتم تحديث تفاصيل المستخدم" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 3bf1e99..086972a 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -703,6 +703,10 @@ "customerLocation": "Customer Location", "deliveryAvailable": "Delivery Available", "viewed": "Viewed", - "itemNoLongerAvailable": "This item is no longer available." + "itemNoLongerAvailable": "This item is no longer available.", + "updateUserDetails": "Update User Details", + "enterNewFirstName": "Enter First Name", + "enterNewLastName": "Enter Last Name", + "userDetailsUpdated": "User Details is Updated" } \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index da876fe..8f9d27b 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -37,6 +37,7 @@ class ApiConsts { static String LogoutUser = "${baseUrlServices}api/Account/Logout"; static String UpdateUserImage = "${baseUrlServices}api/User_UpdateProfileImage"; static String GetUserImage = "${baseUrlServices}api/ProfileImage"; + static String userUpdate = "${baseUrlServices}api/User_Update"; //Profile static String fetProviderDocument = "${baseUrlServices}api/ServiceProviders/ServiceProviderDocument_Get"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 869d16b..e77d260 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -43,6 +43,7 @@ import 'package:mc_common_app/views/user/register_page.dart'; import 'package:mc_common_app/views/user/register_provider_page.dart'; import 'package:mc_common_app/views/user/register_selection_page.dart'; import 'package:mc_common_app/views/splash/splash_page.dart'; +import 'package:mc_common_app/views/user/update_user_details.dart'; import 'package:mc_common_app/views/user/vertify_password_page.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/widgets/image_viewer/image_viewer_screen.dart'; @@ -166,6 +167,7 @@ class AppRoutes { //Chat static const String chatView = "/chatView"; + static const String updateUserDetails = "/updateUserDetails"; static const String initialRoute = splash; static final Map routes = { @@ -185,6 +187,7 @@ class AppRoutes { forgetPasswordMethodPage: (context) => ForgetPasswordMethodPage(ModalRoute.of(context)!.settings.arguments as String), changeMobilePage: (context) => ChangeMobilePage(), changeEmailPage: (context) => const ChangeEmailPage(), + updateUserDetails: (context) => const UpdateUserDetails(), changePassword: (context) => const ChangePasswordPage(), editAccountPage: (context) => const EditAccountPage(), profileView: (context) => const ProfileScreen(), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index cd3bee7..c4a4e19 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -722,7 +722,11 @@ class CodegenLoader extends AssetLoader{ "customerLocation": "موقع العميل", "deliveryAvailable": "التوصيل متاح", "viewed": "تم المشاهدة", - "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا." + "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.", + "updateUserDetails": "تحديث تفاصيل المستخدم", + "enterNewFirstName": "أدخل الاسم الأول", + "enterNewLastName": "أدخل الاسم الأخير", + "userDetailsUpdated": "يتم تحديث تفاصيل المستخدم" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1429,7 +1433,11 @@ static const Map en_US = { "customerLocation": "Customer Location", "deliveryAvailable": "Delivery Available", "viewed": "Viewed", - "itemNoLongerAvailable": "This item is no longer available." + "itemNoLongerAvailable": "This item is no longer available.", + "updateUserDetails": "Update User Details", + "enterNewFirstName": "Enter First Name", + "enterNewLastName": "Enter Last Name", + "userDetailsUpdated": "User Details is Updated" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index c74ae1a..6e23a69 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -686,5 +686,9 @@ abstract class LocaleKeys { static const deliveryAvailable = 'deliveryAvailable'; static const viewed = 'viewed'; static const itemNoLongerAvailable = 'itemNoLongerAvailable'; + static const updateUserDetails = 'updateUserDetails'; + static const enterNewFirstName = 'enterNewFirstName'; + static const enterNewLastName = 'enterNewLastName'; + static const userDetailsUpdated = 'userDetailsUpdated'; } diff --git a/lib/repositories/user_repo.dart b/lib/repositories/user_repo.dart index 79fe915..8417636 100644 --- a/lib/repositories/user_repo.dart +++ b/lib/repositories/user_repo.dart @@ -55,7 +55,7 @@ abstract class UserRepo { Future changePassword(String currentPassword, String newPassword); - //Future updateUserInfo(String firstName, String lastName); + Future> updateUserInfo(String firstName, String lastName); Future changeMobileNoOTPRequest(countryID, String mobileNo, String password); @@ -256,12 +256,12 @@ class UserRepoImp implements UserRepo { return await injector.get().postJsonForObject((json) => ConfirmEmailRespModel.fromJson(json), ApiConsts.ChangeEmail, postParams, token: t); } - // @override - // Future updateUserInfo(String firstName, String lastName) async { - // var postParams = {"userID": "${AppState().getUser.data!.userInfo!.id}", "firstName": "${firstName}", "lastName": "${lastName}", "genderID": 0, "cityID": 0}; - // String t = AppState().getUser.data!.accessToken ?? ""; - // return await injector.get().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.update, postParams, token: t); - // } + @override + Future> updateUserInfo(String firstName, String lastName) async { + var postParams = {"userID": "${AppState().getUser.data!.userInfo!.userId}", "firstName": "${firstName}", "lastName": "${lastName}", "genderID": 1, "cityID": 1}; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => json, ApiConsts.userUpdate, postParams, token: t); + } @override Future emailVerify(String email, String userID) async { diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 2ac2825..4117789 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -164,21 +164,26 @@ class UserVM extends BaseVM { } } - // Future userDetailsUpdate(BuildContext context, String firstName, String lastName) async { - // Utils.showLoading(context); - // GenericRespModel res = await userRepo.changePassword(currentPassword, newPassword); - // Utils.hideLoading(context); - // if (res.messageStatus == 1) { - // Utils.showToast(LocaleKeys.passwordIsUpdated.tr()); - // - // Navigator.of(context).pushNamedAndRemoveUntil(AppRoutes.profileView, (Route route) => true); - // } else { - // Utils.showToast(res.message ?? ""); - // } - // } - - Future performCompleteProfile( - BuildContext context, { + Future userDetailsUpdate(BuildContext context, String firstName, String lastName) async { + Utils.showLoading(context); + Map res = await userRepo.updateUserInfo(firstName, lastName); + Utils.hideLoading(context); + if (res["data"] != null && res["data"].isNotEmpty) { + User localUser = AppState().getUser; + if (localUser.data != null) { + localUser.data!.userInfo!.firstName = res["data"]["firstName"]; + localUser.data!.userInfo!.lastName = res["data"]["lastName"]; + AppState().setUser = localUser; + } + Utils.showToast(LocaleKeys.userDetailsUpdated.tr()); + pop(context); + } else { + Utils.showToast(res.toString() ?? ""); + } + notifyListeners(); + } + + Future performCompleteProfile(BuildContext context, { required String password, required String confirmPassword, required String firstName, @@ -190,14 +195,7 @@ class UserVM extends BaseVM { if (Utils.passwordValidateStructure(password)) { if (password == confirmPassword) { Utils.showLoading(context); - RegisterUserRespModel user = await userRepo.basicComplete( - userId ?? "", - firstName, - lastName, - email, - password, - isNeedToPassToken: isNeedToPassToken, - ); + RegisterUserRespModel user = await userRepo.basicComplete(userId ?? "", firstName, lastName, email, password, isNeedToPassToken: isNeedToPassToken); Utils.hideLoading(context); if (user.messageStatus == 1) { Utils.showToast(LocaleKeys.successfullyRegistered.tr()); @@ -551,8 +549,8 @@ class UserVM extends BaseVM { type == ClassType.NUMBER && countryCode != null ? countryCode + phoneNum : type == ClassType.NUMBER && countryCode == null - ? phoneNum - : phoneNum, + ? phoneNum + : phoneNum, password); Utils.hideLoading(context); LoginPasswordRespModel user = LoginPasswordRespModel.fromJson(jsonDecode(response.body)); @@ -560,8 +558,8 @@ class UserVM extends BaseVM { SharedPrefManager.setPhoneOrEmail(type == ClassType.NUMBER && countryCode != null ? countryCode + phoneNum : type == ClassType.NUMBER && countryCode == null - ? phoneNum - : phoneNum); + ? phoneNum + : phoneNum); SharedPrefManager.setUserPassword(password); navigateReplaceWithName(context, AppRoutes.loginMethodSelection, arguments: user.data!.userToken); } else { @@ -675,8 +673,13 @@ class UserVM extends BaseVM { } void changeLanguage(BuildContext context) { - print("${EasyLocalization.of(context)?.currentLocale}"); - if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") { + print("${EasyLocalization + .of(context) + ?.currentLocale}"); + if (EasyLocalization + .of(context) + ?.currentLocale + ?.countryCode == "SA") { context.setLocale(const Locale("en", "US")); } else { context.setLocale(const Locale('ar', 'SA')); @@ -699,8 +702,13 @@ class UserVM extends BaseVM { AppState().setUser = null; if (AppState().currentAppType == AppType.provider) { AppState().setproviderSubscription = null; - context.read().mySubscriptionsBySp.clear(); - context.read().allSubscriptions = SubscriptionModel(); + context + .read() + .mySubscriptionsBySp + .clear(); + context + .read() + .allSubscriptions = SubscriptionModel(); } navigateReplaceWithNameUntilRoute(context, AppRoutes.registerSelection); diff --git a/lib/views/profile/profile_view.dart b/lib/views/profile/profile_view.dart index 2db0dee..3684fa5 100644 --- a/lib/views/profile/profile_view.dart +++ b/lib/views/profile/profile_view.dart @@ -72,21 +72,21 @@ class _ProfileScreenState extends State { decoration: BoxDecoration( image: AppState().getUser.data!.userInfo!.userLocalImage != null ? DecorationImage( - image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!), - fit: BoxFit.cover, - ) + image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!), + fit: BoxFit.cover, + ) : AppState().getUser.data!.userInfo!.userImageUrl != null - ? DecorationImage( - image: CachedNetworkImageProvider( - AppState().getUser.data!.userInfo!.userImageUrl, - ), - fit: BoxFit.cover, - ) - : DecorationImage( - image: AssetImage( - MyAssets.icLogoWhitePng, - ), - ), + ? DecorationImage( + image: CachedNetworkImageProvider( + AppState().getUser.data!.userInfo!.userImageUrl, + ), + fit: BoxFit.cover, + ) + : DecorationImage( + image: AssetImage( + MyAssets.icLogoWhitePng, + ), + ), ), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 7.0, sigmaY: 7.0), @@ -107,24 +107,16 @@ class _ProfileScreenState extends State { 60.height, Row( crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ - "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25), - Container( - height: 40, - width: 40, - padding: const EdgeInsets.all(8), - decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), - child: MyAssets.icEdit.buildSvg(), - ).onPress( - () async { - await model.updateUserImage(context); + "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25, right: 10), + MyAssets.icEdit.buildSvg(width: 15).onPress( + () async { + Navigator.pushNamed(context, AppRoutes.updateUserDetails); }, ), ], - ).margin(left: 0, top: 0, right: 24, bottom: 0).onPress(() { - print("Change User Name Here"); - }), + ).margin(left: 0, top: 0, right: 24, bottom: 0), Column( children: [ if (AppState().currentAppType == AppType.provider && mySubscription != null) ...[ @@ -169,7 +161,11 @@ class _ProfileScreenState extends State { }, ), ], - ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), borderRadius: 0), + ).toContainer(width: double.infinity, + isShadowEnabled: true, + paddingAll: 10, + margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), + borderRadius: 0), ], ), ), @@ -177,67 +173,83 @@ class _ProfileScreenState extends State { ], ), Positioned( - top: MediaQuery.of(context).size.height * 0.24, + top: MediaQuery + .of(context) + .size + .height * 0.24, child: Container( height: 100, alignment: Alignment.centerLeft, child: ClipOval( child: AppState().getUser.data!.userInfo!.userLocalImage != null ? Image.file( - AppState().getUser.data!.userInfo!.userLocalImage!, - width: 100, - height: 100, - fit: BoxFit.fill, - ) + AppState().getUser.data!.userInfo!.userLocalImage!, + width: 100, + height: 100, + fit: BoxFit.fill, + ) : CachedNetworkImage( - imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}", - imageBuilder: (context, imageProvider) => Container( - decoration: BoxDecoration( - image: DecorationImage( - image: imageProvider, - fit: BoxFit.cover, - ), + imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}", + imageBuilder: (context, imageProvider) => + Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, ), ), - placeholder: (context, url) => const Center(child: CircularProgressIndicator()), - errorWidget: (context, url, error) => const Icon(Icons.error), - width: 100, - height: 100, - fit: BoxFit.fill, - fadeInCurve: Curves.easeIn, - fadeInDuration: const Duration(milliseconds: 1000), - useOldImageOnUrlChange: false, ), + placeholder: (context, url) => const Center(child: CircularProgressIndicator()), + errorWidget: (context, url, error) => const Icon(Icons.error), + width: 100, + height: 100, + fit: BoxFit.fill, + fadeInCurve: Curves.easeIn, + fadeInDuration: const Duration(milliseconds: 1000), + useOldImageOnUrlChange: false, + ), ), ).horPaddingMain(), ), Positioned( - top: MediaQuery.of(context).size.height * 0.30, - right: MediaQuery.of(context).size.height * 0.03, + top: MediaQuery + .of(context) + .size + .height * 0.30, + right: MediaQuery + .of(context) + .size + .height * 0.03, child: Container( height: 40, width: 40, padding: const EdgeInsets.all(8), decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), - child: MyAssets.icEdit.buildSvg(), + child: Center(child: MyAssets.icEdit.buildSvg(),), ).onPress( - () async { + () async { await model.updateUserImage(context); }, ), ), Positioned( - top: MediaQuery.of(context).size.height * 0.05, - left: MediaQuery.of(context).size.height * 0.03, + top: MediaQuery + .of(context) + .size + .height * 0.05, + left: MediaQuery + .of(context) + .size + .height * 0.03, child: const Icon(Icons.arrow_back_ios, color: Colors.black, size: 18) .toContainer( - padding: const EdgeInsets.only(left: 5), - borderRadius: 100, - borderColor: MyColors.lightGreyEFColor, - isEnabledBorder: true, - height: 40, - width: 40, - ) + padding: const EdgeInsets.only(left: 5), + borderRadius: 100, + borderColor: MyColors.lightGreyEFColor, + isEnabledBorder: true, + height: 40, + width: 40, + ) .onPress(() => pop(context))), ], ); diff --git a/lib/views/user/update_user_details.dart b/lib/views/user/update_user_details.dart new file mode 100644 index 0000000..0d6c361 --- /dev/null +++ b/lib/views/user/update_user_details.dart @@ -0,0 +1,68 @@ +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/view_models/user_view_model.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class UpdateUserDetails extends StatefulWidget { + const UpdateUserDetails({Key? key}) : super(key: key); + + @override + State createState() => _UpdateUserDetailsState(); +} + +class _UpdateUserDetailsState extends State { + String firstname = ""; + String lastname = ""; + + late UserVM userVM; + + @override + void initState() { + userVM = Provider.of(context, listen: false); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: LocaleKeys.updateUserDetails.tr(), + ), + body: SingleChildScrollView( + child: Container( + // width: double.infinity, + // height: double.infinity, + padding: const EdgeInsets.all(20), + child: Column( + children: [ + TxtField( + hint: LocaleKeys.enterNewFirstName.tr(), + onChanged: (v) => firstname = v, + ), + 12.height, + TxtField( + hint: LocaleKeys.enterNewLastName.tr(), + onChanged: (v) => lastname = v, + ), + 40.height, + ShowFillButton( + title: LocaleKeys.confirm.tr(), + maxWidth: double.infinity, + onPressed: () async { + await userVM.userDetailsUpdate(context, firstname, lastname); + + }, + ), + ], + ), + ), + ), + ); + } +} From 671b9d9e6f78f0a48f0cb741794e7f371bc0183b Mon Sep 17 00:00:00 2001 From: Aamir Date: Sun, 1 Dec 2024 16:52:56 +0300 Subject: [PATCH 08/11] CMA 244 --- assets/langs/ar-SA.json | 2 +- assets/langs/en-US.json | 3 +- lib/classes/consts.dart | 1 + lib/config/routes.dart | 3 + lib/generated/codegen_loader.g.dart | 16 +-- lib/models/user_models/user.dart | 69 +++++---- lib/repositories/user_repo.dart | 11 +- lib/view_models/subscriptions_view_model.dart | 3 + lib/view_models/user_view_model.dart | 20 ++- lib/views/profile/profile_view.dart | 132 ++++++++---------- lib/views/user/change_email_page.dart | 12 +- lib/views/user/change_mobile_page.dart | 12 +- lib/views/user/change_password_page.dart | 12 +- lib/views/user/update_user_city_country.dart | 105 ++++++++++++++ lib/views/user/update_user_details.dart | 2 +- pubspec.yaml | 10 +- 16 files changed, 271 insertions(+), 142 deletions(-) create mode 100644 lib/views/user/update_user_city_country.dart diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 24c5b32..01b8045 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -708,7 +708,7 @@ "updateUserDetails": "تحديث تفاصيل المستخدم", "enterNewFirstName": "أدخل الاسم الأول", "enterNewLastName": "أدخل الاسم الأخير", - "userDetailsUpdated": "يتم تحديث تفاصيل المستخدم" + "userDetailsUpdated": "يتم تحديث تفاصيل المستخدم", "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.", "reactivateAd": "إعادة تنشيط الإعلان", "dealOutsideApp": "تمت الصفقة خارج التطبيق مع عميل آخر.", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 3eb6430..65c26db 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -738,8 +738,7 @@ "blockedByAdmin": "Blocked by admin", "active": "Active", "paymentType": "Payment Type", - "searchByCreatedDate": "Search By Created Date" - "itemNoLongerAvailable": "This item is no longer available.", + "searchByCreatedDate": "Search By Created Date", "updateUserDetails": "Update User Details", "enterNewFirstName": "Enter First Name", "enterNewLastName": "Enter Last Name", diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 2ae3e1d..a7a73f3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -39,6 +39,7 @@ class ApiConsts { static String logoutUser = "${baseUrlServices}api/Account/Logout"; static String updateUserImage = "${baseUrlServices}api/User_UpdateProfileImage"; static String getUserImage = "${baseUrlServices}api/ProfileImage"; + static String userUpdate = "${baseUrlServices}api/User_Update"; static String providerComplaintCreate = "${baseUrlServices}api/ServiceProviders/ProviderComplaint_Create"; //Profile diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 4af01bf..d23a216 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -44,6 +44,7 @@ import 'package:mc_common_app/views/user/register_page.dart'; import 'package:mc_common_app/views/user/register_provider_page.dart'; import 'package:mc_common_app/views/user/register_selection_page.dart'; import 'package:mc_common_app/views/splash/splash_page.dart'; +import 'package:mc_common_app/views/user/update_user_city_country.dart'; import 'package:mc_common_app/views/user/update_user_details.dart'; import 'package:mc_common_app/views/user/vertify_password_page.dart'; import 'package:flutter/material.dart'; @@ -170,6 +171,7 @@ class AppRoutes { //Chat static const String chatView = "/chatView"; static const String updateUserDetails = "/updateUserDetails"; + static const String updateUserCity = "/updateUserCity"; static const String initialRoute = splash; static final Map routes = { @@ -190,6 +192,7 @@ class AppRoutes { changeMobilePage: (context) => ChangeMobilePage(), changeEmailPage: (context) => const ChangeEmailPage(), updateUserDetails: (context) => const UpdateUserDetails(), + updateUserCity: (context) => const UpdateUserCityCountry(), changePassword: (context) => const ChangePasswordPage(), editAccountPage: (context) => const EditAccountPage(), profileView: (context) => const ProfileScreen(), diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 5a4d936..94e96d1 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -721,11 +721,11 @@ class CodegenLoader extends AssetLoader{ "customerLocation": "موقع العميل", "deliveryAvailable": "التوصيل متاح", "viewed": "تم المشاهدة", - "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.", "updateUserDetails": "تحديث تفاصيل المستخدم", "enterNewFirstName": "أدخل الاسم الأول", "enterNewLastName": "أدخل الاسم الأخير", "userDetailsUpdated": "يتم تحديث تفاصيل المستخدم", + "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.", "reactivateAd": "إعادة تنشيط الإعلان", "dealOutsideApp": "تمت الصفقة خارج التطبيق مع عميل آخر.", "noAgreementCustomer": "لا يوجد اتفاق من جانب العميل.", @@ -1390,7 +1390,7 @@ static const Map en_US = { "priceRange": "Price Range", "cancelOffer": "Cancel Offer", "pleaseSpecify": "Please Specify", - "customerNotResponding": "Customer Not Responding", + "customerNotResponding": "The customer is not responding.", "cancelRequestPrompt": "Do you want to cancel this request?", "requestPermanentlyCancelled": "Your request will be permanently cancelled. You cannot undo this action.", "awaitingResponseFromCustomer": "Awaiting Response From Customer", @@ -1410,7 +1410,7 @@ static const Map en_US = { "customerCarePrompt": "Got any question? We are here to service. Click here to talk to our customer care right now.", "callNow": "Call Now", "condition": "Condition", - "servicesNotAvailableHomeLocation": "Some services are not available on home location.", + "servicesNotAvailableHomeLocation": "This location will be same for all services", "additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary.", "selectServiceLocation": "Select Service Location", "apptOn": "Appt On", @@ -1467,10 +1467,6 @@ static const Map en_US = { "deliveryAvailable": "Delivery Available", "viewed": "Viewed", "itemNoLongerAvailable": "This item is no longer available.", - "updateUserDetails": "Update User Details", - "enterNewFirstName": "Enter First Name", - "enterNewLastName": "Enter Last Name", - "userDetailsUpdated": "User Details is Updated" "reactivateAd": "Reactivate Ad", "dealOutsideApp": "The deal was done outside the app with another customer.", "noAgreementCustomer": "There is no agreement from the customer side.", @@ -1506,7 +1502,11 @@ static const Map en_US = { "blockedByAdmin": "Blocked by admin", "active": "Active", "paymentType": "Payment Type", - "searchByCreatedDate": "Search By Created Date" + "searchByCreatedDate": "Search By Created Date", + "updateUserDetails": "Update User Details", + "enterNewFirstName": "Enter First Name", + "enterNewLastName": "Enter Last Name", + "userDetailsUpdated": "User Details is Updated" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/models/user_models/user.dart b/lib/models/user_models/user.dart index c8c055b..659edaf 100644 --- a/lib/models/user_models/user.dart +++ b/lib/models/user_models/user.dart @@ -25,14 +25,16 @@ class User { int? messageStatus; String? message; - factory User.fromJson(Map json) => User( + factory User.fromJson(Map json) => + User( totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : UserData.fromJson(json["data"]), messageStatus: json["messageStatus"], message: json["message"], ); - Map toJson() => { + Map toJson() => + { "totalItemsCount": totalItemsCount, "data": data?.toJson(), "messageStatus": messageStatus, @@ -53,14 +55,16 @@ class UserData { DateTime? expiryDate; UserInfo? userInfo; - factory UserData.fromJson(Map json) => UserData( + factory UserData.fromJson(Map json) => + UserData( accessToken: json["accessToken"], refreshToken: json["refreshToken"], expiryDate: json["expiryDate"] == null ? null : DateTime.parse(json["expiryDate"]), userInfo: json["userInfo"] == null ? null : UserInfo.fromJson(json["userInfo"]), ); - Map toJson() => { + Map toJson() => + { "accessToken": accessToken, "refreshToken": refreshToken, "expiryDate": expiryDate?.toIso8601String(), @@ -69,34 +73,38 @@ class UserData { } class UserInfo { - UserInfo( - {this.id, - this.userId, - this.firstName, - this.lastName, - this.mobileNo, - this.email, - this.userImageUrl, - this.roleId, - this.roleName, - this.isEmailVerified, - this.serviceProviderBranch, - this.isVerified, - this.userRoles, - this.isCustomer, - this.isProviderDealership, - this.isDealershipUser, - this.providerId, - this.customerId, - this.countryId, - this.cityId, - this.dealershipId, - this.userLocalImage}); + UserInfo({this.id, + this.userId, + this.firstName, + this.lastName, + this.mobileNo, + this.email, + this.userImageUrl, + this.roleId, + this.roleName, + this.isEmailVerified, + this.serviceProviderBranch, + this.isVerified, + this.userRoles, + this.isCustomer, + this.isProviderDealership, + this.isDealershipUser, + this.providerId, + this.customerId, + this.countryId, + this.cityId, + this.dealershipId, + this.userLocalImage, + this.cityName, + this.countryName, + }); int? id; String? userId; String? firstName; String? lastName; + String? countryName; + String? cityName; String? mobileNo; String? email; dynamic userImageUrl; @@ -130,6 +138,8 @@ class UserInfo { userId = json["userID"]; firstName = json["firstName"]; lastName = json["lastName"]; + cityName = json["cityName"]; + countryName = json["countryName"]; mobileNo = json["mobileNo"]; email = json["email"]; userImageUrl = json["userImageUrl"]; @@ -172,11 +182,14 @@ class UserInfo { // dealershipId: json["dealershipID"], // ); - Map toJson() => { + Map toJson() => + { "id": id, "userID": userId, "firstName": firstName, "lastName": lastName, + "countryName": countryName, + "cityName": cityName, "mobileNo": mobileNo, "email": email, "userImageUrl": userImageUrl, diff --git a/lib/repositories/user_repo.dart b/lib/repositories/user_repo.dart index 571549c..9ce6d57 100644 --- a/lib/repositories/user_repo.dart +++ b/lib/repositories/user_repo.dart @@ -55,7 +55,7 @@ abstract class UserRepo { Future changePassword(String currentPassword, String newPassword); - Future> updateUserInfo(String firstName, String lastName); + Future> updateUserInfo(String firstName, String lastName, String? city); Future changeMobileNoOTPRequest(countryID, String mobileNo, String password); @@ -166,6 +166,11 @@ class UserRepoImp implements UserRepo { return await injector.get().getJsonForObject((json) => Country.fromJson(json), ApiConsts.getAllCountry); } + // @override + // Future getAllCountriesForUser() async { + // return await injector.get().getJsonForObject((json) => Country.fromJson(json), ApiConsts.getAllCountry); + // } + @override Future getAllCites(String countryId) async { var postParams = { @@ -257,8 +262,8 @@ class UserRepoImp implements UserRepo { } @override - Future> updateUserInfo(String firstName, String lastName) async { - var postParams = {"userID": "${AppState().getUser.data!.userInfo!.userId}", "firstName": "${firstName}", "lastName": "${lastName}", "genderID": 1, "cityID": 1}; + Future> updateUserInfo(String firstName, String lastName, String? city) async { + var postParams = {"userID": "${AppState().getUser.data!.userInfo!.userId}", "firstName": "${firstName}", "lastName": "${lastName}", "genderID": 1, "cityID": city ?? 1}; String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => json, ApiConsts.userUpdate, postParams, token: t); } diff --git a/lib/view_models/subscriptions_view_model.dart b/lib/view_models/subscriptions_view_model.dart index aa57cc1..21a87de 100644 --- a/lib/view_models/subscriptions_view_model.dart +++ b/lib/view_models/subscriptions_view_model.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:developer'; import 'package:mc_common_app/classes/app_state.dart'; @@ -189,7 +190,9 @@ class SubscriptionsVM extends BaseVM { mySubscriptionsBySp.clear(); setState(ViewState.busy); // allSubscriptions.data + print("====================== SUB ============="); for (var element in allSubscriptions.data!) { + print("SuBBB "+ element.subscriptionType.toString()); if (element.subscriptionTypeEnum == SubscriptionTypeEnum.current) { mySubscriptionsBySp.add(element); } diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 7c32ace..fd6cbee 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -18,6 +18,7 @@ import 'package:mc_common_app/models/subscriptions_models/subscription_model.dar import 'package:mc_common_app/models/user_models/basic_otp.dart'; import 'package:mc_common_app/models/user_models/change_email.dart'; import 'package:mc_common_app/models/user_models/change_mobile.dart'; +import 'package:mc_common_app/models/user_models/cities.dart'; import 'package:mc_common_app/models/user_models/confirm_email.dart'; import 'package:mc_common_app/models/user_models/confirm_mobile.dart'; import 'package:mc_common_app/models/user_models/confirm_password.dart'; @@ -63,6 +64,9 @@ class UserVM extends BaseVM { _loginOtherAccount = value; } + Country? userCountries; + Cities? userCities; + void updateCompleteProfilePageCheckbox(bool newValue) { completeProfilePageCheckbox = newValue; notifyListeners(); @@ -165,15 +169,17 @@ class UserVM extends BaseVM { } } - Future userDetailsUpdate(BuildContext context, String firstName, String lastName) async { + Future userDetailsUpdate(BuildContext context, String firstName, String lastName, String? city) async { Utils.showLoading(context); - Map res = await userRepo.updateUserInfo(firstName, lastName); + Map res = await userRepo.updateUserInfo(firstName, lastName, city); Utils.hideLoading(context); if (res["data"] != null && res["data"].isNotEmpty) { + print(res["data"]); User localUser = AppState().getUser; if (localUser.data != null) { localUser.data!.userInfo!.firstName = res["data"]["firstName"]; localUser.data!.userInfo!.lastName = res["data"]["lastName"]; + // localUser.data!.userInfo!.cityId = res["data"]["cityId"]; AppState().setUser = localUser; } Utils.showToast(LocaleKeys.userDetailsUpdated.tr()); @@ -572,6 +578,16 @@ class UserVM extends BaseVM { return await userRepo.getAllCountries(); } + Future getAllCountriesForUser() async { + userCountries = await userRepo.getAllCountries(); + notifyListeners(); + } + + Future getAllCitiesForUser(int countryId) async { + userCities = await userRepo.getAllCites(countryId.toString()); + notifyListeners(); + } + Future performBasicOtpRegisterPage(BuildContext context, {required String countryCode, required String phoneNum, required int role, bool isNeedToPassToken = false, VoidCallback? reloadPage}) async { Utils.showLoading(context); diff --git a/lib/views/profile/profile_view.dart b/lib/views/profile/profile_view.dart index 3684fa5..d555ad5 100644 --- a/lib/views/profile/profile_view.dart +++ b/lib/views/profile/profile_view.dart @@ -72,21 +72,21 @@ class _ProfileScreenState extends State { decoration: BoxDecoration( image: AppState().getUser.data!.userInfo!.userLocalImage != null ? DecorationImage( - image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!), - fit: BoxFit.cover, - ) + image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!), + fit: BoxFit.cover, + ) : AppState().getUser.data!.userInfo!.userImageUrl != null - ? DecorationImage( - image: CachedNetworkImageProvider( - AppState().getUser.data!.userInfo!.userImageUrl, - ), - fit: BoxFit.cover, - ) - : DecorationImage( - image: AssetImage( - MyAssets.icLogoWhitePng, - ), - ), + ? DecorationImage( + image: CachedNetworkImageProvider( + AppState().getUser.data!.userInfo!.userImageUrl, + ), + fit: BoxFit.cover, + ) + : DecorationImage( + image: AssetImage( + MyAssets.icLogoWhitePng, + ), + ), ), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 7.0, sigmaY: 7.0), @@ -111,7 +111,7 @@ class _ProfileScreenState extends State { children: [ "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25, right: 10), MyAssets.icEdit.buildSvg(width: 15).onPress( - () async { + () async { Navigator.pushNamed(context, AppRoutes.updateUserDetails); }, ), @@ -131,11 +131,13 @@ class _ProfileScreenState extends State { ), ], CustomProfileOptionsTile( - titleText: LocaleKeys.country.tr(), - subtitleText: "Saudi Arabia", + titleText: LocaleKeys.city.tr(), + subtitleText: "${AppState().getUser.data!.userInfo!.cityName ?? ""}, ${AppState().getUser.data!.userInfo!.countryName ?? ""}", needBorderBelow: true, - needEditButton: false, - onTap: () {}, + needEditButton: true, + onTap: () { + Navigator.pushNamed(context, AppRoutes.updateUserCity); + }, ), CustomProfileOptionsTile( titleText: LocaleKeys.email.tr(), @@ -161,11 +163,7 @@ class _ProfileScreenState extends State { }, ), ], - ).toContainer(width: double.infinity, - isShadowEnabled: true, - paddingAll: 10, - margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), - borderRadius: 0), + ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), borderRadius: 0), ], ), ), @@ -173,83 +171,69 @@ class _ProfileScreenState extends State { ], ), Positioned( - top: MediaQuery - .of(context) - .size - .height * 0.24, + top: MediaQuery.of(context).size.height * 0.24, child: Container( height: 100, alignment: Alignment.centerLeft, child: ClipOval( child: AppState().getUser.data!.userInfo!.userLocalImage != null ? Image.file( - AppState().getUser.data!.userInfo!.userLocalImage!, - width: 100, - height: 100, - fit: BoxFit.fill, - ) + AppState().getUser.data!.userInfo!.userLocalImage!, + width: 100, + height: 100, + fit: BoxFit.fill, + ) : CachedNetworkImage( - imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}", - imageBuilder: (context, imageProvider) => - Container( - decoration: BoxDecoration( - image: DecorationImage( - image: imageProvider, - fit: BoxFit.cover, + imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}", + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), ), ), + placeholder: (context, url) => const Center(child: CircularProgressIndicator()), + errorWidget: (context, url, error) => const Icon(Icons.error), + width: 100, + height: 100, + fit: BoxFit.fill, + fadeInCurve: Curves.easeIn, + fadeInDuration: const Duration(milliseconds: 1000), + useOldImageOnUrlChange: false, ), - placeholder: (context, url) => const Center(child: CircularProgressIndicator()), - errorWidget: (context, url, error) => const Icon(Icons.error), - width: 100, - height: 100, - fit: BoxFit.fill, - fadeInCurve: Curves.easeIn, - fadeInDuration: const Duration(milliseconds: 1000), - useOldImageOnUrlChange: false, - ), ), ).horPaddingMain(), ), Positioned( - top: MediaQuery - .of(context) - .size - .height * 0.30, - right: MediaQuery - .of(context) - .size - .height * 0.03, + top: MediaQuery.of(context).size.height * 0.30, + right: MediaQuery.of(context).size.height * 0.03, child: Container( height: 40, width: 40, padding: const EdgeInsets.all(8), decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), - child: Center(child: MyAssets.icEdit.buildSvg(),), + child: Center( + child: MyAssets.icEdit.buildSvg(), + ), ).onPress( - () async { + () async { await model.updateUserImage(context); }, ), ), Positioned( - top: MediaQuery - .of(context) - .size - .height * 0.05, - left: MediaQuery - .of(context) - .size - .height * 0.03, + top: MediaQuery.of(context).size.height * 0.05, + left: MediaQuery.of(context).size.height * 0.03, child: const Icon(Icons.arrow_back_ios, color: Colors.black, size: 18) .toContainer( - padding: const EdgeInsets.only(left: 5), - borderRadius: 100, - borderColor: MyColors.lightGreyEFColor, - isEnabledBorder: true, - height: 40, - width: 40, - ) + padding: const EdgeInsets.only(left: 5), + borderRadius: 100, + borderColor: MyColors.lightGreyEFColor, + isEnabledBorder: true, + height: 40, + width: 40, + ) .onPress(() => pop(context))), ], ); diff --git a/lib/views/user/change_email_page.dart b/lib/views/user/change_email_page.dart index 1e2685a..d75d23c 100644 --- a/lib/views/user/change_email_page.dart +++ b/lib/views/user/change_email_page.dart @@ -41,12 +41,12 @@ class _ChangeEmailPageState extends State { padding: const EdgeInsets.all(20), child: Column( children: [ - LocaleKeys.enterEmail.tr().toText( - height: 23 / 24, - fontSize: 24, - letterSpacing: -1.44, - ), - 12.height, + // LocaleKeys.enterEmail.tr().toText( + // height: 23 / 24, + // fontSize: 24, + // letterSpacing: -1.44, + // ), + // 12.height, TxtField( hint: LocaleKeys.enterNewEmail.tr(), onChanged: (v) => email = v, diff --git a/lib/views/user/change_mobile_page.dart b/lib/views/user/change_mobile_page.dart index f74cef0..10a5808 100644 --- a/lib/views/user/change_mobile_page.dart +++ b/lib/views/user/change_mobile_page.dart @@ -39,12 +39,12 @@ class _ChangeMobilePageState extends State { padding: const EdgeInsets.all(20), child: Column( children: [ - LocaleKeys.enterNewPhoneNumber.tr().toText( - height: 23 / 24, - fontSize: 24, - letterSpacing: -1.44, - ), - 12.height, + // LocaleKeys.enterNewPhoneNumber.tr().toText( + // height: 23 / 24, + // fontSize: 24, + // letterSpacing: -1.44, + // ), + // 12.height, TxtField( hint: LocaleKeys.enterNewPhoneNumber.tr(), onChanged: (v) => mobileNo = v, diff --git a/lib/views/user/change_password_page.dart b/lib/views/user/change_password_page.dart index cea9f1e..7704885 100644 --- a/lib/views/user/change_password_page.dart +++ b/lib/views/user/change_password_page.dart @@ -39,12 +39,12 @@ class _ChangePasswordPageState extends State { padding: const EdgeInsets.all(20), child: Column( children: [ - LocaleKeys.enterNewPassword.tr().toText( - height: 23 / 24, - fontSize: 24, - letterSpacing: -1.44, - ), - 12.height, + // LocaleKeys.enterNewPassword.tr().toText( + // height: 23 / 24, + // fontSize: 24, + // letterSpacing: -1.44, + // ), + // 12.height, TxtField( hint: LocaleKeys.enterOldPassword.tr(), onChanged: (v) => currentPassword = v, diff --git a/lib/views/user/update_user_city_country.dart b/lib/views/user/update_user_city_country.dart new file mode 100644 index 0000000..0f36c8b --- /dev/null +++ b/lib/views/user/update_user_city_country.dart @@ -0,0 +1,105 @@ +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/general_models/widgets_models.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/view_models/user_view_model.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class UpdateUserCityCountry extends StatefulWidget { + const UpdateUserCityCountry({Key? key}) : super(key: key); + + @override + State createState() => _UpdateUserCityCountryState(); +} + +class _UpdateUserCityCountryState extends State { + DropValue? city; + DropValue? country; + + @override + void initState() { + context.read().getAllCountriesForUser(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (BuildContext context, UserVM uVM, Widget? child) { + return Scaffold( + appBar: CustomAppBar( + title: "Update City", + ), + body: Column( + children: [ + uVM.userCountries != null + ? Container( + padding: const EdgeInsets.only(right: 20, left: 20, top: 12), + child: Builder(builder: (context) { + List userCountryDrop = []; + for (var element in uVM.userCountries!.data!) { + if (AppState().getUser.data!.userInfo!.countryId == element.id) { + country = DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", ""); + } + userCountryDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); + } + return DropdownField( + (DropValue value) async { + country = value; + await uVM.getAllCitiesForUser(country!.id); + setState(() {}); + }, + list: userCountryDrop, + dropdownValue: country != null && country != -1 ? DropValue(country!.id, country!.value, "") : null, + hint: country != null && country != -1 ? country!.value : "Country", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })) + : SizedBox(), + uVM.userCities != null + ? Container( + padding: const EdgeInsets.only(right: 20, left: 20, top: 12), + child: Builder(builder: (context) { + List userCityDrop = []; + for (var element in uVM.userCities!.data!) { + if (AppState().getUser.data!.userInfo!.cityId == element.id) { + city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + } + userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); + } + return DropdownField( + (DropValue value) { + city = value; + setState(() {}); + }, + list: userCityDrop, + dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, + hint: city != null && city != -1 ? city!.value : "City", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })) + : SizedBox(), + 20.height, + Padding( + padding: const EdgeInsets.all(20.0), + child: ShowFillButton( + title: LocaleKeys.confirm.tr(), + maxWidth: double.infinity, + onPressed: () async { + await uVM.userDetailsUpdate(context, AppState().getUser.data!.userInfo!.firstName!, AppState().getUser.data!.userInfo!.lastName!, city != null ? city?.id.toString() : null); + }, + ), + ), + ], + ), + ); + }); + } +} diff --git a/lib/views/user/update_user_details.dart b/lib/views/user/update_user_details.dart index 0d6c361..4731bd2 100644 --- a/lib/views/user/update_user_details.dart +++ b/lib/views/user/update_user_details.dart @@ -55,7 +55,7 @@ class _UpdateUserDetailsState extends State { title: LocaleKeys.confirm.tr(), maxWidth: double.infinity, onPressed: () async { - await userVM.userDetailsUpdate(context, firstname, lastname); + await userVM.userDetailsUpdate(context, firstname, lastname, null); }, ), diff --git a/pubspec.yaml b/pubspec.yaml index dfc2ea3..91acd57 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: sizer: ^3.0.4 fluttertoast: ^8.0.8 shared_preferences: ^2.0.6 - file_picker: ^8.1.2 + file_picker: ^8.0.7 image_picker: ^1.1.2 equatable: ^2.0.3 logger: ^2.4.0 @@ -34,7 +34,7 @@ dependencies: badges: ^3.0.2 carousel_slider: 5.0.0 dropdown_button2: ^2.0.0 - flutter_inappwebview: ^6.1.5 + flutter_inappwebview: ^6.0.0 country_code_picker: ^3.0.0 table_calendar: ^3.0.9 intl: any @@ -47,8 +47,8 @@ dependencies: # Firebase Packages - firebase_messaging: ^15.1.3 - firebase_core: ^3.6.0 + firebase_messaging: ^15.0.4 + firebase_core: ^3.3.0 flutter_local_notifications: ^18.0.0 @@ -62,7 +62,7 @@ dependencies: # Auth local_auth: ^2.2.0 # huawei_fido: ^6.3.0+305 - device_info_plus: ^11.0.0 + device_info_plus: ^10.1.0 dev_dependencies: From 2fcc2792a38e9147ab92d1acda7a85d51a69cfb6 Mon Sep 17 00:00:00 2001 From: Aamir Date: Mon, 2 Dec 2024 10:22:03 +0300 Subject: [PATCH 09/11] CMA 244 --- assets/langs/ar-SA.json | 10 +- assets/langs/en-US.json | 9 +- lib/classes/app_state.dart | 10 ++ lib/generated/codegen_loader.g.dart | 16 ++- lib/generated/locale_keys.g.dart | 14 ++- lib/repositories/user_repo.dart | 8 +- lib/view_models/user_view_model.dart | 14 ++- lib/views/user/complete_profile_page.dart | 102 +++++++++++++++---- lib/views/user/register_provider_page.dart | 10 +- lib/views/user/update_user_city_country.dart | 6 +- 10 files changed, 163 insertions(+), 36 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 01b8045..e65240d 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -744,5 +744,13 @@ "blockedByAdmin": "تم حظرها من قبل المسؤول", "active": "نشط", "paymentType": "نوع الدفع", - "searchByCreatedDate": "البحث حسب تاريخ الإنشاء" + "searchByCreatedDate": "البحث حسب تاريخ الإنشاء", + "cityNameMandatory": "المدينة إلزامية", + "genderMandatory": "الجنس إلزامي", + "updateCity": "تحديث المدينة", + "userGender": "جنس", + "userMale": "ذكر", + "userFemale": "أنثى" + + } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 65c26db..65eea5d 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -742,6 +742,11 @@ "updateUserDetails": "Update User Details", "enterNewFirstName": "Enter First Name", "enterNewLastName": "Enter Last Name", - "userDetailsUpdated": "User Details is Updated" - + "userDetailsUpdated": "User Details is Updated", + "cityNameMandatory": "City is mandatory", + "genderMandatory": "Gender is mandatory", + "updateCity": "Update City", + "userGender": "Gender", + "userMale": "Male", + "userFemale": "Female" } \ No newline at end of file diff --git a/lib/classes/app_state.dart b/lib/classes/app_state.dart index 4d528d9..09ddd54 100644 --- a/lib/classes/app_state.dart +++ b/lib/classes/app_state.dart @@ -4,6 +4,7 @@ import 'package:mc_common_app/models/subscriptions_models/provider_subscription_ import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart'; import 'package:mc_common_app/models/user_models/user.dart'; import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; class AppState { static final AppState _instance = AppState._internal(); @@ -70,4 +71,13 @@ class AppState { set setproviderSubscription(List? value) { _providerSubscription = value; } + + + DropValue? _userRegisterCountrySelection ; + + DropValue get getUserRegisterCountrySelection => _userRegisterCountrySelection!; + + set setUserRegisterCountrySelection(DropValue value) { + _userRegisterCountrySelection = value; + } } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 94e96d1..6a25b80 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -760,7 +760,13 @@ class CodegenLoader extends AssetLoader{ "blockedByAdmin": "تم حظرها من قبل المسؤول", "active": "نشط", "paymentType": "نوع الدفع", - "searchByCreatedDate": "البحث حسب تاريخ الإنشاء" + "searchByCreatedDate": "البحث حسب تاريخ الإنشاء", + "cityNameMandatory": "المدينة إلزامية", + "genderMandatory": "الجنس إلزامي", + "updateCity": "تحديث المدينة", + "userGender": "جنس", + "userMale": "ذكر", + "userFemale": "أنثى" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1506,7 +1512,13 @@ static const Map en_US = { "updateUserDetails": "Update User Details", "enterNewFirstName": "Enter First Name", "enterNewLastName": "Enter Last Name", - "userDetailsUpdated": "User Details is Updated" + "userDetailsUpdated": "User Details is Updated", + "cityNameMandatory": "City is mandatory", + "genderMandatory": "Gender is mandatory", + "updateCity": "Update City", + "userGender": "Gender", + "userMale": "Male", + "userFemale": "Female" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 4d6b505..be7dc15 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -684,6 +684,10 @@ abstract class LocaleKeys { static const customerLocation = 'customerLocation'; static const deliveryAvailable = 'deliveryAvailable'; static const viewed = 'viewed'; + static const updateUserDetails = 'updateUserDetails'; + static const enterNewFirstName = 'enterNewFirstName'; + static const enterNewLastName = 'enterNewLastName'; + static const userDetailsUpdated = 'userDetailsUpdated'; static const itemNoLongerAvailable = 'itemNoLongerAvailable'; static const reactivateAd = 'reactivateAd'; static const dealOutsideApp = 'dealOutsideApp'; @@ -720,9 +724,11 @@ abstract class LocaleKeys { static const active = 'active'; static const paymentType = 'paymentType'; static const searchByCreatedDate = 'searchByCreatedDate'; - static const updateUserDetails = 'updateUserDetails'; - static const enterNewFirstName = 'enterNewFirstName'; - static const enterNewLastName = 'enterNewLastName'; - static const userDetailsUpdated = 'userDetailsUpdated'; + static const cityNameMandatory = 'cityNameMandatory'; + static const genderMandatory = 'genderMandatory'; + static const updateCity = 'updateCity'; + static const userGender = 'userGender'; + static const userMale = 'userMale'; + static const userFemale = 'userFemale'; } diff --git a/lib/repositories/user_repo.dart b/lib/repositories/user_repo.dart index 9ce6d57..589681e 100644 --- a/lib/repositories/user_repo.dart +++ b/lib/repositories/user_repo.dart @@ -31,7 +31,7 @@ abstract class UserRepo { Future basicVerify(String phoneNo, String otp, String userToken, {bool isNeedToPassToken = false}); - Future basicComplete(String userId, String firstName, String lastName, String email, String password, {bool isNeedToPassToken = false}); + Future basicComplete(String userId, String firstName, String lastName, String email, String password, String cityID, String genderID, {bool isNeedToPassToken = false}); Future loginV1(String phoneNo, String password); @@ -106,12 +106,12 @@ class UserRepoImp implements UserRepo { } @override - Future basicComplete(String userId, String firstName, String lastName, String email, String password, {bool isNeedToPassToken = false}) async { + Future basicComplete(String userId, String firstName, String lastName, String email, String password, String cityID, String genderID, {bool isNeedToPassToken = false}) async { Map postParams; if (email.isEmpty) { - postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "companyName": "string", "isEmailVerified": true, "password": password}; + postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "companyName": "string", "isEmailVerified": true, "password": password, "cityID": cityID, "genderID": genderID}; } else { - postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "email": email, "companyName": "string", "isEmailVerified": true, "password": password}; + postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "email": email, "companyName": "string", "isEmailVerified": true, "password": password, "cityID": cityID, "genderID": genderID}; } String? t; if (isNeedToPassToken) { diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index fd6cbee..d06f1c6 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -45,6 +45,7 @@ import 'package:mc_common_app/views/location_views/map_selection_widget.dart'; import 'package:mc_common_app/widgets/dialog/dialogs.dart'; import 'package:mc_common_app/widgets/dialog/message_dialog.dart'; import 'package:mc_common_app/widgets/dialog/otp_dialog.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/tab/login_email_tab.dart'; import 'package:provider/provider.dart'; @@ -198,11 +199,13 @@ class UserVM extends BaseVM { required String email, required String? userId, bool isNeedToPassToken = false, + required String cityID, + required String genderID, }) async { if (Utils.passwordValidateStructure(password)) { if (password == confirmPassword) { Utils.showLoading(context); - RegisterUserRespModel user = await userRepo.basicComplete(userId ?? "", firstName, lastName, email, password, isNeedToPassToken: isNeedToPassToken); + RegisterUserRespModel user = await userRepo.basicComplete(userId ?? "", firstName, lastName, email, password, cityID, genderID, isNeedToPassToken: isNeedToPassToken); Utils.hideLoading(context); if (user.messageStatus == 1) { Utils.showToast(LocaleKeys.successfullyRegistered.tr()); @@ -225,6 +228,8 @@ class UserVM extends BaseVM { required String? firstName, required String? lastName, required String? email, + required DropValue? city, + required DropValue? gender, }) { bool isValid = true; if (firstName!.isEmpty) { @@ -249,6 +254,13 @@ class UserVM extends BaseVM { //("Please accept terms"); isValid = false; } + else if (city == null) { + Utils.showToast(LocaleKeys.cityNameMandatory.tr()); + isValid = false; + } else if (gender == null) { + Utils.showToast(LocaleKeys.genderMandatory.tr()); + isValid = false; + } return isValid; } diff --git a/lib/views/user/complete_profile_page.dart b/lib/views/user/complete_profile_page.dart index d484d6f..eb93b4e 100644 --- a/lib/views/user/complete_profile_page.dart +++ b/lib/views/user/complete_profile_page.dart @@ -1,3 +1,4 @@ +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -9,6 +10,7 @@ import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/view_models/user_view_model.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -25,17 +27,29 @@ class CompleteProfilePage extends StatefulWidget { } class _CompleteProfilePageState extends State { - String? firstName = "", lastName = "", email = "", confirmPassword = ""; + String? firstName = "", + lastName = "", + email = "", + confirmPassword = ""; late String password = ""; bool isChecked = false; late UserVM userVM; + DropValue? city; + DropValue? gender; @override void initState() { userVM = Provider.of(context, listen: false); + getcities(); + super.initState(); } + getcities() async { + print("Country ID = " + AppState().getUserRegisterCountrySelection.id.toString()); + await userVM.getAllCitiesForUser(AppState().getUserRegisterCountrySelection.id); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -53,20 +67,20 @@ class _CompleteProfilePageState extends State { children: [ 6.height, LocaleKeys.completeProfile.tr().toText( - height: 23 / 24, - fontSize: 24, - letterSpacing: -1.44, - ), + height: 23 / 24, + fontSize: 24, + letterSpacing: -1.44, + ), 12.height, Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: LocaleKeys.profileMsg.tr().toText( - color: MyColors.lightTextColor, - textAlign: TextAlign.center, - fontSize: 14, - height: 23 / 24, - letterSpacing: -0.48, - ), + color: MyColors.lightTextColor, + textAlign: TextAlign.center, + fontSize: 14, + height: 23 / 24, + letterSpacing: -0.48, + ), ), 12.height, TxtField( @@ -85,6 +99,32 @@ class _CompleteProfilePageState extends State { }, ), 12.height, + Container( + padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), + child: Builder(builder: (context) { + List userGender = []; + userGender.add(DropValue(1.toInt(), "${LocaleKeys.userMale.tr()}", "", isEnabled: true)); + userGender.add(DropValue(2.toInt(), "${LocaleKeys.userFemale.tr()}", "", isEnabled: true)); + // for (var element in userVM.userCities!.data!) { + // if (AppState().getUser.data != null) { + // if (AppState().getUser.data!.userInfo!.cityId == element.id) { + // city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + // } + // } + // + // } + return DropdownField( + (DropValue value) { + gender = value; + setState(() {}); + }, + list: userGender, + dropdownValue: gender != null && gender != -1 ? DropValue(gender!.id, gender!.value, "") : null, + hint: gender != null && gender != -1 ? gender!.value : "${LocaleKeys.userGender.tr()} *", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })), + 12.height, TxtField( hint: LocaleKeys.email.tr(), value: email, @@ -95,6 +135,32 @@ class _CompleteProfilePageState extends State { }, ), 12.height, + userVM.userCities != null + ? Container( + padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), + child: Builder(builder: (context) { + List userCityDrop = []; + for (var element in userVM.userCities!.data!) { + if (AppState().getUser.data != null) { + if (AppState().getUser.data!.userInfo!.cityId == element.id) { + city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + } + } + userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); + } + return DropdownField( + (DropValue value) { + city = value; + setState(() {}); + }, + list: userCityDrop, + dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, + hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })) + : SizedBox(), + 12.height, TxtField( hint: LocaleKeys.createPass.tr(), isPasswordEnabled: true, @@ -175,12 +241,12 @@ class _CompleteProfilePageState extends State { if (!userVM.completeProfilePageCheckbox) { return; } - bool validateStatus = userVM.dataValidation( - password: password, - firstName: firstName, - lastName: lastName, - email: email, - ); + bool validateStatus = userVM.dataValidation(password: password, + firstName: firstName, + lastName: lastName, + email: email, + city: city, + gender: gender); if (validateStatus) { userVM.performCompleteProfile( context, @@ -191,6 +257,8 @@ class _CompleteProfilePageState extends State { email: email!, userId: widget.user.data!.userId ?? "", isNeedToPassToken: widget.user.data!.isNeedToPassToken, + cityID: city!.id.toString(), + genderID: gender!.id.toString(), ); } }); diff --git a/lib/views/user/register_provider_page.dart b/lib/views/user/register_provider_page.dart index aa9cb5a..8df8486 100644 --- a/lib/views/user/register_provider_page.dart +++ b/lib/views/user/register_provider_page.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/config/dependency_injection.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; @@ -118,8 +119,12 @@ class _RegisterPageState extends State { if (snapshot.hasData) { List dropList = []; snapshot.data?.data?.forEach((element) { - dropList.add(DropValue(element.id ?? 0, - EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? "${element.countryNameN ?? ""} ${element.countryCode ?? ""}" : "${element.countryName ?? ""} ${element.countryCode ?? ""}", element.countryCode ?? "")); + dropList.add(DropValue( + element.id ?? 0, + EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" + ? "${element.countryNameN ?? ""} ${element.countryCode ?? ""}" + : "${element.countryName ?? ""} ${element.countryCode ?? ""}", + element.countryCode ?? "")); }); return Column( children: [ @@ -132,6 +137,7 @@ class _RegisterPageState extends State { DropdownField( (DropValue value) { selectedDrop = value; + AppState().setUserRegisterCountrySelection = value; setState(() { countryCode = value.subValue; countryId = value.id; diff --git a/lib/views/user/update_user_city_country.dart b/lib/views/user/update_user_city_country.dart index 0f36c8b..5107c5c 100644 --- a/lib/views/user/update_user_city_country.dart +++ b/lib/views/user/update_user_city_country.dart @@ -35,7 +35,7 @@ class _UpdateUserCityCountryState extends State { return Consumer(builder: (BuildContext context, UserVM uVM, Widget? child) { return Scaffold( appBar: CustomAppBar( - title: "Update City", + title: LocaleKeys.updateCity.tr(), ), body: Column( children: [ @@ -58,7 +58,7 @@ class _UpdateUserCityCountryState extends State { }, list: userCountryDrop, dropdownValue: country != null && country != -1 ? DropValue(country!.id, country!.value, "") : null, - hint: country != null && country != -1 ? country!.value : "Country", + hint: country != null && country != -1 ? country!.value : "${LocaleKeys.country.tr()} *", // errorValue: adVM.vehicleCountryId.errorValue, ); })) @@ -81,7 +81,7 @@ class _UpdateUserCityCountryState extends State { }, list: userCityDrop, dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, - hint: city != null && city != -1 ? city!.value : "City", + hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", // errorValue: adVM.vehicleCountryId.errorValue, ); })) From 803ade0b9da6f71b398a59f2df08add49606e006 Mon Sep 17 00:00:00 2001 From: Aamir Date: Mon, 2 Dec 2024 10:39:14 +0300 Subject: [PATCH 10/11] CMA 244 --- lib/views/user/complete_profile_page.dart | 434 +++++++++++----------- lib/views/user/register_page.dart | 4 +- 2 files changed, 219 insertions(+), 219 deletions(-) diff --git a/lib/views/user/complete_profile_page.dart b/lib/views/user/complete_profile_page.dart index eb93b4e..e78392e 100644 --- a/lib/views/user/complete_profile_page.dart +++ b/lib/views/user/complete_profile_page.dart @@ -33,242 +33,240 @@ class _CompleteProfilePageState extends State { confirmPassword = ""; late String password = ""; bool isChecked = false; - late UserVM userVM; DropValue? city; DropValue? gender; @override void initState() { - userVM = Provider.of(context, listen: false); - getcities(); - super.initState(); } - getcities() async { - print("Country ID = " + AppState().getUserRegisterCountrySelection.id.toString()); - await userVM.getAllCitiesForUser(AppState().getUserRegisterCountrySelection.id); - } + @override Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - isRemoveBackButton: widget.user.data!.roleId == 7 ? false : true, - title: widget.user.data!.roleId == 7 ? "" : LocaleKeys.signUp.tr(), - ), - body: SizedBox( - width: double.infinity, - height: double.infinity, - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - 6.height, - LocaleKeys.completeProfile.tr().toText( - height: 23 / 24, - fontSize: 24, - letterSpacing: -1.44, - ), - 12.height, - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: LocaleKeys.profileMsg.tr().toText( - color: MyColors.lightTextColor, - textAlign: TextAlign.center, - fontSize: 14, - height: 23 / 24, - letterSpacing: -0.48, - ), - ), - 12.height, - TxtField( - hint: LocaleKeys.firstName.tr(), - value: firstName, - onChanged: (v) { - firstName = v; - }, - ), - 12.height, - TxtField( - hint: LocaleKeys.surname.tr(), - value: lastName, - onChanged: (v) { - lastName = v; - }, - ), - 12.height, - Container( - padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), - child: Builder(builder: (context) { - List userGender = []; - userGender.add(DropValue(1.toInt(), "${LocaleKeys.userMale.tr()}", "", isEnabled: true)); - userGender.add(DropValue(2.toInt(), "${LocaleKeys.userFemale.tr()}", "", isEnabled: true)); - // for (var element in userVM.userCities!.data!) { - // if (AppState().getUser.data != null) { - // if (AppState().getUser.data!.userInfo!.cityId == element.id) { - // city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); - // } - // } - // - // } - return DropdownField( - (DropValue value) { - gender = value; - setState(() {}); - }, - list: userGender, - dropdownValue: gender != null && gender != -1 ? DropValue(gender!.id, gender!.value, "") : null, - hint: gender != null && gender != -1 ? gender!.value : "${LocaleKeys.userGender.tr()} *", - // errorValue: adVM.vehicleCountryId.errorValue, - ); - })), - 12.height, - TxtField( - hint: LocaleKeys.email.tr(), - value: email, - // isButtonEnable: email!.length > 0 ? true : false, - buttonTitle: LocaleKeys.verify.tr(), - onChanged: (v) { - email = v; - }, - ), - 12.height, - userVM.userCities != null - ? Container( - padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), - child: Builder(builder: (context) { - List userCityDrop = []; - for (var element in userVM.userCities!.data!) { - if (AppState().getUser.data != null) { - if (AppState().getUser.data!.userInfo!.cityId == element.id) { - city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); - } - } - userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); - } - return DropdownField( - (DropValue value) { - city = value; - setState(() {}); - }, - list: userCityDrop, - dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, - hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", - // errorValue: adVM.vehicleCountryId.errorValue, - ); - })) - : SizedBox(), - 12.height, - TxtField( - hint: LocaleKeys.createPass.tr(), - isPasswordEnabled: true, - maxLines: 1, - value: password, - onChanged: (v) { - password = v; - }, - ), - 12.height, - TxtField( - hint: LocaleKeys.confirmPass.tr(), - isPasswordEnabled: true, - maxLines: 1, - value: confirmPassword, - onChanged: (v) { - confirmPassword = v; - }, - ), - 50.height, - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, + return Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { + print("Country ID = " + AppState().getUserRegisterCountrySelection.id.toString()); + userVM.getAllCitiesForUser(AppState().getUserRegisterCountrySelection.id); + return Scaffold( + appBar: CustomAppBar( + isRemoveBackButton: widget.user.data!.roleId == 7 ? false : true, + title: widget.user.data!.roleId == 7 ? "" : LocaleKeys.signUp.tr(), + ), + body: SizedBox( + width: double.infinity, + height: double.infinity, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( children: [ - Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { - return Checkbox( - value: userVM.completeProfilePageCheckbox, - activeColor: MyColors.darkPrimaryColor, - onChanged: (value) { - userVM.updateCompleteProfilePageCheckbox(value!); - }, - ); - }), - Expanded( - child: Text.rich( - TextSpan( - children: [ + 6.height, + LocaleKeys.completeProfile.tr().toText( + height: 23 / 24, + fontSize: 24, + letterSpacing: -1.44, + ), + 12.height, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: LocaleKeys.profileMsg.tr().toText( + color: MyColors.lightTextColor, + textAlign: TextAlign.center, + fontSize: 14, + height: 23 / 24, + letterSpacing: -0.48, + ), + ), + 12.height, + TxtField( + hint: LocaleKeys.firstName.tr(), + value: firstName, + onChanged: (v) { + firstName = v; + }, + ), + 12.height, + TxtField( + hint: LocaleKeys.surname.tr(), + value: lastName, + onChanged: (v) { + lastName = v; + }, + ), + 12.height, + Container( + padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), + child: Builder(builder: (context) { + List userGender = []; + userGender.add(DropValue(1.toInt(), "${LocaleKeys.userMale.tr()}", "", isEnabled: true)); + userGender.add(DropValue(2.toInt(), "${LocaleKeys.userFemale.tr()}", "", isEnabled: true)); + // for (var element in userVM.userCities!.data!) { + // if (AppState().getUser.data != null) { + // if (AppState().getUser.data!.userInfo!.cityId == element.id) { + // city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + // } + // } + // + // } + return DropdownField( + (DropValue value) { + gender = value; + setState(() {}); + }, + list: userGender, + dropdownValue: gender != null && gender != -1 ? DropValue(gender!.id, gender!.value, "") : null, + hint: gender != null && gender != -1 ? gender!.value : "${LocaleKeys.userGender.tr()} *", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })), + 12.height, + TxtField( + hint: LocaleKeys.email.tr(), + value: email, + // isButtonEnable: email!.length > 0 ? true : false, + buttonTitle: LocaleKeys.verify.tr(), + onChanged: (v) { + email = v; + }, + ), + 12.height, + userVM.userCities != null + ? Container( + padding: const EdgeInsets.only(right: 0, left: 0, top: 0, bottom: 0), + child: Builder(builder: (context) { + List userCityDrop = []; + for (var element in userVM.userCities!.data!) { + if (AppState().getUser.data != null) { + if (AppState().getUser.data!.userInfo!.cityId == element.id) { + city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + } + } + userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); + } + return DropdownField( + (DropValue value) { + city = value; + setState(() {}); + }, + list: userCityDrop, + dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, + hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })) + : SizedBox(), + 12.height, + TxtField( + hint: LocaleKeys.createPass.tr(), + isPasswordEnabled: true, + maxLines: 1, + value: password, + onChanged: (v) { + password = v; + }, + ), + 12.height, + TxtField( + hint: LocaleKeys.confirmPass.tr(), + isPasswordEnabled: true, + maxLines: 1, + value: confirmPassword, + onChanged: (v) { + confirmPassword = v; + }, + ), + 50.height, + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { + return Checkbox( + value: userVM.completeProfilePageCheckbox, + activeColor: MyColors.darkPrimaryColor, + onChanged: (value) { + userVM.updateCompleteProfilePageCheckbox(value!); + }, + ); + }), + Expanded( + child: Text.rich( TextSpan( - text: LocaleKeys.termsOfService.tr(), - style: const TextStyle(fontSize: 12, fontWeight: MyFonts.Medium), + children: [ + TextSpan( + text: LocaleKeys.termsOfService.tr(), + style: const TextStyle(fontSize: 12, fontWeight: MyFonts.Medium), + ), + TextSpan( + text: " ${LocaleKeys.terms.tr()}", + style: const TextStyle( + decoration: TextDecoration.underline, + fontSize: 12, + color: MyColors.darkPrimaryColor, + fontWeight: MyFonts.Bold, + )) + ], ), - TextSpan( - text: " ${LocaleKeys.terms.tr()}", - style: const TextStyle( - decoration: TextDecoration.underline, - fontSize: 12, - color: MyColors.darkPrimaryColor, - fontWeight: MyFonts.Bold, - )) - ], - ), - ).onPress(() { - navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions); - }), - ) - // Column( - // children: [ - // LocaleKeys.termsOfService.tr().toText(fontSize: 12), - // LocaleKeys.terms.tr().toText(fontSize: 12, color: MyColors.darkPrimaryColor), - // ], - // ), - // Theme( - // data: ThemeData(unselectedWidgetColor: Colors.transparent), - // child: Checkbox( - // value: false, - // onChanged: (_) {}, - // ), - // ) + ).onPress(() { + navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions); + }), + ) + // Column( + // children: [ + // LocaleKeys.termsOfService.tr().toText(fontSize: 12), + // LocaleKeys.terms.tr().toText(fontSize: 12, color: MyColors.darkPrimaryColor), + // ], + // ), + // Theme( + // data: ThemeData(unselectedWidgetColor: Colors.transparent), + // child: Checkbox( + // value: false, + // onChanged: (_) {}, + // ), + // ) + ], + ), + 16.height, + Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { + return ShowFillButton( + title: LocaleKeys.save.tr(), + maxWidth: double.infinity, + isDisabled: !userVM.completeProfilePageCheckbox, + onPressed: () { + if (!userVM.completeProfilePageCheckbox) { + return; + } + bool validateStatus = userVM.dataValidation(password: password, + firstName: firstName, + lastName: lastName, + email: email, + city: city, + gender: gender); + if (validateStatus) { + userVM.performCompleteProfile( + context, + password: password, + confirmPassword: confirmPassword!, + firstName: firstName!, + lastName: lastName!, + email: email!, + userId: widget.user.data!.userId ?? "", + isNeedToPassToken: widget.user.data!.isNeedToPassToken, + cityID: city!.id.toString(), + genderID: gender!.id.toString(), + ); + } + }); + }), + 16.height, ], ), - 16.height, - Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { - return ShowFillButton( - title: LocaleKeys.save.tr(), - maxWidth: double.infinity, - isDisabled: !userVM.completeProfilePageCheckbox, - onPressed: () { - if (!userVM.completeProfilePageCheckbox) { - return; - } - bool validateStatus = userVM.dataValidation(password: password, - firstName: firstName, - lastName: lastName, - email: email, - city: city, - gender: gender); - if (validateStatus) { - userVM.performCompleteProfile( - context, - password: password, - confirmPassword: confirmPassword!, - firstName: firstName!, - lastName: lastName!, - email: email!, - userId: widget.user.data!.userId ?? "", - isNeedToPassToken: widget.user.data!.isNeedToPassToken, - cityID: city!.id.toString(), - genderID: gender!.id.toString(), - ); - } - }); - }), - 16.height, - ], + ), ), ), - ), - ), + ); + } ); } } diff --git a/lib/views/user/register_page.dart b/lib/views/user/register_page.dart index 31c2e05..a5e9d20 100644 --- a/lib/views/user/register_page.dart +++ b/lib/views/user/register_page.dart @@ -1,3 +1,4 @@ +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; @@ -78,8 +79,9 @@ class _RegisterPageState extends State { DropdownField( dropdownValue: selectedDrop, (DropValue value) { + print("========"); selectedDrop = value; - + AppState().setUserRegisterCountrySelection = value; setState(() { countryCode = value.subValue; countryId = value.id; From aaa8f68e6026272d11f7f09190def5a33d1cc3dc Mon Sep 17 00:00:00 2001 From: Aamir Date: Thu, 5 Dec 2024 12:39:30 +0300 Subject: [PATCH 11/11] fixes --- assets/langs/ar-SA.json | 6 +- assets/langs/en-US.json | 6 +- lib/classes/consts.dart | 8 + lib/generated/codegen_loader.g.dart | 12 +- lib/generated/locale_keys.g.dart | 4 + .../profile/document.dart | 102 ++++--- lib/models/user_models/user.dart | 9 + lib/repositories/branch_repo.dart | 1 + lib/services/common_services.dart | 36 ++- lib/utils/location/Location.dart | 3 +- lib/view_models/ad_view_model.dart | 18 ++ lib/view_models/chat_view_model.dart | 5 + lib/view_models/requests_view_model.dart | 7 + lib/view_models/service_view_model.dart | 33 +-- lib/view_models/user_view_model.dart | 24 +- .../provider_license_page.dart | 269 ++++++++++-------- lib/views/user/register_page.dart | 1 - lib/views/user/update_user_city_country.dart | 100 ++++--- lib/views/user/update_user_details.dart | 4 +- 19 files changed, 419 insertions(+), 229 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index e65240d..e1eed1a 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -750,7 +750,11 @@ "updateCity": "تحديث المدينة", "userGender": "جنس", "userMale": "ذكر", - "userFemale": "أنثى" + "userFemale": "أنثى", + "maxFileSelection" :"يمكنك تحديد الحد الأقصى لملفات 7", + "maxFileSize": "يجب أن يكون حجم كل ملف أقل من 2 ميغابايت", + "onlyJPGandPNG": "يُسمح فقط بملفات JPG وPNG", + "expiryDate": "تاريخ انتهاء الصلاحية" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 65eea5d..8d55a7b 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -748,5 +748,9 @@ "updateCity": "Update City", "userGender": "Gender", "userMale": "Male", - "userFemale": "Female" + "userFemale": "Female", + "maxFileSelection" :"You can select a maximum of 7 files", + "maxFileSize": "Each file size must be less than 2 MB", + "onlyJPGandPNG": "Only JPG and PNG files are allowed", + "expiryDate": "Expiry Date" } \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index a7a73f3..5a97810 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -253,6 +253,12 @@ class GlobalConsts { } return appInvitationMessageEn; } + + + // Attachment Values + + int maxFileCount = 7; + int maxFileSizeInBytes = 2 * 1024 * 1024; } class MyAssets { @@ -394,4 +400,6 @@ class SignalrConsts { // General static String sendMessageGeneral = "SendMessageGeneral"; static String receiveMessageGeneral = "ReceiveMessageGeneral"; + + } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 6a25b80..bd7c9f3 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -766,7 +766,11 @@ class CodegenLoader extends AssetLoader{ "updateCity": "تحديث المدينة", "userGender": "جنس", "userMale": "ذكر", - "userFemale": "أنثى" + "userFemale": "أنثى", + "maxFileSelection": "يمكنك تحديد الحد الأقصى لملفات 7", + "maxFileSize": "يجب أن يكون حجم كل ملف أقل من 2 ميغابايت", + "onlyJPGandPNG": "يُسمح فقط بملفات JPG وPNG", + "expiryDate": "تاريخ انتهاء الصلاحية" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1518,7 +1522,11 @@ static const Map en_US = { "updateCity": "Update City", "userGender": "Gender", "userMale": "Male", - "userFemale": "Female" + "userFemale": "Female", + "maxFileSelection": "You can select a maximum of 7 files", + "maxFileSize": "Each file size must be less than 2 MB", + "onlyJPGandPNG": "Only JPG and PNG files are allowed", + "expiryDate": "Expiry Date" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index be7dc15..16cec03 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -730,5 +730,9 @@ abstract class LocaleKeys { static const userGender = 'userGender'; static const userMale = 'userMale'; static const userFemale = 'userFemale'; + static const maxFileSelection = 'maxFileSelection'; + static const maxFileSize = 'maxFileSize'; + static const onlyJPGandPNG = 'onlyJPGandPNG'; + static const expiryDate = 'expiryDate'; } diff --git a/lib/models/provider_branches_models/profile/document.dart b/lib/models/provider_branches_models/profile/document.dart index d82aa02..bea4d46 100644 --- a/lib/models/provider_branches_models/profile/document.dart +++ b/lib/models/provider_branches_models/profile/document.dart @@ -4,6 +4,8 @@ import 'dart:convert'; +import 'package:mc_common_app/utils/enums.dart'; + Document documentFromJson(String str) => Document.fromJson(json.decode(str)); String documentToJson(Document data) => json.encode(data.toJson()); @@ -21,16 +23,14 @@ class Document { int? messageStatus; String? message; - factory Document.fromJson(Map json) => - Document( + factory Document.fromJson(Map json) => Document( totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : List.from(json["data"].map((x) => DocumentData.fromJson(x))), messageStatus: json["messageStatus"], message: json["message"], ); - Map toJson() => - { + Map toJson() => { "totalItemsCount": totalItemsCount, "data": data == null ? null : List.from(data!.map((x) => x.toJson())), "messageStatus": messageStatus, @@ -39,27 +39,29 @@ class Document { } class DocumentData { - DocumentData({ - this.id, - this.serviceProviderId, - this.documentId, - this.documentUrl, - this.status, - this.statusText, - this.comment, - this.isActive, - this.document, - this.fileExt, - this.documentName, - this.isLocalFile, - this.description, - }); + DocumentData( + {this.id, + this.serviceProviderId, + this.documentId, + this.documentUrl, + this.status, + this.statusText, + this.comment, + this.isActive, + this.document, + this.fileExt, + this.documentName, + this.isLocalFile, + this.description, + this.dateExpire, + this.isAllowUpdate, + this.isExpired}); int? id; int? serviceProviderId; int? documentId; String? documentUrl; - int? status; + DocumentStatusEnum? status; String? comment; bool? isActive; String? document; @@ -68,25 +70,29 @@ class DocumentData { String? documentName; bool? isLocalFile; String? description; + String? dateExpire; + bool? isExpired; + bool? isAllowUpdate; - factory DocumentData.fromJson(Map json) => - DocumentData( - id: json["id"], - serviceProviderId: json["serviceProviderID"], - documentId: json["documentID"], - documentUrl: json["documentURL"], - status: json["status"], - statusText: json["statusText"], - comment: json["comment"], - isActive: json["isActive"], - document: null, - fileExt: null, - documentName: json["documentName"], - isLocalFile: false, - description: null); + factory DocumentData.fromJson(Map json) => DocumentData( + id: json["id"], + serviceProviderId: json["serviceProviderID"], + documentId: json["documentID"], + documentUrl: json["documentURL"], + status: json.containsKey("status") ? (json['status'] as int).toDocumentStatusEnum() : null, + statusText: json["statusText"], + comment: json["comment"], + isActive: json["isActive"], + dateExpire: json["dateExpire"], + isExpired: json["isExpired"], + isAllowUpdate: json["isAllowUpdate"], + document: null, + fileExt: null, + documentName: json["documentName"], + isLocalFile: false, + description: null); - Map toJson() => - { + Map toJson() => { "id": id, "serviceProviderID": serviceProviderId, "documentID": documentId, @@ -94,5 +100,27 @@ class DocumentData { "status": status, "comment": comment, "isActive": isActive, + "dateExpire": dateExpire, + "isExpired": isExpired, + "isAllowUpdate": isAllowUpdate, }; } + +extension DocumentEnum on int { + DocumentStatusEnum toDocumentStatusEnum() { + switch (this) { + case 0: + return DocumentStatusEnum.needUpload; + case 1: + return DocumentStatusEnum.pending; + case 2: + return DocumentStatusEnum.review; + case 3: + return DocumentStatusEnum.approvedOrActive; + case 4: + return DocumentStatusEnum.rejected; + default: + throw Exception('Invalid status value: $this'); // Explicit handling for invalid cases + } + } +} diff --git a/lib/models/user_models/user.dart b/lib/models/user_models/user.dart index 659edaf..7c91069 100644 --- a/lib/models/user_models/user.dart +++ b/lib/models/user_models/user.dart @@ -82,6 +82,8 @@ class UserInfo { this.userImageUrl, this.roleId, this.roleName, + this.genderID, + this.genderName, this.isEmailVerified, this.serviceProviderBranch, this.isVerified, @@ -97,6 +99,7 @@ class UserInfo { this.userLocalImage, this.cityName, this.countryName, + }); int? id; @@ -105,6 +108,8 @@ class UserInfo { String? lastName; String? countryName; String? cityName; + int? genderID; + String? genderName; String? mobileNo; String? email; dynamic userImageUrl; @@ -139,6 +144,8 @@ class UserInfo { firstName = json["firstName"]; lastName = json["lastName"]; cityName = json["cityName"]; + genderID = json["genderID"]; + genderName = json["genderName"]; countryName = json["countryName"]; mobileNo = json["mobileNo"]; email = json["email"]; @@ -205,6 +212,8 @@ class UserInfo { "providerID": providerId, "customerID": customerId, "dealershipID": dealershipId, + "genderName": genderName, + "genderID": genderID }; @override diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index 2cb2f77..6375ee0 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -208,6 +208,7 @@ class BranchRepoImp implements BranchRepo { "documentExt": documents[i].fileExt, "documentImage": documents[i].document, "isActive": true, + "dateExpire":documents[i].dateExpire, }; map.add(postParams); } diff --git a/lib/services/common_services.dart b/lib/services/common_services.dart index c80988d..ccc77ea 100644 --- a/lib/services/common_services.dart +++ b/lib/services/common_services.dart @@ -4,6 +4,8 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/main.dart'; import 'package:mc_common_app/utils/app_permission_handler.dart'; import 'package:mc_common_app/utils/utils.dart'; @@ -56,21 +58,35 @@ class CommonServicesImp implements CommonAppServices { return pickedFiles; } - @override + + Future> pickMultipleImages() async { final picker = ImagePicker(); - final pickedImagesXFiles = await picker.pickMultiImage(); - + List imageModels = []; List pickedImages = []; - if (pickedImagesXFiles == null) { - return []; - } - if (pickedImagesXFiles.isEmpty) { - return []; + var images = await picker.pickMultiImage(imageQuality: 70); + + for (var element in images) { + final extension = element.path.split('.').last.toLowerCase(); + + if (extension != 'jpg' && extension != 'jpeg' && extension != 'png') { + Utils.showToast(LocaleKeys.onlyJPGandPNG); + return []; + } + + if (await element.length() > GlobalConsts().maxFileSizeInBytes) { + Utils.showToast(LocaleKeys.maxFileSize); + return []; + } + imageModels.add(File(element.path)); } - for (var element in pickedImagesXFiles) { - pickedImages.add(File(element.path)); + + if (imageModels.length > GlobalConsts().maxFileCount) { + Utils.showToast(LocaleKeys.maxFileSelection); + imageModels = imageModels.sublist(0, GlobalConsts().maxFileCount); // Keep only the first 7 images } + + pickedImages.addAll(imageModels); return pickedImages; } diff --git a/lib/utils/location/Location.dart b/lib/utils/location/Location.dart index 0b08abe..5d2260d 100644 --- a/lib/utils/location/Location.dart +++ b/lib/utils/location/Location.dart @@ -81,7 +81,8 @@ class LocationService implements Location { if (granted) { Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) { if (value == null) { - Geolocator.getCurrentPosition().then((value) { + Geolocator.getCurrentPosition().then((value) async { + if(value == null) await Geolocator.openAppSettings(); done(value); }); } else { diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index 76b0f09..6f1cf99 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -1194,7 +1194,14 @@ class AdVM extends BaseVM { for (var element in images) { imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); } + pickedPostingImages.addAll(imageModels); + // Added By Aamir + if (pickedPostingImages.length > GlobalConsts().maxFileCount) { + pickedPostingImages = pickedPostingImages.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } + if (pickedPostingImages.isNotEmpty) vehicleImageError = ""; notifyListeners(); } @@ -1237,7 +1244,13 @@ class AdVM extends BaseVM { vehicleDamageCards[index].partImages = imageModels; } else { vehicleDamageCards[index].partImages!.addAll(imageModels); +// Added By Aamir + if (vehicleDamageCards[index].partImages!.length > GlobalConsts().maxFileCount) { + vehicleDamageCards[index].partImages = vehicleDamageCards[index].partImages!.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } } + vehicleDamageCards[index].partImageErrorValue = ""; notifyListeners(); } @@ -1287,6 +1300,11 @@ class AdVM extends BaseVM { void pickMultipleDamageImages() async { List images = await commonServices.pickMultipleImages(); pickedDamageImages.addAll(images); + + if (pickedDamageImages.length > GlobalConsts().maxFileCount) { + pickedDamageImages = pickedDamageImages.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } if (pickedDamageImages.isNotEmpty) vehicleDamageImageError = ""; notifyListeners(); } diff --git a/lib/view_models/chat_view_model.dart b/lib/view_models/chat_view_model.dart index f558cf5..9ea2a21 100644 --- a/lib/view_models/chat_view_model.dart +++ b/lib/view_models/chat_view_model.dart @@ -406,6 +406,11 @@ class ChatVM extends BaseVM { imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); } pickedImagesForMessage.addAll(imageModels); + if (pickedImagesForMessage.length > GlobalConsts().maxFileCount) { + pickedImagesForMessage = pickedImagesForMessage.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } + notifyListeners(); } diff --git a/lib/view_models/requests_view_model.dart b/lib/view_models/requests_view_model.dart index 079cd9a..7df80f6 100644 --- a/lib/view_models/requests_view_model.dart +++ b/lib/view_models/requests_view_model.dart @@ -231,10 +231,17 @@ class RequestsVM extends BaseVM { imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); } pickedVehicleImages.addAll(imageModels); + if (pickedVehicleImages.length > GlobalConsts().maxFileCount) { + pickedVehicleImages = pickedVehicleImages.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } + if (pickedVehicleImages.isNotEmpty) vehicleImageError = ""; notifyListeners(); } + + bool isFetchingRequestType = false; bool isFetchingVehicleType = true; bool isFetchingVehicleDetail = false; diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index 1068494..933cc2c 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -132,6 +132,10 @@ class ServiceVM extends BaseVM { imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); } pickedBranchImages.addAll(imageModels); + if (pickedBranchImages.length > GlobalConsts().maxFileCount) { + pickedBranchImages = pickedBranchImages.sublist(0, GlobalConsts().maxFileCount); + Utils.showToast(LocaleKeys.maxFileSelection); + } if (pickedBranchImages.isNotEmpty) branchImageError = ""; notifyListeners(); } @@ -201,7 +205,6 @@ class ServiceVM extends BaseVM { } branchServicesFilterOptions[serviceStatusEnum.getIdFromServiceStatusEnum() - 1].isSelected = true; // -1 to match with the index - } // Future selectFile(BuildContext context, int index) async { @@ -264,11 +267,7 @@ class ServiceVM extends BaseVM { context, allowMultiple: false, ); - if (files != null && files.any((element) => - element.path - .split('.') - .last - .toLowerCase() != 'pdf')) { + if (files != null && files.any((element) => element.path.split('.').last.toLowerCase() != 'pdf')) { Utils.showToast("Only PDF Files are allowed"); return; } @@ -279,11 +278,11 @@ class ServiceVM extends BaseVM { isFromNetwork: false, )); } - documentID == 1 - ? commerceCertificates.addAll(imageModels) - : documentID == 2 - ? commercialCertificates.addAll(imageModels) - : vatCertificates.addAll(imageModels); + // documentID == 1 + // ? commerceCertificates.addAll(imageModels) + // : documentID == 2 + // ? commercialCertificates.addAll(imageModels) + // : vatCertificates.addAll(imageModels); document!.data![index].document = Utils.convertFileToBase64(files.first); document!.data![index].fileExt = Utils.checkFileExt(files.first.path); document!.data![index].documentUrl = files.first.path; @@ -459,10 +458,10 @@ class ServiceVM extends BaseVM { DropValue( element.id ?? 0, ((element.categoryName!.isEmpty - ? "N/A" - : countryCode == "SA" - ? element.categoryNameN - : element.categoryName) ?? + ? "N/A" + : countryCode == "SA" + ? element.categoryNameN + : element.categoryName) ?? "N/A"), "", ), @@ -657,9 +656,7 @@ class ServiceVM extends BaseVM { File file = File(imageModel.filePath!); List imageBytes = await file.readAsBytes(); String image = base64Encode(imageBytes); - String fileName = file.path - .split('/') - .last; + String fileName = file.path.split('/').last; branchPostingImages = BranchPostingImages( imageName: fileName, imageStr: image, diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index d06f1c6..6a2bd38 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -170,7 +170,7 @@ class UserVM extends BaseVM { } } - Future userDetailsUpdate(BuildContext context, String firstName, String lastName, String? city) async { + Future userDetailsUpdate(BuildContext context, String firstName, String lastName, String? city, String? cityName, String? countryName) async { Utils.showLoading(context); Map res = await userRepo.updateUserInfo(firstName, lastName, city); Utils.hideLoading(context); @@ -180,6 +180,13 @@ class UserVM extends BaseVM { if (localUser.data != null) { localUser.data!.userInfo!.firstName = res["data"]["firstName"]; localUser.data!.userInfo!.lastName = res["data"]["lastName"]; + localUser.data!.userInfo!.cityId = res["data"]["cityID"]; + localUser.data!.userInfo!.countryId = res["data"]["countryID"]; + if (cityName != null && countryName != null) { + localUser.data!.userInfo!.cityName = cityName; + localUser.data!.userInfo!.countryName = countryName; + } + // localUser.data!.userInfo!.cityId = res["data"]["cityId"]; AppState().setUser = localUser; } @@ -205,7 +212,15 @@ class UserVM extends BaseVM { if (Utils.passwordValidateStructure(password)) { if (password == confirmPassword) { Utils.showLoading(context); - RegisterUserRespModel user = await userRepo.basicComplete(userId ?? "", firstName, lastName, email, password, cityID, genderID, isNeedToPassToken: isNeedToPassToken); + RegisterUserRespModel user = await userRepo.basicComplete( + userId ?? "", + firstName, + lastName, + email, + password, + cityID, + genderID, + isNeedToPassToken: isNeedToPassToken); Utils.hideLoading(context); if (user.messageStatus == 1) { Utils.showToast(LocaleKeys.successfullyRegistered.tr()); @@ -253,8 +268,7 @@ class UserVM extends BaseVM { Utils.showToast(LocaleKeys.pleaseAcceptTerms.tr()); //("Please accept terms"); isValid = false; - } - else if (city == null) { + } else if (city == null) { Utils.showToast(LocaleKeys.cityNameMandatory.tr()); isValid = false; } else if (gender == null) { @@ -591,6 +605,8 @@ class UserVM extends BaseVM { } Future getAllCountriesForUser() async { + userCountries = null; + userCities = null; userCountries = await userRepo.getAllCountries(); notifyListeners(); } diff --git a/lib/views/setting_options/provider_license_page.dart b/lib/views/setting_options/provider_license_page.dart index 103cd26..d4501fc 100644 --- a/lib/views/setting_options/provider_license_page.dart +++ b/lib/views/setting_options/provider_license_page.dart @@ -19,6 +19,7 @@ import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_ import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/common_widgets/search_entity_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; @@ -35,6 +36,7 @@ class _ProviderLicensePageState extends State { late ServiceVM branchVM; bool showAttachment = false; String? attachedFile; + String? formattedDate; @override void initState() { @@ -50,7 +52,7 @@ class _ProviderLicensePageState extends State { if (model.document != null && model.document!.data != null && model.document!.data!.isNotEmpty) { for (var doc in model.document!.data!) { log("doc: ${doc.status}"); - if (doc.status == 4 || doc.status == 0) { + if (doc.status == DocumentStatusEnum.rejected || doc.status == DocumentStatusEnum.needUpload || doc.isAllowUpdate!) { isShow = true; } } @@ -162,6 +164,7 @@ class _ProviderLicensePageState extends State { padding: const EdgeInsets.symmetric(horizontal: 20), itemBuilder: (context, index) { DocumentData? document = serviceVM.document?.data![index]; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -172,40 +175,58 @@ class _ProviderLicensePageState extends State { (document!.documentName!).toText(fontSize: 16, letterSpacing: -0.56, fontWeight: MyFonts.SemiBold), if (document.statusText != null && document.statusText!.isNotEmpty) ...[ 10.width, - Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status ?? 1)), + Utils.statusContainerChip(text: document.statusText!.replaceFirst('OrActive', ''), chipColor: getColorByStatus(document.status!)), ], ], ), - // if (document.status != 1 && document.status != 3) ...[ - // Padding( - // padding: const EdgeInsets.only(top: 4, bottom: 8), - // child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor), - // ), - // TxtField( - // hint: LocaleKeys.description.tr(), - // maxLines: 3, - // isBackgroundEnabled: true, - // ), - // ], - 10.height, - if (isNeedToShow(model: serviceVM, document: document)) ...[ - PickedFilesContainer( - isReview: document.status != 0 && (document.status == 1 || document.status == 3), - allowAdButton: false, - pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document), - onCrossPressedPrimary: isNetworkImage(document: document) - ? serviceVM.removeNetworkImage - : document.documentId == 1 - ? serviceVM.commerceRemove - : document.documentId == 2 - ? serviceVM.commercialRemove - : serviceVM.vatRemove, + if (document.documentUrl != null) ...[ + BuildFilesContainer( + image: ImageModel(id: index, filePath: document.documentUrl!, isFromNetwork: document.isLocalFile! ? false : true), + onCrossPressedPrimary: (String val) { + document.documentUrl = null; + document.isLocalFile = false; + setState(() {}); + }, + index: index, + isReview: isReview(document), isPdf: true, - isFromNetwork: !(document.isLocalFile ?? false), - onAddFilePressed: () { - serviceVM.pickPdfReceiptFile(context, document.documentId!, index); + ), + 5.height, + ("${document.documentName} Expiry").toText(fontSize: 14, letterSpacing: -0.56, fontWeight: MyFonts.Medium), + 5.height, + TxtField( + isBackgroundEnabled: (document.status == DocumentStatusEnum.pending || document.status == DocumentStatusEnum.approvedOrActive && !document.isAllowUpdate!), + isNeedBorder: document.isAllowUpdate! ? true : false, + isSidePaddingZero: true, + + hint: LocaleKeys.expiryDate.tr(), + value: document.dateExpire != null && document.status == DocumentStatusEnum.pending || document.status == DocumentStatusEnum.approvedOrActive ? "${DateFormat('yyyy-MM-dd').format( + DateTime.parse(document.dateExpire!))}" : formattedDate == null + ? "" + : "${DateFormat('yyyy-MM-dd').format(DateTime.parse(document.dateExpire!))}", + isNeedClickAll: true, + postFixDataColor: MyColors.darkTextColor, + onTap: () async { + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.approvedOrActive || document.status == DocumentStatusEnum.needUpload || + document.status == DocumentStatusEnum.rejected) { + formattedDate = + await Utils.pickDateFromDatePicker(context, lastDate: DateTime(DateTime + .now() + .year + 3, DateTime + .now() + .month + 1, DateTime + .now() + .day), firstDate: DateTime.now()); + if (formattedDate!.isNotEmpty) { + document.dateExpire = formattedDate; + setState(() {}); + } + } + + // requestsVM.updateRequestedDate(formattedDate); }, ), + 10.height, buildCommentContainer(document: document), ] else ...[ @@ -215,107 +236,133 @@ class _ProviderLicensePageState extends State { text: LocaleKeys.attachPDF.tr(), icon: MyAssets.attachmentIcon.buildSvg(), ), - ], + ] ], ); }, ); } - List isLocalOrNetworkFiles({required ServiceVM model, required DocumentData document}) { - bool isNetworkImage = false; - - if (!document.isLocalFile!) { - isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; + bool isReview(DocumentData document) { + print(document.toJson()); + bool val = false; + if (document.isAllowUpdate == null) { + val = false; } - if (isNetworkImage) { - return [ImageModel(id: document.id, isFromNetwork: isNetworkImage, filePath: document.documentUrl)]; - } else if (document.documentId == 1) { - return model.commerceCertificates; - } else if (document.documentId == 2) { - return model.commercialCertificates; - } else { - return model.vatCertificates; + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.approvedOrActive) { + val = false; } - } - - bool isNeedToShow({required ServiceVM model, required DocumentData document}) { - bool allow = false; - bool isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty && !(document.isLocalFile ?? true); - if (isNetworkImage) { - allow = true; - } else { - if (document.documentId == 1 && model.commerceCertificates.isNotEmpty) { - allow = true; - } - if (document.documentId == 2 && model.commercialCertificates.isNotEmpty) { - allow = true; - } - if (document.documentId == 3 && model.vatCertificates.isNotEmpty) { - allow = true; - } + if (!document.isAllowUpdate! && document.status == DocumentStatusEnum.approvedOrActive) { + val = true; } - return allow; - } - - dynamic checkOnCrossPress({required ServiceVM model, required DocumentData document}) async { - bool isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; - if (isNetworkImage) { - return document.documentUrl; - } else { - if (document.documentId == 1) { - model.commerceRemove; - } - if (document.documentId == 2) { - model.commercialRemove; - } - if (document.documentId == 3) { - model.vatRemove; - } + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.pending) { + val = true; } - } - - bool isNetworkImage({required DocumentData document}) { - bool isNetworkImage = false; - if (!document.isLocalFile!) { - isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.rejected) { + val = false; + } + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.needUpload) { + val = true; } - return isNetworkImage; + if (document.isAllowUpdate! && document.status == DocumentStatusEnum.review) { + val = true; + } + + return val; } - Widget buildCommentContainer({required DocumentData document}) { - String comment = ""; - if (document.status == 4 && document.comment != null) { - comment = document.comment ?? ""; - } +// List isLocalOrNetworkFiles({required ServiceVM model, required DocumentData document}) { +// bool isNetworkImage = false; +// print(document); +// if (!document.isLocalFile!) { +// isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; +// } +// if (isNetworkImage) { +// return [ImageModel(id: document.id, isFromNetwork: isNetworkImage, filePath: document.documentUrl)]; +// } else { +// return [ImageModel(id: document.id, isFromNetwork: false, filePath: document.documentUrl)]; +// ; +// } +// } - if (comment.isEmpty) { - return const SizedBox(); - } - return Center(child: comment.toString().toText(color: MyColors.adCancelledStatusColor, fontSize: 14)).toContainer( - borderRadius: 8, - margin: const EdgeInsets.only(top: 10), - width: double.infinity, - backgroundColor: MyColors.adCancelledStatusColor.withOpacity(0.16), - ); +// bool isNeedToShow({required ServiceVM model, required DocumentData document}) { +// bool allow = false; +// bool isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty && !(document.isLocalFile ?? true); +// if (isNetworkImage) { +// allow = true; +// } else { +// if (document.documentId == 1 && document.documentUrl!.isNotEmpty) { +// allow = true; +// } +// if (document.documentId == 2 && document.documentUrl!.isNotEmpty) { +// allow = true; +// } +// if (document.documentId == 3 && document.documentUrl!.isNotEmpty) { +// allow = true; +// } +// } +// return allow; +// } +// +// dynamic checkOnCrossPress({required ServiceVM model, required DocumentData document}) async { +// bool isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; +// if (isNetworkImage) { +// print(document.documentUrl); +// return document.documentUrl; +// } + +//} else { +// if (document.documentId == 1) { +// model.commerceRemove; +// } +// if (document.documentId == 2) { +// model.commercialRemove; +// } +// if (document.documentId == 3) { +// model.vatRemove; +// } +// } +} + +bool isNetworkImage({required DocumentData document}) { + bool isNetworkImage = false; + if (!document.isLocalFile!) { + isNetworkImage = document.documentUrl != null && document.documentUrl!.isNotEmpty ? true : false; + } + return isNetworkImage; +} + +Widget buildCommentContainer({required DocumentData document}) { + String comment = ""; + if (document.status == 4 && document.comment != null) { + comment = document.comment ?? ""; } - Color getColorByStatus(int docStatus) { - switch (docStatus) { - case 1: - return MyColors.adPendingStatusColor; + if (comment.isEmpty) { + return const SizedBox(); + } + return Center(child: comment.toString().toText(color: MyColors.adCancelledStatusColor, fontSize: 14)).toContainer( + borderRadius: 8, + margin: const EdgeInsets.only(top: 10), + width: double.infinity, + backgroundColor: MyColors.adCancelledStatusColor.withOpacity(0.16), + ); +} - case 2: - return MyColors.adActiveStatusColor; +Color getColorByStatus(DocumentStatusEnum docStatus) { + switch (docStatus) { + case DocumentStatusEnum.pending: + return MyColors.adPendingStatusColor; - case 3: - return MyColors.greenColor; + case DocumentStatusEnum.approvedOrActive: + return MyColors.adActiveStatusColor; - case 4: - return MyColors.adCancelledStatusColor; + case DocumentStatusEnum.rejected: + return MyColors.adCancelledStatusColor; - default: - return MyColors.adPendingStatusColor; - } + case DocumentStatusEnum.needUpload: + return MyColors.adPendingStatusColor; + default: + return MyColors.adPendingStatusColor; } } diff --git a/lib/views/user/register_page.dart b/lib/views/user/register_page.dart index a5e9d20..feaa219 100644 --- a/lib/views/user/register_page.dart +++ b/lib/views/user/register_page.dart @@ -79,7 +79,6 @@ class _RegisterPageState extends State { DropdownField( dropdownValue: selectedDrop, (DropValue value) { - print("========"); selectedDrop = value; AppState().setUserRegisterCountrySelection = value; setState(() { diff --git a/lib/views/user/update_user_city_country.dart b/lib/views/user/update_user_city_country.dart index 5107c5c..f38f7bb 100644 --- a/lib/views/user/update_user_city_country.dart +++ b/lib/views/user/update_user_city_country.dart @@ -3,6 +3,7 @@ import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; +import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/user_view_model.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; @@ -26,10 +27,19 @@ class _UpdateUserCityCountryState extends State { @override void initState() { + print(AppState().getUser!.data!.userInfo!.toJson()); context.read().getAllCountriesForUser(); super.initState(); } + @override + void dispose() { + city = null; + country = null; + print(" Dispose Called"); + super.dispose(); + } + @override Widget build(BuildContext context) { return Consumer(builder: (BuildContext context, UserVM uVM, Widget? child) { @@ -41,50 +51,56 @@ class _UpdateUserCityCountryState extends State { children: [ uVM.userCountries != null ? Container( - padding: const EdgeInsets.only(right: 20, left: 20, top: 12), - child: Builder(builder: (context) { - List userCountryDrop = []; - for (var element in uVM.userCountries!.data!) { - if (AppState().getUser.data!.userInfo!.countryId == element.id) { - country = DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", ""); - } - userCountryDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); - } - return DropdownField( + padding: const EdgeInsets.only(right: 20, left: 20, top: 12), + child: Builder(builder: (context) { + List userCountryDrop = []; + for (var element in uVM.userCountries!.data!) { + var countryid = country == null ? AppState().getUser.data!.userInfo!.countryId : country!.id; + print("Country ID" + countryid.toString()); + if (countryid == element.id) { + print("Country Matched"); + country = DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", ""); + } + userCountryDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); + } + return DropdownField( (DropValue value) async { - country = value; - await uVM.getAllCitiesForUser(country!.id); - setState(() {}); - }, - list: userCountryDrop, - dropdownValue: country != null && country != -1 ? DropValue(country!.id, country!.value, "") : null, - hint: country != null && country != -1 ? country!.value : "${LocaleKeys.country.tr()} *", - // errorValue: adVM.vehicleCountryId.errorValue, - ); - })) + country = value; + city = null; + await uVM.getAllCitiesForUser(country!.id); + setState(() {}); + }, + list: userCountryDrop, + dropdownValue: country != null && country != -1 ? DropValue(country!.id, country!.value, "") : null, + hint: country != null && country != -1 ? country!.value : "${LocaleKeys.country.tr()} *", + // errorValue: adVM.vehicleCountryId.errorValue, + ); + })) : SizedBox(), - uVM.userCities != null + uVM.userCities != null && uVM.userCities!.data!.isNotEmpty ? Container( - padding: const EdgeInsets.only(right: 20, left: 20, top: 12), - child: Builder(builder: (context) { - List userCityDrop = []; - for (var element in uVM.userCities!.data!) { - if (AppState().getUser.data!.userInfo!.cityId == element.id) { - city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); - } - userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); - } - return DropdownField( + padding: const EdgeInsets.only(right: 20, left: 20, top: 12), + child: Builder(builder: (context) { + List userCityDrop = []; + for (var element in uVM.userCities!.data!) { + var cid = city == null ? AppState().getUser.data!.userInfo!.cityId : city!.id; + print("City ID" + cid.toString()); + if (cid == element.id) { + city = DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""); + } + userCityDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); + } + return DropdownField( (DropValue value) { - city = value; - setState(() {}); - }, - list: userCityDrop, - dropdownValue: city != null && city != -1 ? DropValue(city!.id, city!.value, "") : null, - hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", - // errorValue: adVM.vehicleCountryId.errorValue, - ); - })) + city = value; + setState(() {}); + }, + list: userCityDrop, + dropdownValue: city != null && city!.id != -1 ? DropValue(city!.id, city!.value, "") : null, + hint: city != null && city != -1 ? city!.value : "${LocaleKeys.city.tr()} *", + // errorValue: uVM.userCities!.data!.isEmpty ? "No Cities Found" : "", + ); + })) : SizedBox(), 20.height, Padding( @@ -93,7 +109,9 @@ class _UpdateUserCityCountryState extends State { title: LocaleKeys.confirm.tr(), maxWidth: double.infinity, onPressed: () async { - await uVM.userDetailsUpdate(context, AppState().getUser.data!.userInfo!.firstName!, AppState().getUser.data!.userInfo!.lastName!, city != null ? city?.id.toString() : null); + + await uVM.userDetailsUpdate( + context, AppState().getUser.data!.userInfo!.firstName!, AppState().getUser.data!.userInfo!.lastName!, city != null ? city?.id.toString() : null, city!.value, country!.value); }, ), ), diff --git a/lib/views/user/update_user_details.dart b/lib/views/user/update_user_details.dart index 4731bd2..1a51d29 100644 --- a/lib/views/user/update_user_details.dart +++ b/lib/views/user/update_user_details.dart @@ -1,3 +1,4 @@ +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; @@ -55,8 +56,7 @@ class _UpdateUserDetailsState extends State { title: LocaleKeys.confirm.tr(), maxWidth: double.infinity, onPressed: () async { - await userVM.userDetailsUpdate(context, firstname, lastname, null); - + await userVM.userDetailsUpdate(context, firstname, lastname, AppState().getUser.data!.userInfo!.cityId!.toString(), null, null); }, ), ],