From cef48cb1cba57c95be75ba02c9f21fb3a66791fc Mon Sep 17 00:00:00 2001 From: Aamir Date: Sun, 1 Dec 2024 14:52:41 +0300 Subject: [PATCH] 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); + + }, + ), + ], + ), + ), + ), + ); + } +}