From 4a8c27821cffaaec4bea7cf1085cb7d937f0729b Mon Sep 17 00:00:00 2001 From: devmirza121 Date: Thu, 21 Apr 2022 14:34:13 +0300 Subject: [PATCH] Issue's fixes --- assets/images/ic_world.png | Bin 0 -> 8960 bytes lib/api/api_client.dart | 24 ++- lib/api/client/branch_api_client.dart | 47 +++++- lib/api/client/user_api_client.dart | 37 +++-- lib/api/shared_prefrence.dart | 22 +++ lib/classes/consts.dart | 3 + lib/config/routes.dart | 10 +- lib/generated/codegen_loader.g.dart | 4 +- lib/main.dart | 3 +- lib/models/profile/branch.dart | 4 + lib/models/user/refresh_token.dart | 65 ++++++++ lib/models/user/user.dart | 10 +- lib/pages/dashboard/dashboard_page.dart | 41 +++-- lib/pages/settings/branch_detail_page.dart | 146 ++++++++++++++++++ lib/pages/settings/create_services_page.dart | 5 +- lib/pages/settings/dealership_page.dart | 2 +- lib/pages/settings/define_branch_page.dart | 117 ++++++++++---- lib/pages/settings/define_license_page.dart | 46 ++++-- lib/pages/user/complete_profile_page.dart | 3 +- lib/pages/user/edit_account_page.dart | 21 +-- lib/pages/user/forget_password_page.dart | 21 ++- .../user/login_method_selection_page.dart | 20 +-- lib/pages/user/login_verification_page.dart | 8 +- lib/pages/user/login_with_password_page.dart | 37 +++-- lib/pages/user/register_page.dart | 22 ++- lib/pages/user/splash_page.dart | 71 ++++++++- lib/services/shared_preferences.dart | 119 -------------- lib/utils/navigator.dart | 4 +- lib/widgets/dialog/otp_dialog.dart | 10 +- lib/widgets/dropdown/dropdow_field.dart | 17 +- lib/widgets/show_fill_button.dart | 11 +- lib/widgets/tab/login_email_tab.dart | 7 +- lib/widgets/txt_field.dart | 2 +- pubspec.lock | 9 +- resources/langs/ar-SA.json | 30 +++- resources/langs/en-US.json | 34 +++- 36 files changed, 751 insertions(+), 281 deletions(-) create mode 100644 assets/images/ic_world.png create mode 100644 lib/models/user/refresh_token.dart create mode 100644 lib/pages/settings/branch_detail_page.dart delete mode 100644 lib/services/shared_preferences.dart diff --git a/assets/images/ic_world.png b/assets/images/ic_world.png new file mode 100644 index 0000000000000000000000000000000000000000..01ea6343db1796648d08a5f0a9ee6b5c08053a59 GIT binary patch literal 8960 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 literal 0 HcmV?d00001 diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 173b262..19cb719 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:car_provider_app/api/client/user_api_client.dart'; +import 'package:car_provider_app/classes/app_state.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:http/io_client.dart'; @@ -72,6 +74,7 @@ class ApiClient { print("res121:" + response.statusCode.toString()); } var jsonData = jsonDecode(response.body); + return factoryConstructor(jsonData); } catch (ex) { print(ex); @@ -127,6 +130,12 @@ class ApiClient { print("res: " + response.body); } if (response.statusCode >= 200 && response.statusCode < 500) { + var jsonData = jsonDecode(response.body); + if (jsonData["StatusMessage"] != null && jsonData["StatusMessage"] == "Unauthorized user attempt to access API") { + String mToken = await UserApiClent().UpdateUserToken(); + return await _postForResponse(url, requestBody, token: mToken, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); + } + return response; } else { throw _throwAPIException(response); @@ -157,7 +166,7 @@ class ApiClient { } else { throw APIException(APIException.OTHER, arguments: e); } - }catch (ex) { + } catch (ex) { print("exception1:" + ex.toString()); throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex); } @@ -217,7 +226,10 @@ class ApiClient { } if (queryParameters != null) { String queryString = new Uri(queryParameters: queryParameters).query; - url = url + '?' + queryString.toString(); + if (!url.contains(queryString.toString())) { + url = url + '?' + queryString.toString(); + } + // if (isFirstCall) url = url + '?' + queryString.toString(); } if (!kReleaseMode) { @@ -225,11 +237,15 @@ class ApiClient { print("queryParameters:$queryParameters"); } var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60)); - if (!kReleaseMode) { print("res: " + response.body.toString()); } - if (response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 500) { + var jsonData = jsonDecode(response.body); + if (jsonData["StatusMessage"] != null && jsonData["StatusMessage"] == "Unauthorized user attempt to access API") { + String mToken = await UserApiClent().UpdateUserToken(); + return await _getForResponse(url, token: mToken, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); + } return response; } else { throw _throwAPIException(response); diff --git a/lib/api/client/branch_api_client.dart b/lib/api/client/branch_api_client.dart index a5521ba..6e4629a 100644 --- a/lib/api/client/branch_api_client.dart +++ b/lib/api/client/branch_api_client.dart @@ -24,7 +24,21 @@ class BranchApiClent { factory BranchApiClent() => _instance; + Future fetchBranch() async { + var postParams = { + "serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + }; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().getJsonForObject((json) => Branch.fromJson(json), ApiConsts.getProviderBranch, queryParameters: postParams, token: t); + } + Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async { + String lat = "0", long = "0"; + try { + lat = latitude.substring(0, 9); + long = longitude.substring(0, 9); + } catch (e) {} var postParams = { // "id": 0, "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", @@ -32,8 +46,8 @@ class BranchApiClent { "branchDescription": branchDescription, "cityID": cityId, "address": address, - "latitude": latitude.substring(0,9)??0, - "longitude": longitude.substring(0,9)??0, + "latitude": lat, + "longitude": long, "isActive": true }; String t = AppState().getUser.data!.accessToken ?? ""; @@ -41,6 +55,35 @@ class BranchApiClent { return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t); } + Future updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async { + String lat = "0", long = "0"; + try { + lat = latitude.substring(0, 9); + long = longitude.substring(0, 9); + } catch (e) {} + var postParams = { + "id": id, + "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", + "branchName": branchName, + "branchDescription": branchDescription, + "cityID": cityId, + "address": address, + "latitude": lat, + "longitude": long, + "isActive": isNeedToDelete + }; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); + } + + Future deleteBranch(int id) async { + var postParams = {"id": id, "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", "isActive": false}; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); + } + Future fetchAllBranches() async { var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; diff --git a/lib/api/client/user_api_client.dart b/lib/api/client/user_api_client.dart index 7975fc1..dbd4609 100644 --- a/lib/api/client/user_api_client.dart +++ b/lib/api/client/user_api_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:car_provider_app/models/user/change_email.dart'; import 'package:car_provider_app/models/user/change_mobile.dart'; import 'package:car_provider_app/models/user/cities.dart'; @@ -22,9 +23,10 @@ import 'package:car_provider_app/models/user/register_user.dart'; import '../../classes/app_state.dart'; import '../../models/m_response.dart'; +import '../../models/user/refresh_token.dart'; +import '../../models/user/user.dart'; import '../api_client.dart'; - - +import '../shared_prefrence.dart'; class UserApiClent { static final UserApiClent _instance = UserApiClent._internal(); @@ -49,9 +51,9 @@ class UserApiClent { Future basicComplete(String userId, String firstName, String lastName, String email, String password) async { var postParams; - if(email.isEmpty){ + if (email.isEmpty) { postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "companyName": "string", "isEmailVerified": true, "password": password}; - }else{ + } else { postParams = {"userID": userId, "firstName": firstName, "lastName": lastName, "email": email, "companyName": "string", "isEmailVerified": true, "password": password}; } @@ -108,7 +110,7 @@ class UserApiClent { Future ForgetPasswordOTPCompare(String userToken, String userOTP) async { var postParams = {"userToken": userToken, "userOTP": userOTP}; return await ApiClient().postJsonForResponse(ApiConsts.ForgetPasswordOTPCompare, postParams); - // return await ApiClient().postJsonForObject((json) => PasswordOTPCompare.fromJson(json), ApiConsts.ForgetPasswordOTPCompare, postParams); + // return await ApiClient().postJsonForObject((json) => PasswordOTPCompare.fromJson(json), ApiConsts.ForgetPasswordOTPCompare, postParams); } Future ForgetPassword(String userToken, String newPassword) async { @@ -130,7 +132,6 @@ class UserApiClent { String t = AppState().getUser.data!.accessToken ?? ""; print("tokeen " + t); return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ChangePassword, postParams, token: t); - } Future ChangeMobileNoOTPRequest( @@ -177,9 +178,7 @@ class UserApiClent { } Future EmailVerifyOTPVerify(String userToken, String userOTP) async { - var postParams = - {"userToken": userToken, - "userOTP": userOTP}; + var postParams = {"userToken": userToken, "userOTP": userOTP}; String t = AppState().getUser.data!.accessToken ?? ""; return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.EmailVerifyOTPVerify, postParams, token: t); @@ -202,4 +201,24 @@ class UserApiClent { print("tokeen " + t); return await ApiClient().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t); } + + Future RefreshTokenAPI(String token, String refreshToken) async { + var postParams = {"token": token, "refreshToken": refreshToken}; + // String t = AppState().getUser.data!.accessToken ?? ""; + return await ApiClient().postJsonForObject((json) => RefreshToken.fromJson(json), ApiConsts.RefreshToken, postParams); + } + + Future UpdateUserToken() async { + String token = await SharedPrefManager.getUserToken(); + String refreshToken = await SharedPrefManager.getRefreshToken(); + RefreshToken refresh = await RefreshTokenAPI(token, refreshToken); + SharedPrefManager.setUserToken(refresh.data!.accessToken ?? ""); + SharedPrefManager.setRefreshToken(refresh.data!.refreshToken ?? ""); + String mdata = await SharedPrefManager.getData(); + UserInfo info = UserInfo.fromJson(jsonDecode(mdata)); + User user = new User(); + user.data = new UserData(accessToken: refresh.data!.accessToken ?? "", refreshToken: refresh.data!.refreshToken ?? "", userInfo: info); + AppState().setUser = user; + return refresh.data!.accessToken??""; + } } diff --git a/lib/api/shared_prefrence.dart b/lib/api/shared_prefrence.dart index 77b3953..2e46e42 100644 --- a/lib/api/shared_prefrence.dart +++ b/lib/api/shared_prefrence.dart @@ -7,6 +7,8 @@ class SharedPrefManager { static String USER_TOKEN = "user.token"; static String USER_NAME = "user.name"; static String PASSWORD = "user.password"; + static String REFRESH_TOKEN = "user.refresh.token"; + static String DATA = "data"; static Future _prefs = SharedPreferences.getInstance(); @@ -49,4 +51,24 @@ class SharedPrefManager { SharedPreferences prefs = await _prefs; return prefs.getString(PASSWORD) ?? ""; } + + static setRefreshToken(String cookie) async { + final prefs = await SharedPreferences.getInstance(); + prefs.setString(REFRESH_TOKEN, cookie) ?? "NA"; + } + + static Future getRefreshToken() async { + SharedPreferences prefs = await _prefs; + return prefs.getString(REFRESH_TOKEN) ?? ""; + } + + static setData(String cookie) async { + final prefs = await SharedPreferences.getInstance(); + prefs.setString(DATA, cookie) ?? "NA"; + } + + static Future getData() async { + SharedPreferences prefs = await _prefs; + return prefs.getString(DATA) ?? ""; + } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index bda0cac..c4c3832 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -5,6 +5,7 @@ class ApiConsts { static String BasicOTP = baseUrlServices + "api/Register/BasicOTP"; static String BasicVerify = baseUrlServices + "api/Register/BasicVerify"; static String BasicComplete = baseUrlServices + "api/Register/BasicComplete"; + static String RefreshToken = baseUrlServices + "api/Account/RefreshToken"; //User @@ -36,7 +37,9 @@ class ApiConsts { static String ServiceProviderDocument_Update = baseUrlServices + "api/ServiceProviders/ServiceProviderDocument_Update"; //Branch + static String getProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Get"; static String createProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Create"; + static String updateProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Update"; static String ServiceProviderBranchGet = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Get"; static String ServiceCategory_Get = baseUrlServices + "api/Master/ServiceCategory_Get"; static String Services_Get = baseUrlServices + "api/ServiceProviders/Services_Get"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 302e12c..296f00c 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,5 +1,7 @@ +import 'package:car_provider_app/models/profile/branch.dart'; import 'package:car_provider_app/models/user/register_user.dart'; import 'package:car_provider_app/pages/dashboard/dashboard_page.dart'; +import 'package:car_provider_app/pages/settings/branch_detail_page.dart'; import 'package:car_provider_app/pages/settings/create_services_page.dart'; import 'package:car_provider_app/pages/settings/dealership_page.dart'; import 'package:car_provider_app/pages/settings/define_branch_page.dart'; @@ -52,6 +54,7 @@ class AppRoutes { //settings static final String dealershipSetting = "/dealershipSetting"; + static final String branch = "/branch"; static final String defineBranch = "/defineBranch"; static final String createServices = "/createServices"; @@ -77,14 +80,15 @@ class AppRoutes { changePassword: (context) => ChangePasswordPage(), forgetPasswordMethodPage: (context) => ForgetPasswordMethodPage(ModalRoute.of(context)!.settings.arguments as String), changeMobilePage: (context) => ChangeMobilePage(), - changeEmailPage : (context) => ChangeEmailPage(), - editAccoundPage : (context) => EditAccountPage(), + changeEmailPage: (context) => ChangeEmailPage(), + editAccoundPage: (context) => EditAccountPage(), //Home page dashboard: (context) => DashboardPage(), //setting dealershipSetting: (context) => DealershipPage(), - defineBranch: (context) => DefineBranchPage(), + branch: (context) => BranchDetailPage(), + defineBranch: (context) => DefineBranchPage(ModalRoute.of(context)!.settings.arguments as BranchData), createServices: (context) => CreateServicesPage(), }; } diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index e22918e..08efbb6 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -107,7 +107,7 @@ class CodegenLoader extends AssetLoader{ "completeProfile1": "اكمل الملف الشخصي 1/3", "completeProfile2": "اكمل الملف الشخصي 2/3", "completeProfile3": "اكمل الملف الشخصي 3/3", - "userInformation": "User Information", + "userInformation": "معلومات المتسخدم", "provider": "Provider", "title": "Hello", "msg": "Hello {} in the {} world ", @@ -233,7 +233,7 @@ static const Map en_US = { "update": "Update", "termsOfService": "By creating an account you agree to our Terms of Service and\n Privacy Policy", "branchInfo": "Branch Info and Services", - "profileCompleted": "Profile Completed", + "profileCompleted": "Profile is Completed", "selectLocationMap": "Select Location Map", "licensesAndCertifications": "licenses & certifications", "completeProfile1": "Complete Profile 1/3", diff --git a/lib/main.dart b/lib/main.dart index f84595c..3d4f454 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,8 @@ Future main() async { Locale('en', 'US') ], - fallbackLocale: Locale('ar', 'SA'), + fallbackLocale: Locale('en', 'US'), + // startLocale: Locale('ar', 'SA'), path: 'resources/langs', child: MyApp(), ), diff --git a/lib/models/profile/branch.dart b/lib/models/profile/branch.dart index cc7d68a..b401131 100644 --- a/lib/models/profile/branch.dart +++ b/lib/models/profile/branch.dart @@ -42,6 +42,7 @@ class BranchData { this.serviceProviderId, this.branchName, this.branchDescription, + this.countryID, this.cityId, this.address, this.latitude, @@ -53,17 +54,20 @@ class BranchData { int? serviceProviderId; String? branchName; String? branchDescription; + int? countryID; int? cityId; String? address; String? latitude; String? longitude; int? status; + factory BranchData.fromJson(Map json) => BranchData( id: json["id"] == null ? null : json["id"], serviceProviderId: json["serviceProviderID"] == null ? null : json["serviceProviderID"], branchName: json["branchName"] == null ? null : json["branchName"], branchDescription: json["branchDescription"] == null ? null : json["branchDescription"], + countryID: json["countryID"] == null ? null : json["countryID"], cityId: json["cityID"] == null ? null : json["cityID"], address: json["address"] == null ? null : json["address"], latitude: json["latitude"] == null ? null : json["latitude"], diff --git a/lib/models/user/refresh_token.dart b/lib/models/user/refresh_token.dart new file mode 100644 index 0000000..7de1e59 --- /dev/null +++ b/lib/models/user/refresh_token.dart @@ -0,0 +1,65 @@ +// To parse this JSON data, do +// +// final refreshToken = refreshTokenFromJson(jsonString); + +import 'dart:convert'; + +RefreshToken refreshTokenFromJson(String str) => RefreshToken.fromJson(json.decode(str)); + +String refreshTokenToJson(RefreshToken data) => json.encode(data.toJson()); + +class RefreshToken { + RefreshToken({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + final dynamic? totalItemsCount; + final RefreshData? data; + final int? messageStatus; + final String? message; + + factory RefreshToken.fromJson(Map json) => RefreshToken( + totalItemsCount: json["totalItemsCount"], + data: json["data"] == null ? null : RefreshData.fromJson(json["data"]), + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount, + "data": data == null ? null : data!.toJson(), + "messageStatus": messageStatus == null ? null : messageStatus, + "message": message == null ? null : message, + }; +} + +class RefreshData { + RefreshData({ + this.accessToken, + this.refreshToken, + this.expiryDate, + this.userInfo, + }); + + final String? accessToken; + final String? refreshToken; + final DateTime? expiryDate; + final dynamic? userInfo; + + factory RefreshData.fromJson(Map json) => RefreshData( + accessToken: json["accessToken"] == null ? null : json["accessToken"], + refreshToken: json["refreshToken"] == null ? null : json["refreshToken"], + expiryDate: json["expiryDate"] == null ? null : DateTime.parse(json["expiryDate"]), + userInfo: json["userInfo"], + ); + + Map toJson() => { + "accessToken": accessToken == null ? null : accessToken, + "refreshToken": refreshToken == null ? null : refreshToken, + "expiryDate": expiryDate == null ? null : expiryDate!.toIso8601String(), + "userInfo": userInfo, + }; +} diff --git a/lib/models/user/user.dart b/lib/models/user/user.dart index 46ff5b0..f1f0ee7 100644 --- a/lib/models/user/user.dart +++ b/lib/models/user/user.dart @@ -17,13 +17,13 @@ class User { }); dynamic totalItemsCount; - Data? data; + UserData? data; int? messageStatus; String? message; factory User.fromJson(Map json) => User( totalItemsCount: json["totalItemsCount"], - data: json["data"] == null ? null : Data.fromJson(json["data"]), + data: json["data"] == null ? null : UserData.fromJson(json["data"]), messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], message: json["message"] == null ? null : json["message"], ); @@ -36,8 +36,8 @@ class User { }; } -class Data { - Data({ +class UserData { + UserData({ this.accessToken, this.refreshToken, this.expiryDate, @@ -49,7 +49,7 @@ class Data { DateTime? expiryDate; UserInfo? userInfo; - factory Data.fromJson(Map json) => Data( + factory UserData.fromJson(Map json) => UserData( accessToken: json["accessToken"] == null ? null : json["accessToken"], refreshToken: json["refreshToken"] == null ? null : json["refreshToken"], expiryDate: json["expiryDate"] == null ? null : DateTime.parse(json["expiryDate"]), diff --git a/lib/pages/dashboard/dashboard_page.dart b/lib/pages/dashboard/dashboard_page.dart index c6d3eac..aefce54 100644 --- a/lib/pages/dashboard/dashboard_page.dart +++ b/lib/pages/dashboard/dashboard_page.dart @@ -15,12 +15,16 @@ import 'package:car_provider_app/widgets/show_fill_button.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; import 'package:car_provider_app/extensions/string_extensions.dart'; import 'package:car_provider_app/extensions/widget_extensions.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:http/http.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'dart:io'; +import '../../generated/locale_keys.g.dart'; + class DashboardPage extends StatefulWidget { @override State createState() => _DashboardPageState(); @@ -56,13 +60,13 @@ class _DashboardPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: appBar( - title: "Logo/Brand", + title: LocaleKeys.logo_brand.tr(), ), drawer: showDrawer(context), body: Container( child: Container( child: Center( - child: "Dashboard/Main Page".toText24(), + child: LocaleKeys.dashboard_main.tr().toText24(), ), ), ), @@ -156,12 +160,12 @@ class _DashboardPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ userName.toText24(), - "User role or title".toText12(), + AppState().getUser.data!.userInfo!.roleName!.toText12(), ], ), ), ShowFillButton( - title: "EDIT", + title: LocaleKeys.edit.tr(), onPressed: () { navigateWithName(context, AppRoutes.editAccoundPage); }, @@ -171,26 +175,41 @@ class _DashboardPageState extends State { ), ListTile( leading: SvgPicture.asset("assets/images/ic_notification.svg"), - title: "Notifications".toText12(), + title: LocaleKeys.notifications.tr().toText12(), ), ListTile( leading: SvgPicture.asset("assets/images/ic_settings.svg"), - title: "General".toText12(), + title: LocaleKeys.general.tr().toText12(), ), ListTile( leading: SvgPicture.asset("assets/images/ic_notes.svg"), - title: "Define Licenses".toText12(), + title: LocaleKeys.defineLicences.tr().toText12(), onTap: () { navigateWithName(context, AppRoutes.defineLicense); }, ), ListTile( leading: SvgPicture.asset("assets/images/ic_car.svg"), - title: "Dealership Settings".toText12(), + title: LocaleKeys.dealershipSettings.tr().toText12(), onTap: () { navigateWithName(context, AppRoutes.dealershipSetting); }, ), + ListTile( + leading: Image.asset( + "assets/images/ic_world.png", + width: 20, + height: 20, + color: Colors.blue, + ), + title: LocaleKeys.english.tr().toText12(), + onTap: () { + if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") + context.setLocale(const Locale("en", "US")); + else + context.setLocale(const Locale('ar', 'SA')); + }, + ), // ListTile( // leading: SvgPicture.asset("assets/images/ic_lock.svg"), // title: "Change Password".toText12(), @@ -214,8 +233,10 @@ class _DashboardPageState extends State { // ), ListTile( leading: SvgPicture.asset("assets/images/ic_logout.svg"), - title: "Sign Out".toText12(), - onTap: () { + title: LocaleKeys.signOut.tr().toText12(), + onTap: () async { + final pref = await SharedPreferences.getInstance(); + await pref.clear(); pop(context); pop(context); }, diff --git a/lib/pages/settings/branch_detail_page.dart b/lib/pages/settings/branch_detail_page.dart new file mode 100644 index 0000000..6b61a46 --- /dev/null +++ b/lib/pages/settings/branch_detail_page.dart @@ -0,0 +1,146 @@ +import 'package:car_provider_app/api/client/branch_api_client.dart'; +import 'package:car_provider_app/extensions/int_extensions.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../classes/utils.dart'; +import '../../config/routes.dart'; +import '../../generated/locale_keys.g.dart'; + +import '../../models/m_response.dart'; +import '../../models/profile/branch.dart'; +import '../../utils/navigator.dart'; +import '../../widgets/show_fill_button.dart'; + +class BranchDetailPage extends StatefulWidget { + @override + State createState() => _BranchDetailPageState(); +} + +class _BranchDetailPageState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + LocaleKeys.defineBranches.tr(), + ), + ), + body: Container( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + Expanded( + child: FutureBuilder( + future: BranchApiClent().fetchBranch(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return snapshot.data!.data!.length == 0 + ? Center(child: Text(LocaleKeys.no_branch.tr())) + : ListView.separated( + itemBuilder: (context, index) { + return Row( + children: [ + Container( + width: 44, + height: 44, + color: Colors.blue, + padding: EdgeInsets.all(6), + child: SvgPicture.asset( + "assets/icons/ic_branchs.svg", + color: Colors.white, + ), + ), + 12.width, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + snapshot.data!.data![index].branchName ?? "", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + 8.height, + Text( + snapshot.data!.data![index].address ?? "N/A", + style: TextStyle( + fontSize: 16, + ), + ), + ], + ), + ), + ShowFillButton( + title: LocaleKeys.edit.tr(), + fontSize: 12, + width: 50, + height: 30, + horizontalPadding: 8, + onPressed: () async { + await navigateWithName(context, AppRoutes.defineBranch, arguments: snapshot.data!.data![index]); + setState(() {}); + }, + ), + 12.width, + ShowFillButton( + title: LocaleKeys.remove.tr(), + fontSize: 12, + width: 50, + height: 30, + horizontalPadding: 8, + onPressed: () async { + Utils.showLoading(context); + MResponse res = + await BranchApiClent().updateBranch(snapshot.data!.data![index].id ?? 0, snapshot.data!.data![index].branchName??"", snapshot.data!.data![index].branchDescription??"", snapshot.data!.data![index].cityId.toString(), snapshot.data!.data![index].address??"", snapshot.data!.data![index].latitude.toString(), snapshot.data!.data![index].longitude.toString(),isNeedToDelete: false); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast(LocaleKeys.branch_deleted.tr()); + setState(() {}); + } else { + Utils.showToast(res.message ?? ""); + } + }, + ) + ], + ); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + itemCount: snapshot.data!.data!.length, + padding: EdgeInsets.all(12), + ); + } else { + return Center( + child: CircularProgressIndicator(), + ); + } + }, + )), + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: LocaleKeys.createBranch.tr(), + onPressed: () async { + await navigateWithName(context, AppRoutes.defineBranch, arguments: new BranchData()); + setState(() {}); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings/create_services_page.dart b/lib/pages/settings/create_services_page.dart index 37b7345..f8d072b 100644 --- a/lib/pages/settings/create_services_page.dart +++ b/lib/pages/settings/create_services_page.dart @@ -8,6 +8,7 @@ import 'package:car_provider_app/models/profile/services.dart'; import 'package:car_provider_app/models/user/country.dart'; import 'package:car_provider_app/widgets/dropdown/dropdow_field.dart'; import 'package:car_provider_app/widgets/show_fill_button.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; @@ -49,7 +50,7 @@ class _CreateServicesPageState extends State { category = await BranchApiClent().fetchBranchCategory(); setState(() { category!.data?.forEach((element) { - categoryDropList.add(new DropValue(element.id ?? 0, ((element.categoryName!.isEmpty ? "N/A" : element.categoryName) ?? "N/A"), "")); + categoryDropList.add(new DropValue(element.id ?? 0, ((element.categoryName!.isEmpty ? "N/A" :EasyLocalization.of(context)?.currentLocale?.countryCode == "SA"? element.categoryNameN:element.categoryName) ?? "N/A"), "")); }); }); } @@ -118,7 +119,7 @@ class _CreateServicesPageState extends State { }, ), 12.width, - (services!.data![index].description ?? "").toText12() + ((EasyLocalization.of(context)?.currentLocale?.countryCode == "SA"?services!.data![index].descriptionN:services!.data![index].description) ?? "").toText12() ], ), ); diff --git a/lib/pages/settings/dealership_page.dart b/lib/pages/settings/dealership_page.dart index 7a9447a..fb1795a 100644 --- a/lib/pages/settings/dealership_page.dart +++ b/lib/pages/settings/dealership_page.dart @@ -26,7 +26,7 @@ class DealershipPage extends StatelessWidget { leading: SvgPicture.asset("assets/icons/ic_branchs.svg"), title: LocaleKeys.defineBranches.tr().toText12(), onTap: () { - navigateWithName(context, AppRoutes.defineBranch); + navigateWithName(context, AppRoutes.branch); }, ), ListTile( diff --git a/lib/pages/settings/define_branch_page.dart b/lib/pages/settings/define_branch_page.dart index ab0b8f9..a43c3b0 100644 --- a/lib/pages/settings/define_branch_page.dart +++ b/lib/pages/settings/define_branch_page.dart @@ -3,6 +3,7 @@ import 'package:car_provider_app/api/client/user_api_client.dart'; import 'package:car_provider_app/classes/utils.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; import 'package:car_provider_app/models/m_response.dart'; +import 'package:car_provider_app/models/profile/branch.dart'; import 'package:car_provider_app/models/user/cities.dart'; import 'package:car_provider_app/models/user/country.dart'; import 'package:car_provider_app/pages/location/pick_location_page.dart'; @@ -10,9 +11,16 @@ import 'package:car_provider_app/utils/utils.dart'; import 'package:car_provider_app/widgets/dropdown/dropdow_field.dart'; import 'package:car_provider_app/widgets/show_fill_button.dart'; import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import '../../generated/locale_keys.g.dart'; + class DefineBranchPage extends StatefulWidget { + BranchData branchData; + + DefineBranchPage(this.branchData); + @override State createState() => _DefineBranchPageState(); } @@ -24,6 +32,8 @@ class _DefineBranchPageState extends State { List countryDropList = []; List citiesDropList = []; + DropValue? countryValue; + DropValue? cityValue; Country? country; Cities? cities; @@ -32,6 +42,7 @@ class _DefineBranchPageState extends State { void initState() { // TODO: implement initState super.initState(); + fetchCountry(); } @@ -39,8 +50,16 @@ class _DefineBranchPageState extends State { country = await UserApiClent().getAllCountries(); setState(() { country!.data?.forEach((element) { - countryDropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + if (widget.branchData.id != null) { + if (element.id == widget.branchData.countryID) { + countryValue = new DropValue( + element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? ""); + } + } + countryDropList.add( + new DropValue(element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "")); }); + if (widget.branchData.id != null) fetchCites(); }); } @@ -52,7 +71,21 @@ class _DefineBranchPageState extends State { cities = await UserApiClent().getAllCites(countryId.toString()); setState(() { cities!.data?.forEach((element) { - citiesDropList.add(new DropValue(element.id ?? 0, (element.cityName ?? ""), element.id.toString() ?? "")); + if (widget.branchData.id != null) { + if (element.id == widget.branchData.cityId) { + address = widget.branchData.address!; + branchName = widget.branchData.branchName!; + branchDescription = widget.branchData.branchDescription!; + latitude = double.parse(widget.branchData.latitude ?? ""); + longitude = double.parse(widget.branchData.longitude ?? ""); + countryId = widget.branchData.countryID!; + cityId = widget.branchData.cityId!; + cityValue = + new DropValue(element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? ""); + } + } + citiesDropList + .add(new DropValue(element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? "")); }); }); } @@ -62,7 +95,7 @@ class _DefineBranchPageState extends State { return Scaffold( appBar: AppBar( title: Text( - "Define Branch", + LocaleKeys.defineBranches.tr(), ), ), body: Container( @@ -77,32 +110,42 @@ class _DefineBranchPageState extends State { child: Column( children: [ country != null - ? DropdownField((DropValue value) { - setState(() { - countryCode = value.subValue; - countryId = value.id; - fetchCites(); - }); - }, list: countryDropList, hint: "Chosse Country") + ? DropdownField( + (DropValue value) { + setState(() { + countryCode = value.subValue; + countryId = value.id; + fetchCites(); + }); + }, + list: countryDropList, + dropdownValue: countryValue, + hint: LocaleKeys.chooseCountry.tr() + "*", + ) : CircularProgressIndicator(), 12.height, if (countryId != -1) cities != null ? citiesDropList.length == 0 - ? Text("No City Available for this country") - : DropdownField((DropValue value) { - setState(() { - // countryCode = value.subValue; - cityId = value.id; - }); - }, list: citiesDropList, hint: "Chosse City") + ? Text(LocaleKeys.no_city_available.tr()) + : DropdownField( + (DropValue value) { + setState(() { + // countryCode = value.subValue; + cityId = value.id; + }); + }, + list: citiesDropList, + dropdownValue: cityValue, + hint: LocaleKeys.chooseCity.tr() + "*", + ) : CircularProgressIndicator(), 12.height, if (cityId != -1) Column( children: [ TxtField( - hint: "Branch Name", + hint: LocaleKeys.branchName.tr() + "*", value: branchName, onChanged: (v) { branchName = v; @@ -110,7 +153,7 @@ class _DefineBranchPageState extends State { ), 12.height, TxtField( - hint: "Branch Description", + hint: LocaleKeys.branchDescription.tr() + "*", value: branchDescription, onChanged: (v) { branchDescription = v; @@ -118,15 +161,17 @@ class _DefineBranchPageState extends State { ), 12.height, TxtField( - hint: "Address", - isNeedClickAll: true, + hint: LocaleKeys.address.tr(), + isNeedClickAll: false, maxLines: 5, value: address, - // onChanged: (v) {}, + onChanged: (v) { + address = v; + }, ), 12.height, ShowFillButton( - title: "Pick Address", + title: LocaleKeys.pickAddress.tr(), onPressed: () { navigateTo( context, @@ -152,12 +197,28 @@ class _DefineBranchPageState extends State { Padding( padding: const EdgeInsets.all(12.0), child: ShowFillButton( - title: "Create Branch", + title: widget.branchData.id == null ? LocaleKeys.createBranch.tr() : LocaleKeys.updateBranch.tr(), onPressed: () async { - Utils.showLoading(context); - MResponse res = await BranchApiClent().createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); - Utils.hideLoading(context); - Utils.showToast(res.message ?? ""); + if (widget.branchData.id == null) { + Utils.showLoading(context); + MResponse res = await BranchApiClent().createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast(LocaleKeys.branch_created.tr()); + } else { + Utils.showToast(res.message ?? ""); + } + } else { + Utils.showLoading(context); + MResponse res = + await BranchApiClent().updateBranch(widget.branchData.id ?? 0, branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast(LocaleKeys.branch_updated.tr()); + } else { + Utils.showToast(res.message ?? ""); + } + } }, ), ), diff --git a/lib/pages/settings/define_license_page.dart b/lib/pages/settings/define_license_page.dart index 9407bf4..4b9e11b 100644 --- a/lib/pages/settings/define_license_page.dart +++ b/lib/pages/settings/define_license_page.dart @@ -8,10 +8,12 @@ import 'package:car_provider_app/models/profile/document.dart'; import 'package:car_provider_app/utils/utils.dart'; import 'package:car_provider_app/widgets/show_fill_button.dart'; import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; +import '../../generated/locale_keys.g.dart'; class DefineLicensePage extends StatefulWidget { @override @@ -37,7 +39,7 @@ class _DefineLicensePageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("Define Licenses"), + title: Text(LocaleKeys.defineLicences.tr()), ), body: Container( width: double.infinity, @@ -50,18 +52,18 @@ class _DefineLicensePageState extends State { Padding( padding: const EdgeInsets.all(12.0), child: ShowFillButton( - title: "Update", + title: LocaleKeys.update.tr(), width: double.infinity, onPressed: () { - Utils.showLoading(context); - ProfileApiClent().serviceProviderDocumentsUpdate(document!.data).then((value) { - Utils.hideLoading(context); - if (value.messageStatus == 1) { - Utils.showToast("Documents uploaded successfully"); + if (AppState().getUser.data!.userInfo!.roleId == 5) { + if (validation()) { + updateDocument(); } else { - Utils.showToast(value.message ?? ""); + Utils.showToast("All document's are mandatory for Dealership Provider"); } - }); + } else { + updateDocument(); + } }, ), ), @@ -71,10 +73,32 @@ class _DefineLicensePageState extends State { ); } + validation() { + bool valid = true; + document!.data!.forEach((element) { + if (element.documentUrl == null) { + valid = false; + } + }); + return valid; + } + + updateDocument() { + Utils.showLoading(context); + ProfileApiClent().serviceProviderDocumentsUpdate(document!.data).then((value) { + Utils.hideLoading(context); + if (value.messageStatus == 1) { + Utils.showToast("Documents uploaded successfully"); + } else { + Utils.showToast(value.message ?? ""); + } + }); + } + Widget showWidget() { if (document != null) { return document!.data!.length == 0 - ? Text("Something went wrong") + ? Text(LocaleKeys.somethingWrong.tr()) : ListView.separated( itemBuilder: (context, index) { return Column( @@ -85,7 +109,7 @@ class _DefineLicensePageState extends State { children: [ Flexible( child: TxtField( - hint: "Select Attachment", + hint: LocaleKeys.selectAttachment.tr(), value: document?.data![index].documentUrl ?? "", isNeedClickAll: true, maxLines: 2, diff --git a/lib/pages/user/complete_profile_page.dart b/lib/pages/user/complete_profile_page.dart index 50ba5b9..5e74840 100644 --- a/lib/pages/user/complete_profile_page.dart +++ b/lib/pages/user/complete_profile_page.dart @@ -1,7 +1,6 @@ import 'package:car_provider_app/api/client/user_api_client.dart'; import 'package:car_provider_app/classes/utils.dart'; import 'package:car_provider_app/config/routes.dart'; -import 'package:car_provider_app/generated/locale_keys.g.dart'; import 'package:car_provider_app/models/m_response.dart'; import 'package:car_provider_app/models/user/basic_otp.dart'; import 'package:car_provider_app/models/user/register_user.dart'; @@ -19,6 +18,8 @@ import 'package:car_provider_app/widgets/txt_field.dart'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; +import '../../generated/locale_keys.g.dart'; + class CompleteProfilePage extends StatefulWidget { RegisterUser user; diff --git a/lib/pages/user/edit_account_page.dart b/lib/pages/user/edit_account_page.dart index 178620b..4228d74 100644 --- a/lib/pages/user/edit_account_page.dart +++ b/lib/pages/user/edit_account_page.dart @@ -14,9 +14,12 @@ import 'package:car_provider_app/widgets/app_bar.dart'; import 'package:car_provider_app/widgets/dialog/dialogs.dart'; import 'package:car_provider_app/widgets/dialog/message_dialog.dart'; import 'package:car_provider_app/widgets/dialog/otp_dialog.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import '../../generated/locale_keys.g.dart'; + class EditAccountPage extends StatefulWidget { @override State createState() => _EditAccountPageState(); @@ -29,7 +32,7 @@ class _EditAccountPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: appBar(title: "Edit Account"), + appBar: appBar(title: LocaleKeys.editAccount.tr()), body: Container( width: double.infinity, height: double.infinity, @@ -39,7 +42,7 @@ class _EditAccountPageState extends State { 20.height, ListTile( leading: SvgPicture.asset("assets/images/ic_lock.svg"), - title: "Change Password".toText12(), + title: LocaleKeys.changePassword.tr().toText12(), onTap: () { navigateWithName(context, AppRoutes.changePassword); }, @@ -49,14 +52,14 @@ class _EditAccountPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ SvgPicture.asset("assets/images/ic_mobile.svg"), - "Change Mobile".toText12(), - "Verify".toText12(), + LocaleKeys.changeMobile.tr().toText12(), + LocaleKeys.verify.tr().toText12(), RaisedButton( onPressed: () { navigateWithName(context, AppRoutes.changeMobilePage); }, child: Text( - "Change", + LocaleKeys.change.tr(), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -75,9 +78,9 @@ class _EditAccountPageState extends State { Icons.email, color: Colors.blue, ), - "Change Email".toText12(), + LocaleKeys.changeEmail.tr().toText12(), InkWell( - child: ((AppState().getUser.data!.userInfo!.isEmailVerified ?? false) ? "Verified" : "Verify").toText12(), + child: ((AppState().getUser.data!.userInfo!.isEmailVerified ?? false) ? LocaleKeys.verified.tr() : LocaleKeys.verify.tr()).toText12(), onTap: (AppState().getUser.data!.userInfo!.isEmailVerified ?? false) ? null : () { @@ -89,7 +92,7 @@ class _EditAccountPageState extends State { navigateWithName(context, AppRoutes.changeEmailPage); }, child: Text( - "Change", + LocaleKeys.change.tr(), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -135,7 +138,7 @@ class _EditAccountPageState extends State { if (otpCompare.messageStatus == 1) { AppState().getUser.data!.userInfo!.isEmailVerified = true; setState(() {}); - Utils.showToast("Email is verified successfully"); + Utils.showToast(LocaleKeys.emailVerified.tr()); // Navigator.of(context).pushNamedAndRemoveUntil(AppRoutes.dashboard, (Route route) => false); // showMDialog( // context, diff --git a/lib/pages/user/forget_password_page.dart b/lib/pages/user/forget_password_page.dart index 438cb50..f30e18c 100644 --- a/lib/pages/user/forget_password_page.dart +++ b/lib/pages/user/forget_password_page.dart @@ -19,12 +19,14 @@ import 'package:car_provider_app/extensions/string_extensions.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; import 'package:car_provider_app/extensions/widget_extensions.dart'; import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:car_provider_app/models/user/user.dart'; import 'dart:convert'; import 'package:http/http.dart'; +import '../../generated/locale_keys.g.dart'; import '../../models/user/country.dart'; import '../../widgets/dropdown/dropdow_field.dart'; import '../../widgets/tab/login_email_tab.dart'; @@ -57,7 +59,7 @@ class _ForgetPasswordPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: appBar(title: "Change Password"), + appBar: appBar(title: LocaleKeys.changePassword.tr()), body: Container( width: double.infinity, height: double.infinity, @@ -73,7 +75,7 @@ class _ForgetPasswordPageState extends State { }, ), 50.height, - "Retrieve Password".toText24(), + LocaleKeys.retrievePassword.tr().toText24(), 12.height, type == ClassType.NUMBER ? Column(children: [ getCountry(), @@ -85,7 +87,7 @@ class _ForgetPasswordPageState extends State { }, ) ],) : TxtField( - hint: "Email Address", + hint: LocaleKeys.emailAddress.tr(), value: userName, onChanged: (v) { userName = v; @@ -93,7 +95,7 @@ class _ForgetPasswordPageState extends State { ), 50.height, ShowFillButton( - title: "Continue", + title: LocaleKeys.continu.tr(), width: double.infinity, onPressed: () { if (userName.isNum() && type==ClassType.NUMBER) { @@ -114,13 +116,18 @@ class _ForgetPasswordPageState extends State { if (_country != null) { List dropList = []; _country!.data?.forEach((element) { - dropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + dropList.add(new DropValue( + element.id ?? 0, + EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" + ? ((element.countryNameN ?? "") + " " + (element.countryCode ?? "")) + : (element.countryName ?? "") + " " + (element.countryCode ?? ""), + element.countryCode ?? "")); }); return Padding( padding: const EdgeInsets.all(2.0), child: DropdownField((DropValue value) { countryCode = value.subValue; - }, list: dropList, hint: "Chose Country"), + }, list: dropList, hint: LocaleKeys.chooseCountry.tr()), ); } else { return Center( @@ -148,7 +155,7 @@ class _ForgetPasswordPageState extends State { Utils.hideLoading(context); PasswordOTPRequest otpRequest = PasswordOTPRequest.fromJson(jsonDecode(response.body)); if (otpRequest.messageStatus == 1) { - Utils.showToast("Code is sent to email"); + Utils.showToast(LocaleKeys.codeSentToEmail.tr()); showMDialog(context, child: OtpDialog( onClick: (String code) async { pop(context); diff --git a/lib/pages/user/login_method_selection_page.dart b/lib/pages/user/login_method_selection_page.dart index fc05ccb..c9ab7fc 100644 --- a/lib/pages/user/login_method_selection_page.dart +++ b/lib/pages/user/login_method_selection_page.dart @@ -49,7 +49,7 @@ class LoginMethodSelectionPage extends StatelessWidget { onClick: () { performBasicOtp(context); }, - title: 'Finger Print', + title: LocaleKeys.fingerPrint.tr(), icon: icons + "ic_fingerprint.png", ), ), @@ -59,7 +59,7 @@ class LoginMethodSelectionPage extends StatelessWidget { onClick: () { performBasicOtp(context); }, - title: 'Face Recognition', + title: LocaleKeys.faceRecognition.tr(), icon: icons + "ic_face_id.png", ), ), @@ -73,7 +73,7 @@ class LoginMethodSelectionPage extends StatelessWidget { onClick: () { performBasicOtp(context); }, - title: 'With SMS', + title: LocaleKeys.SMS.tr(), icon: icons + "ic_sms.png", ), ), @@ -84,7 +84,7 @@ class LoginMethodSelectionPage extends StatelessWidget { // navigateWithName(context, AppRoutes.dashboard); performBasicOtp(context); }, - title: 'With Whatsapp', + title: LocaleKeys.whatsapp.tr(), icon: icons + "ic_whatsapp.png", ), ), @@ -107,24 +107,24 @@ class LoginMethodSelectionPage extends StatelessWidget { onClick: (String code) async { pop(context); Utils.showLoading(context); - Response response2 = await UserApiClent().login_V2_OTPVerify(user.data!.userToken??"", code); + Response response2 = await UserApiClent().login_V2_OTPVerify(user.data!.userToken ?? "", code); Utils.hideLoading(context); RegisterUser verifiedUser = RegisterUser.fromJson(jsonDecode(response2.body)); if (verifiedUser.messageStatus == 1) { User user = User.fromJson(jsonDecode(response2.body)); - if(user.data!.userInfo!.roleId==5||user.data!.userInfo!.roleId==6){ - + if (user.data!.userInfo!.roleId == 5 || user.data!.userInfo!.roleId == 6) { AppState().setUser = user; SharedPrefManager.setUserToken(user.data!.accessToken ?? ""); SharedPrefManager.setUserId(user.data!.userInfo!.userId ?? ""); + SharedPrefManager.setRefreshToken(user.data!.refreshToken ?? ""); + SharedPrefManager.setData(jsonEncode(user.data!.userInfo!.toJson())); navigateReplaceWithName(context, AppRoutes.dashboard); - }else{ + } else { Utils.showToast("Sorry, Only Provider's can log in this app"); } - } else { - Utils.showToast(verifiedUser.message??""); + Utils.showToast(verifiedUser.message ?? ""); } }, )); diff --git a/lib/pages/user/login_verification_page.dart b/lib/pages/user/login_verification_page.dart index 389f203..abb1d64 100644 --- a/lib/pages/user/login_verification_page.dart +++ b/lib/pages/user/login_verification_page.dart @@ -104,7 +104,7 @@ class _LoginVerificationPageState extends State { onClick: () { performBasicOtp(context, userToken); }, - title: 'Finger Print', + title: LocaleKeys.fingerPrint.tr(), icon: icons + "ic_fingerprint.png", ), ), @@ -114,7 +114,7 @@ class _LoginVerificationPageState extends State { onClick: () { performBasicOtp(context, userToken); }, - title: 'Face Recognition', + title: LocaleKeys.faceRecognition.tr(), icon: icons + "ic_face_id.png", ), ), @@ -128,7 +128,7 @@ class _LoginVerificationPageState extends State { onClick: () { performBasicOtp(context, userToken); }, - title: 'With SMS', + title: LocaleKeys.SMS.tr(), icon: icons + "ic_sms.png", ), ), @@ -138,7 +138,7 @@ class _LoginVerificationPageState extends State { onClick: () { performBasicOtp(context, userToken); }, - title: 'With Whatsapp', + title: LocaleKeys.whatsapp.tr(), icon: icons + "ic_whatsapp.png", ), ), diff --git a/lib/pages/user/login_with_password_page.dart b/lib/pages/user/login_with_password_page.dart index a8a2cca..f12110a 100644 --- a/lib/pages/user/login_with_password_page.dart +++ b/lib/pages/user/login_with_password_page.dart @@ -21,9 +21,11 @@ import 'package:car_provider_app/extensions/widget_extensions.dart'; import 'package:car_provider_app/widgets/show_fill_button.dart'; import 'package:car_provider_app/widgets/tab/login_email_tab.dart'; import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import '../../generated/locale_keys.g.dart'; import '../../models/user/country.dart'; import '../../widgets/dropdown/dropdow_field.dart'; @@ -55,7 +57,7 @@ class _LoginWithPasswordState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: appBar(title: "Log In"), + appBar: appBar(title: LocaleKeys.login.tr()), body: Container( width: double.infinity, height: double.infinity, @@ -70,15 +72,14 @@ class _LoginWithPasswordState extends State { }, ), 50.height, - (type == ClassType.NUMBER ? "Enter Phone" : "Enter Email").toText24(), + (type == ClassType.NUMBER ? LocaleKeys.enterPhoneNumber.tr() : LocaleKeys.enterEmail.tr()).toText24(), mFlex(1), Column( children: [ - if (type == ClassType.NUMBER) - getCountry(), + if (type == ClassType.NUMBER) getCountry(context), 6.height, TxtField( - hint: type == ClassType.NUMBER ? "5********" : "Enter Email", + hint: type == ClassType.NUMBER ? LocaleKeys.enterPhoneNumber.tr() : LocaleKeys.enterEmail.tr(), value: phoneNum, onChanged: (v) { phoneNum = v; @@ -86,7 +87,7 @@ class _LoginWithPasswordState extends State { ), 6.height, TxtField( - hint: "Enter Password?", + hint: LocaleKeys.EnterPass.tr(), value: password, isPasswordEnabled: true, maxLines: 1, @@ -100,14 +101,14 @@ class _LoginWithPasswordState extends State { Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - "Forget Password?".toText12(color: Colors.blue).onPress(() { + LocaleKeys.forgetPassword.tr().toText12(color: Colors.blue).onPress(() { navigateWithName(context, AppRoutes.forgetPassword); }), ], ), 50.height, ShowFillButton( - title: "Log In", + title: LocaleKeys.login.tr(), width: double.infinity, onPressed: () { performBasicOtp(context); @@ -120,17 +121,26 @@ class _LoginWithPasswordState extends State { ); } - Widget getCountry() { + Widget getCountry(BuildContext context) { if (_country != null) { List dropList = []; _country!.data?.forEach((element) { - dropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + dropList.add(new DropValue( + element.id ?? 0, + EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" + ? ((element.countryNameN ?? "") + " " + (element.countryCode ?? "")) + : (element.countryName ?? "") + " " + (element.countryCode ?? ""), + element.countryCode ?? "")); }); return Padding( padding: const EdgeInsets.all(2.0), - child: DropdownField((DropValue value) { - countryCode = value.subValue; - }, list: dropList, hint: "Chose Country"), + child: DropdownField( + (DropValue value) { + countryCode = value.subValue; + }, + list: dropList, + hint: LocaleKeys.chooseCountry.tr(), + ), ); } else { return Center( @@ -152,5 +162,4 @@ class _LoginWithPasswordState extends State { Utils.showToast(user.message ?? ""); } } - } diff --git a/lib/pages/user/register_page.dart b/lib/pages/user/register_page.dart index ee22e6c..5b37b67 100644 --- a/lib/pages/user/register_page.dart +++ b/lib/pages/user/register_page.dart @@ -18,8 +18,11 @@ import 'package:car_provider_app/extensions/int_extensions.dart'; import 'package:car_provider_app/extensions/string_extensions.dart'; import 'package:car_provider_app/extensions/widget_extensions.dart'; import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import '../../generated/locale_keys.g.dart'; + class RegisterPage extends StatelessWidget { String phoneNum = "", countryCode = ""; int role = -1, countryId = -1; @@ -27,14 +30,14 @@ class RegisterPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: appBar(title: "Sign Up"), + appBar: appBar(title: LocaleKeys.signUp.tr()), body: Container( width: double.infinity, height: double.infinity, padding: EdgeInsets.all(40), child: Column( children: [ - "Enter Phone Number".toText24(), + LocaleKeys.enterPhoneNumber.tr().toText24(), 12.height, FutureBuilder( future: UserApiClent().getRoles(), @@ -42,11 +45,11 @@ class RegisterPage extends StatelessWidget { if (snapshot.hasData) { List dropList = []; snapshot.data?.data?.forEach((element) { - dropList.add(new DropValue(element.id ?? 0, element.roleName ?? "", "")); + dropList.add(new DropValue(element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? element.roleNameN ?? "" : element.roleName ?? "", "")); }); return DropdownField((DropValue value) { role = value.id; - }, list: dropList, hint: "Chosse Role"); + }, list: dropList, hint: LocaleKeys.selectRole.tr()); } else { return CircularProgressIndicator(); } @@ -59,12 +62,17 @@ class RegisterPage extends StatelessWidget { if (snapshot.hasData) { List dropList = []; snapshot.data?.data?.forEach((element) { - dropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + dropList.add(new DropValue( + element.id ?? 0, + EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" + ? (element.countryNameN ?? "") + " " + (element.countryCode ?? "") + : (element.countryName ?? "") + " " + (element.countryCode ?? ""), + element.countryCode ?? "")); }); return DropdownField((DropValue value) { countryCode = value.subValue; countryId = value.id; - }, list: dropList, hint: "Chose Country"); + }, list: dropList, hint: LocaleKeys.chooseCountry.tr()); } else { return CircularProgressIndicator(); } @@ -78,7 +86,7 @@ class RegisterPage extends StatelessWidget { ), 50.height, ShowFillButton( - title: "Continue", + title: LocaleKeys.continu.tr(), width: double.infinity, onPressed: () { if (validation()) performBasicOtp(context); diff --git a/lib/pages/user/splash_page.dart b/lib/pages/user/splash_page.dart index 3dc39f7..1aff79a 100644 --- a/lib/pages/user/splash_page.dart +++ b/lib/pages/user/splash_page.dart @@ -1,14 +1,24 @@ import 'dart:async'; +import 'dart:convert'; import 'package:car_provider_app/config/routes.dart'; +import 'package:car_provider_app/extensions/int_extensions.dart'; import 'package:car_provider_app/extensions/string_extensions.dart'; import 'package:car_provider_app/generated/locale_keys.g.dart'; import 'package:car_provider_app/utils/navigator.dart'; import 'package:car_provider_app/utils/utils.dart'; import 'package:car_provider_app/extensions/widget_extensions.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; +import '../../api/client/user_api_client.dart'; +import '../../api/shared_prefrence.dart'; +import '../../classes/app_state.dart'; +import '../../classes/utils.dart'; +import '../../models/user/refresh_token.dart'; +import '../../models/user/user.dart'; + class SplashPage extends StatelessWidget { @override Widget build(BuildContext context) { @@ -21,13 +31,62 @@ class SplashPage extends StatelessWidget { mFlex(5), "Logo".toText(fontSize: 45, isBold: true), mFlex(3), - LocaleKeys.firstTimeLogIn.tr().toText(fontSize: 18, isBold: true).onPress(() { - navigateWithName(context, AppRoutes.registerSelection); - }), + LocaleKeys.firstTimeLogIn.tr().toText(fontSize: 18, isBold: true).onPress( + () { + navigateWithName(context, AppRoutes.registerSelection); + }, + ), mFlex(1), - LocaleKeys.alreadySigned.tr().toText(fontSize: 18, isBold: true).onPress(() { - navigateWithName(context, AppRoutes.loginVerification); - }), + LocaleKeys.alreadySigned.tr().toText(fontSize: 18, isBold: true).onPress( + () async { + String token = await SharedPrefManager.getUserToken(); + String refreshToken = await SharedPrefManager.getRefreshToken(); + if(token.isNotEmpty){ + Utils.showLoading(context); + RefreshToken refresh = await UserApiClent().RefreshTokenAPI(token, refreshToken); + Utils.hideLoading(context); + if (refresh.messageStatus == 1) { + SharedPrefManager.setUserToken(refresh.data!.accessToken ?? ""); + SharedPrefManager.setRefreshToken(refresh.data!.refreshToken ?? ""); + String mdata = await SharedPrefManager.getData(); + print(mdata); + UserInfo info = UserInfo.fromJson(jsonDecode(mdata)); + User user = new User(); + user.data = new UserData(accessToken: refresh.data!.accessToken ?? "", refreshToken: refresh.data!.refreshToken ?? "", userInfo: info); + AppState().setUser = user; + print(AppState().getUser.data?.userInfo?.roleName); + navigateWithName(context, AppRoutes.dashboard); + } else { + String accessToken = await SharedPrefManager.getUserToken(); + String refreshToken = await SharedPrefManager.getRefreshToken(); + String mdata = await SharedPrefManager.getData(); + UserInfo info = UserInfo.fromJson(jsonDecode(mdata)); + User user = new User(); + user.data = new UserData(accessToken: accessToken, refreshToken: refreshToken, userInfo: info); + AppState().setUser = user; + print(AppState().getUser.data?.userInfo?.roleName); + navigateWithName(context, AppRoutes.dashboard); + } + }else{ + Utils.showToast(LocaleKeys.login_once.tr()); + } + }, + ), + 35.height, + TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.white, + ), + onPressed: () { + if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") + context.setLocale(const Locale("en", "US")); + else + context.setLocale(const Locale('ar', 'SA')); + }, + child: Text( + LocaleKeys.english.tr(), + ), + ), mFlex(5), ], ), diff --git a/lib/services/shared_preferences.dart b/lib/services/shared_preferences.dart deleted file mode 100644 index dd02cd1..0000000 --- a/lib/services/shared_preferences.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'dart:convert'; - -import 'package:car_provider_app/models/config_model.dart'; - -import 'package:shared_preferences/shared_preferences.dart' -as SharedPrefsPlugin; - -/// -/// Taken from AlarmGuide Project -/// - -abstract class ISharedPreferences { - Future get authState; - - Future setAuthState(int authState); - - Future get configState; - - Future setConfigState(int confState); - - Future get config; - - Future setConfig(ConfigModel config); - - Future get promotionNotificationsEnabled; - - Future setPromotionNotificationEnabled(bool newSetting); - - Future get helpAlreadyShown; - - Future setHelpAlreadyShown(); - - Future get useS3; - - Future setUseS3(int value); -} - -class SharedPreferences implements ISharedPreferences { - static const String _AUTH_STATE_KEY = "auth_key"; - static const String _CONFIG_KEY = "config"; - static const String _CONFIG_STATE_KEY = "config_key"; - static const String _PROMOTION_NOTIFICATION_KEY = "promotion"; - static const String _HELP_ALREADY_SHOWN = "help_shown"; - static const String _USE_S3 = "s3"; - - @override - Future get authState async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - return sharedPrefs.getInt(_AUTH_STATE_KEY); - } - - @override - Future setAuthState(int authState) async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setInt(_AUTH_STATE_KEY, authState); - } - - @override - Future get config async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - final configAsJson = sharedPrefs.getString(_CONFIG_KEY); - return ConfigModel.fromJson(jsonDecode(configAsJson!)); - } - - @override - Future setConfig(ConfigModel config) async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setString(_CONFIG_KEY, jsonEncode(config)); - setConfigState(1); - } - - @override - Future get promotionNotificationsEnabled async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - return sharedPrefs.getBool(_PROMOTION_NOTIFICATION_KEY); - } - - @override - Future setPromotionNotificationEnabled(bool newSetting) async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setBool(_PROMOTION_NOTIFICATION_KEY, newSetting); - } - - @override - Future get helpAlreadyShown async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - return sharedPrefs.getBool(_HELP_ALREADY_SHOWN); - } - - @override - Future setHelpAlreadyShown() async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setBool(_HELP_ALREADY_SHOWN, true); - } - - @override - Future get configState async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - return sharedPrefs.getInt(_CONFIG_STATE_KEY); - } - - @override - Future setConfigState(int confState) async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setInt(_CONFIG_STATE_KEY, confState); - } - - @override - Future setUseS3(int value) async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - sharedPrefs.setInt(_USE_S3, value); - } - - @override - Future get useS3 async { - final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); - return sharedPrefs.getInt(_USE_S3); - } -} diff --git a/lib/utils/navigator.dart b/lib/utils/navigator.dart index fde5619..d2f6f41 100644 --- a/lib/utils/navigator.dart +++ b/lib/utils/navigator.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -navigateWithName(BuildContext context, String routeName, {Object? arguments}) { - Navigator.pushNamed(context, routeName, arguments: arguments); +Future navigateWithName(BuildContext context, String routeName, {Object? arguments}) { + return Navigator.pushNamed(context, routeName, arguments: arguments); } navigateReplaceWithName(BuildContext context, String routeName, {Object? arguments}) { diff --git a/lib/widgets/dialog/otp_dialog.dart b/lib/widgets/dialog/otp_dialog.dart index 1cb2043..a5ccc63 100644 --- a/lib/widgets/dialog/otp_dialog.dart +++ b/lib/widgets/dialog/otp_dialog.dart @@ -5,8 +5,10 @@ import 'package:car_provider_app/utils/utils.dart'; import 'package:car_provider_app/widgets/show_fill_button.dart'; import 'package:car_provider_app/extensions/string_extensions.dart'; import 'package:car_provider_app/extensions/int_extensions.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import '../../generated/locale_keys.g.dart'; import '../count_down_timer.dart'; import '../otp_widget.dart'; @@ -35,7 +37,7 @@ class _OtpDialogState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Please insert OTP Code".toText24(), + LocaleKeys.insert_otp_code.tr().toText24(), 20.height, Center( child: OTPWidget( @@ -97,7 +99,7 @@ class _OtpDialogState extends State { child: Row( children: [ Expanded( - child: Text("Time will expire in"), + child: Text(LocaleKeys.time_will_expire.tr()), ), CountDownTimer( secondsRemaining: 60, @@ -127,7 +129,7 @@ class _OtpDialogState extends State { child: Padding( padding: const EdgeInsets.all(12.0), child: Text( - "Resend Code", + LocaleKeys.resend_code.tr(), style: TextStyle( decoration: TextDecoration.underline, fontWeight: FontWeight.bold, @@ -139,7 +141,7 @@ class _OtpDialogState extends State { ), 40.height, ShowFillButton( - title: "Check Code", + title: LocaleKeys.check_code.tr(), width: double.infinity, onPressed: () { widget.onClick(code); diff --git a/lib/widgets/dropdown/dropdow_field.dart b/lib/widgets/dropdown/dropdow_field.dart index 0aa6239..4ab9775 100644 --- a/lib/widgets/dropdown/dropdow_field.dart +++ b/lib/widgets/dropdown/dropdow_field.dart @@ -8,15 +8,18 @@ class DropValue { String value; String subValue; - DropValue(this.id, this.value,this.subValue); + DropValue(this.id, this.value, this.subValue); + + bool operator ==(o) => o is DropValue && o.value == value && o.id == id; } class DropdownField extends StatefulWidget { String? hint; List? list; + DropValue? dropdownValue; Function(DropValue) onSelect; - DropdownField(this.onSelect, {this.hint, this.list}); + DropdownField(this.onSelect, {this.hint, this.list, this.dropdownValue}); @override State createState() => _DropdownFieldState(); @@ -25,10 +28,16 @@ class DropdownField extends StatefulWidget { class _DropdownFieldState extends State { DropValue? dropdownValue; List defaultV = [ - new DropValue(1, "One",""), - new DropValue(2, "Two",""), + new DropValue(1, "One", ""), + new DropValue(2, "Two", ""), ]; + @override + void initState() { + super.initState(); + dropdownValue = widget.dropdownValue; + } + @override Widget build(BuildContext context) { return Container( diff --git a/lib/widgets/show_fill_button.dart b/lib/widgets/show_fill_button.dart index 457b38a..32908be 100644 --- a/lib/widgets/show_fill_button.dart +++ b/lib/widgets/show_fill_button.dart @@ -7,7 +7,7 @@ class ShowFillButton extends StatelessWidget { String title; VoidCallback onPressed; Color txtColor; - double elevation, radius, width; + double elevation, radius, width,height, fontSize, horizontalPadding; ShowFillButton({ required this.title, @@ -16,6 +16,9 @@ class ShowFillButton extends StatelessWidget { this.elevation = 4, this.radius = 6, this.width = 88, + this.height=45, + this.fontSize = 16, + this.horizontalPadding = 16, }); @override @@ -24,15 +27,15 @@ class ShowFillButton extends StatelessWidget { style: ElevatedButton.styleFrom( onPrimary: Colors.black87, primary: accentColor, - minimumSize: Size(width, 45), - padding: EdgeInsets.symmetric(horizontal: 16), + minimumSize: Size(width, height), + padding: EdgeInsets.symmetric(horizontal: horizontalPadding), elevation: elevation, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(radius)), ), ), onPressed: onPressed, - child: title.toUpperCase().toText(fontSize: 16, isBold: true), + child: title.toUpperCase().toText(fontSize: fontSize, isBold: true), ); } } diff --git a/lib/widgets/tab/login_email_tab.dart b/lib/widgets/tab/login_email_tab.dart index 7c29b63..b27c758 100644 --- a/lib/widgets/tab/login_email_tab.dart +++ b/lib/widgets/tab/login_email_tab.dart @@ -1,5 +1,8 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import '../../generated/locale_keys.g.dart'; + enum ClassType { EMAIL, NUMBER } class LoginEmailTab extends StatefulWidget { @@ -32,7 +35,7 @@ class _LoginEmailTabState extends State { color: type == ClassType.NUMBER ? Colors.blue : Colors.transparent, child: Center( child: Text( - "Number", + LocaleKeys.number.tr(), style: TextStyle( color: type == ClassType.NUMBER ? Colors.white : Colors.black, fontWeight: FontWeight.bold, @@ -54,7 +57,7 @@ class _LoginEmailTabState extends State { color: type == ClassType.EMAIL ? Colors.blue : Colors.transparent, child: Center( child: Text( - "Email", + LocaleKeys.email.tr(), style: TextStyle( color: type == ClassType.EMAIL ? Colors.white : Colors.black, fontWeight: FontWeight.bold, diff --git a/lib/widgets/txt_field.dart b/lib/widgets/txt_field.dart index ee4bb1b..814103a 100644 --- a/lib/widgets/txt_field.dart +++ b/lib/widgets/txt_field.dart @@ -64,7 +64,7 @@ class TxtField extends StatelessWidget { elevation: elevation, margin: isSidePaddingZero?EdgeInsets.zero:null, child: TextField( - keyboardType: TextInputType.number, + keyboardType: keyboardType, autofocus: false, controller: controller, enabled: isNeedClickAll == true ? false : true, diff --git a/pubspec.lock b/pubspec.lock index caa035b..c2b3b93 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -301,6 +301,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" meta: dependency: transitive description: @@ -571,7 +578,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.8" typed_data: dependency: transitive description: diff --git a/resources/langs/ar-SA.json b/resources/langs/ar-SA.json index 1931ef9..589e7fa 100644 --- a/resources/langs/ar-SA.json +++ b/resources/langs/ar-SA.json @@ -1,6 +1,6 @@ { "firstTimeLogIn": "تسجيل الدخول لأول مره", - "signUp": "تسجيل دخول", + "signUp": "التسجيل", "changeMobile": "تغيير رقم الجوال", "notifications": "الاشعارات", "general": "عام", @@ -10,6 +10,7 @@ "retrievePassword" : "استرجاع كلمة المرور", "changeEmail": "تغيير الايميل", "verify": "تحقق", + "verified": "تم التحقق", "signOut": "تسجيل خروج", "enterEmail": "ادخل الايميل", "enterNewEmail": "ادخل ايميل جديد", @@ -74,6 +75,7 @@ "defineProviders":"تحديد الموفرين", "closeAccount": "اغلاق الحساب", "createBranch" : "انشاء فرع", + "updateBranch" : "فرع التحديث", "address": "العنوان", "branchDescription": "وصف الفرع", "branchName": "اسم الفرع", @@ -92,6 +94,15 @@ "completeProfile2" : "اكمل الملف الشخصي 2/3", "completeProfile3" : "اكمل الملف الشخصي 3/3", "userInformation": "معلومات المتسخدم", + "faceRecognition": "تحقق مع بصمة الوجه", + "fingerPrint" : "تحقق مع بصمة الاصبع", + "whatsapp": "تحقق مع Whatsapp", + "SMS": "رسائل قصيره", + "selectRole" : "حدد الدور", + "userRoleOrTitle" : "عنوان المستخدم", + "codeSentToEmail": "تم ارسال الرمز للايميل", + "number": "موبايل", + "english": "English", "provider": "Provider", "title": "Hello", "msg": "Hello {} in the {} world ", @@ -128,5 +139,18 @@ "female": "Hello girl :) {}" } }, - "reset_locale": "Reset Language" -} \ No newline at end of file + "reset_locale": "Reset Language", + "insert_otp_code" : "الرجاء إدخال رمز OTP", + "resend_code" : "أعد إرسال الرمز", + "check_code" : "التحقق من الشفرة", + "time_will_expire" : "سينتهي الوقت في", + "no_city_available" : "لا توجد مدينة متاحة لهذا البلد", + "branch_created" : "تم إنشاء الفرع بنجاح", + "branch_updated" : "تم تحديث الفرع بنجاح", + "branch_deleted" : "تم حذف الفرع بنجاح", + "dashboard_main" : "لوحة القيادة / الصفحة الرئيسية", + "logo_brand" : "الشعار / العلامة التجارية", + "remove": "إزالة", + "no_branch": "لم يتم إضافة فرع حتى الآن", + "login_once": "الرجاء تسجيل الدخول مرة واحدة" +} diff --git a/resources/langs/en-US.json b/resources/langs/en-US.json index 780b026..4512be7 100644 --- a/resources/langs/en-US.json +++ b/resources/langs/en-US.json @@ -1,6 +1,6 @@ { "firstTimeLogIn" : "First Time Log In", - "signUp": "Sing Up", + "signUp": "Sign Up", "changeMobile": "Change Mobile", "notifications": "Notifications", "general": "General", @@ -10,6 +10,7 @@ "retrievePassword" : "Retrieve Password", "changeEmail": "Change Email", "verify": "Verify", + "verified": "Verified", "signOut": "Sign Out", "enterEmail": "Enter Email", "enterNewEmail": "Enter New Email", @@ -74,11 +75,12 @@ "defineProviders":"Define Providers", "closeAccount": "Close Account", "createBranch" : "Create Branch", + "updateBranch" : "Update Branch", "address": "Address", "branchDescription": "Branch Description", "branchName": "Branch Name", - "chooseCity": "Choose City", - "chooseCountry": "Choose Country", + "chooseCity": "Select City", + "chooseCountry": "Select Country", "selectAttachment":"Select Attachment", "somethingWrong" : "Something went wrong", "documentsUploaded" : "Documents uploaded successfully", @@ -93,6 +95,15 @@ "completeProfile3" : "Complete Profile 3/3", "userInformation": "User Information", "provider": "Provider", + "faceRecognition": "Face Recognition", + "fingerPrint" : "Finger Print", + "whatsapp": "With Whatsapp", + "SMS": "With SMS", + "selectRole" : "Select Role", + "userRoleOrTitle" : "User role or title", + "codeSentToEmail": "Code is sent to email", + "number": "Number", + "english": "عربي", "title": "Hello", "msg": "Hello {} in the {} world ", "msg_named": "{} are written in the {lang} language", @@ -128,5 +139,18 @@ "female": "Hello girl :) {}" } }, - "reset_locale": "Reset Language" -} \ No newline at end of file + "reset_locale": "Reset Language", + "insert_otp_code" : "Please insert OTP Code", + "resend_code" : "Resend Code", + "check_code" : "Check Code", + "time_will_expire" : "Time will Expire in", + "no_city_available" : "No City Available for this country", + "branch_created" : "Branch is successfully created", + "branch_updated" : "Branch is successfully Updated", + "branch_deleted" : "Branch is successfully Deleted", + "dashboard_main" : "Dashboard/Main Page", + "logo_brand" : "Logo/Brand", + "remove": "Remove", + "no_branch": "No Branch Added Yet", + "login_once": "Please login once" +}