From 9591eca23ca4ba71f88c10693cc710995aa4546c Mon Sep 17 00:00:00 2001 From: devmirza121 Date: Thu, 17 Feb 2022 18:02:40 +0300 Subject: [PATCH] API's Modifications 1.4 --- assets/images/ic_car.svg | 11 ++ assets/images/ic_edit.svg | 4 + assets/images/ic_lock.svg | 3 + assets/images/ic_logout.svg | 11 ++ assets/images/ic_mobile.svg | 10 ++ assets/images/ic_notes.svg | 12 ++ assets/images/ic_notification.svg | 4 + assets/images/ic_settings.svg | 4 + lib/api/api_client.dart | 104 +++++++++++++++++- lib/api/client/profile_api_client.dart | 40 +++++++ lib/api/{ => client}/user_api_client.dart | 18 ++- lib/api/login_api_client.dart | 27 ----- lib/api/tangheem_user_api_client.dart | 34 ------ lib/classes/app_state.dart | 21 ++++ lib/classes/consts.dart | 10 +- lib/config/routes.dart | 3 + lib/models/profile/document.dart | 80 ++++++++++++++ lib/models/user.dart | 9 -- lib/models/user/country.dart | 81 ++++++++++++++ lib/models/user/role.dart | 65 +++++++++++ lib/pages/dashboard/dashboard_page.dart | 27 ++++- lib/pages/user/complete_profile_page.dart | 2 +- .../user/login_method_selection_page.dart | 2 +- lib/pages/user/login_verification_page.dart | 5 +- lib/pages/user/login_verify_account_page.dart | 2 +- lib/pages/user/login_with_password_page.dart | 2 +- .../user/profile/define_license_page.dart | 96 ++++++++++++++++ lib/pages/user/profile/profile_3_page.dart | 14 +-- lib/pages/user/register_page.dart | 77 ++++++++++--- lib/widgets/dropdown/dropdow_field.dart | 41 ++++--- pubspec.lock | 20 +++- pubspec.yaml | 4 +- 32 files changed, 711 insertions(+), 132 deletions(-) create mode 100644 assets/images/ic_car.svg create mode 100644 assets/images/ic_edit.svg create mode 100644 assets/images/ic_lock.svg create mode 100644 assets/images/ic_logout.svg create mode 100644 assets/images/ic_mobile.svg create mode 100644 assets/images/ic_notes.svg create mode 100644 assets/images/ic_notification.svg create mode 100644 assets/images/ic_settings.svg create mode 100644 lib/api/client/profile_api_client.dart rename lib/api/{ => client}/user_api_client.dart (76%) delete mode 100644 lib/api/login_api_client.dart delete mode 100644 lib/api/tangheem_user_api_client.dart create mode 100644 lib/classes/app_state.dart create mode 100644 lib/models/profile/document.dart delete mode 100644 lib/models/user.dart create mode 100644 lib/models/user/country.dart create mode 100644 lib/models/user/role.dart create mode 100644 lib/pages/user/profile/define_license_page.dart diff --git a/assets/images/ic_car.svg b/assets/images/ic_car.svg new file mode 100644 index 0000000..804f607 --- /dev/null +++ b/assets/images/ic_car.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/ic_edit.svg b/assets/images/ic_edit.svg new file mode 100644 index 0000000..c14165f --- /dev/null +++ b/assets/images/ic_edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/ic_lock.svg b/assets/images/ic_lock.svg new file mode 100644 index 0000000..1273157 --- /dev/null +++ b/assets/images/ic_lock.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/ic_logout.svg b/assets/images/ic_logout.svg new file mode 100644 index 0000000..2be107f --- /dev/null +++ b/assets/images/ic_logout.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/ic_mobile.svg b/assets/images/ic_mobile.svg new file mode 100644 index 0000000..068cf7a --- /dev/null +++ b/assets/images/ic_mobile.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/ic_notes.svg b/assets/images/ic_notes.svg new file mode 100644 index 0000000..009cf17 --- /dev/null +++ b/assets/images/ic_notes.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/ic_notification.svg b/assets/images/ic_notification.svg new file mode 100644 index 0000000..e45bab2 --- /dev/null +++ b/assets/images/ic_notification.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/ic_settings.svg b/assets/images/ic_settings.svg new file mode 100644 index 0000000..83b64c9 --- /dev/null +++ b/assets/images/ic_settings.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index f6d65ea..e2433be 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -92,7 +92,14 @@ class ApiClient { return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); } - Future _postForResponse(String url, requestBody, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { + Future _postForResponse( + String url, + requestBody, { + String? token, + Map? queryParameters, + Map? headers, + int retryTimes = 0, + }) async { try { var _headers = {}; if (token != null) { @@ -107,7 +114,11 @@ class ApiClient { var queryString = new Uri(queryParameters: queryParameters).query; url = url + '?' + queryString; } - var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 100)); + + var response; + + response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 100)); + if (!kReleaseMode) { print("Url:$url"); print("body:$requestBody"); @@ -160,4 +171,93 @@ class ApiClient { } Future _post(url, {Map? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding)); + + Future getJsonForObject(FactoryConstructor factoryConstructor, String url, + {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { + var _headers = {'Accept': 'application/json'}; + if (headers != null && headers.isNotEmpty) { + _headers.addAll(headers); + } + var response = await getJsonForResponse(url, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes); + try { + if (!kReleaseMode) { + print("res:" + response.body); + } + var jsonData = jsonDecode(response.body); + return factoryConstructor(jsonData); + } catch (ex) { + print("exception:" + response.body); + throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex); + } + } + + Future getJsonForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { + if (headers == null) { + headers = {'Content-Type': 'application/json'}; + } else { + headers['Content-Type'] = 'application/json'; + } + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); + } + + Future _getForResponse(String url, {String? token, Map? queryParameters, Map? headers, int retryTimes = 0}) async { + try { + var _headers = {}; + if (token != null) { + _headers['Authorization'] = 'Bearer $token'; + } + + if (headers != null && headers.isNotEmpty) { + _headers.addAll(headers); + } + if (queryParameters != null) { + String queryString = new Uri(queryParameters: queryParameters).query; + url = url + '?' + queryString.toString(); + } + + if (!kReleaseMode) { + print("Url:$url"); + 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) { + return response; + } else { + throw _throwAPIException(response); + } + } on SocketException catch (e) { + if (retryTimes > 0) { + print('will retry after 3 seconds...'); + await Future.delayed(Duration(seconds: 3)); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); + } else { + throw APIException(APIException.OTHER, arguments: e); + } + } on HttpException catch (e) { + if (retryTimes > 0) { + print('will retry after 3 seconds...'); + await Future.delayed(Duration(seconds: 3)); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); + } else { + throw APIException(APIException.OTHER, arguments: e); + } + } on TimeoutException catch (e) { + throw APIException(APIException.TIMEOUT, arguments: e); + } on ClientException catch (e) { + if (retryTimes > 0) { + await Future.delayed(Duration(seconds: 3)); + return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); + } else { + throw APIException(APIException.OTHER, arguments: e); + } + } catch (e) { + throw APIException(APIException.OTHER, arguments: e); + } + } + + Future _get(url, {Map? headers}) => _withClient((client) => client.get(url, headers: headers)); } diff --git a/lib/api/client/profile_api_client.dart b/lib/api/client/profile_api_client.dart new file mode 100644 index 0000000..68227c5 --- /dev/null +++ b/lib/api/client/profile_api_client.dart @@ -0,0 +1,40 @@ +import 'dart:async'; +import 'package:car_provider_app/classes/app_state.dart'; +import 'package:car_provider_app/models/profile/document.dart'; +import 'package:car_provider_app/models/user/country.dart'; +import 'package:car_provider_app/models/user/role.dart'; +import 'package:http/http.dart'; +import 'package:car_provider_app/classes/consts.dart'; +import 'package:car_provider_app/models/content_info_model.dart'; +import 'package:car_provider_app/models/member_model.dart'; +import 'package:car_provider_app/models/surah_model.dart'; +import 'package:car_provider_app/models/user/basic_otp.dart'; +import 'package:car_provider_app/models/user/register_user.dart'; + +import '../api_client.dart'; + +class ProfileApiClent { + static final ProfileApiClent _instance = ProfileApiClent._internal(); + + ProfileApiClent._internal(); + + factory ProfileApiClent() => _instance; + + Future getServiceProviderDocument(dynamic userId) async { + var queryParameters = { + "ServiceProviderID": userId.toString(), + }; + String? token = AppState().getUser.data?.accessToken; + print(token); + return await ApiClient().getJsonForObject((json) => Document.fromJson(json), ApiConsts.GetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? ""); + } + + Future basicVerify(String phoneNo, String otp, String userToken) async { + var postParams = { + "userMobileNo": phoneNo, + "userOTP": otp, + "userToken": userToken, + }; + return await ApiClient().postJsonForObject((json) => RegisterUser.fromJson(json), ApiConsts.BasicVerify, postParams); + } +} diff --git a/lib/api/user_api_client.dart b/lib/api/client/user_api_client.dart similarity index 76% rename from lib/api/user_api_client.dart rename to lib/api/client/user_api_client.dart index 95935e7..135b017 100644 --- a/lib/api/user_api_client.dart +++ b/lib/api/client/user_api_client.dart @@ -1,4 +1,6 @@ import 'dart:async'; +import 'package:car_provider_app/models/user/country.dart'; +import 'package:car_provider_app/models/user/role.dart'; import 'package:http/http.dart'; import 'package:car_provider_app/classes/consts.dart'; import 'package:car_provider_app/models/content_info_model.dart'; @@ -7,7 +9,7 @@ import 'package:car_provider_app/models/surah_model.dart'; import 'package:car_provider_app/models/user/basic_otp.dart'; import 'package:car_provider_app/models/user/register_user.dart'; -import 'api_client.dart'; +import '../api_client.dart'; class UserApiClent { static final UserApiClent _instance = UserApiClent._internal(); @@ -16,8 +18,8 @@ class UserApiClent { factory UserApiClent() => _instance; - Future basicOtp(String phoneNo, {int otpType = 1}) async { - var postParams = {"countryID": 1, "userMobileNo": phoneNo, "otpType": otpType, "userRole": 4}; + Future basicOtp(String phoneNo, {int otpType = 1, int roleId = 4, int countryId = 1}) async { + var postParams = {"countryID": countryId, "userMobileNo": phoneNo, "otpType": otpType, "userRole": roleId}; return await ApiClient().postJsonForObject((json) => BasicOtp.fromJson(json), ApiConsts.BasicOTP, postParams); } @@ -56,4 +58,14 @@ class UserApiClent { var postParams = {"userToken": userToken, "userOTP": otp}; return await ApiClient().postJsonForResponse(ApiConsts.Login_V2_OTPVerify, postParams); } + + Future getAllCountries() async { + var postParams = {}; + return await ApiClient().getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry); + } + + Future getRoles() async { + var postParams = {}; + return await ApiClient().getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); + } } diff --git a/lib/api/login_api_client.dart b/lib/api/login_api_client.dart deleted file mode 100644 index 6cf0954..0000000 --- a/lib/api/login_api_client.dart +++ /dev/null @@ -1,27 +0,0 @@ - -class LoginApiClient { - static final LoginApiClient _instance = LoginApiClient._internal(); - - LoginApiClient._internal(); - - factory LoginApiClient() => _instance; - - // Future checkMobileAppVersion() async { - // String url = "${ApiConsts.utilitiesRest}CheckMobileAppVersion"; - // Map postParams = {}; - // postParams.addAll(AppState().postParamsJson); - // return await ApiClient().postJsonForObject((json) => CheckMobileAppVersionModel.fromJson(json), url, postParams); - // } - // - // Future memberLogin(String username, String password) async { - // String url = "${ApiConsts.erpRest}MemberLogin"; - // Map postParams = {"P_APP_VERSION": "CS", "P_LANGUAGE": "US", "P_PASSWORD": password, "P_USER_NAME": username}; - // postParams.addAll(AppState().postParamsJson); - // return await ApiClient().postJsonForObject((json) { - // GenericResponseModel responseData = GenericResponseModel.fromJson(json); - // AppState().postParamsObject?.setLogInTokenID = responseData.logInTokenID; - // return responseData.memberLoginList; - // }, url, postParams); - // } - -} diff --git a/lib/api/tangheem_user_api_client.dart b/lib/api/tangheem_user_api_client.dart deleted file mode 100644 index bfe32a9..0000000 --- a/lib/api/tangheem_user_api_client.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'dart:async'; - -import 'package:car_provider_app/classes/consts.dart'; -import 'package:car_provider_app/models/content_info_model.dart'; -import 'package:car_provider_app/models/member_model.dart'; -import 'package:car_provider_app/models/surah_model.dart'; - -import 'api_client.dart'; - -class TangheemUserApiClient { - static final TangheemUserApiClient _instance = TangheemUserApiClient._internal(); - - TangheemUserApiClient._internal(); - - factory TangheemUserApiClient() => _instance; - - Future getSurahs() async { - String url = "${ApiConsts.baseUrl}AlSuar_Get"; - var postParams = {}; - return await ApiClient().postJsonForObject((json) => SurahModel.fromJson(json), url, postParams); - } - - Future getMembers() async { - String url = "${ApiConsts.baseUrl}Committee_Get"; - var postParams = {}; - return await ApiClient().postJsonForObject((json) => MemberModel.fromJson(json), url, postParams); - } - - Future getContentInfo(int contentId) async { - String url = "${ApiConsts.baseUrl}ContentInfo_Get"; - var postParams = {"contentTypeId": contentId}; - return await ApiClient().postJsonForObject((json) => ContentInfoModel.fromJson(json), url, postParams); - } -} diff --git a/lib/classes/app_state.dart b/lib/classes/app_state.dart new file mode 100644 index 0000000..d73e33a --- /dev/null +++ b/lib/classes/app_state.dart @@ -0,0 +1,21 @@ +import 'package:car_provider_app/models/user/user.dart'; + +class AppState { + static final AppState _instance = AppState._internal(); + + AppState._internal(); + + factory AppState() => _instance; + + bool isLogged = false; + + set setLogged(v) => isLogged = v; + + bool? get getIsLogged => isLogged; + + User? _user = null; + + set setUser(v) => _user = v; + + User get getUser => _user??User(); +} diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 0615648..3b12d24 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -2,18 +2,24 @@ class ApiConsts { // static String baseUrl = "http://10.200.204.20:2801/"; // Local server static String baseUrl = "https://mdlaboratories.com"; // production server static String baseUrlServices = baseUrl + "/mc/"; // production server - // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String BasicOTP = baseUrlServices + "api/Register/BasicOTP"; static String BasicVerify = baseUrlServices + "api/Register/BasicVerify"; static String BasicComplete = baseUrlServices + "api/Register/BasicComplete"; + + //User static String Login_V1 = baseUrlServices + "api/Account/Login_V1"; static String Login_V2_OTP = baseUrlServices + "api/Account/Login_V2_OTP"; static String Login_V2_OTPVerify = baseUrlServices + "api/Account/Login_V2_OTPVerify"; static String user = baseUrlServices + "api/User/"; -} + static String GetAllCountry = baseUrlServices + "api/Master/Country_Get"; + static String GetProviderRoles = baseUrlServices + "api/Master/RoleServiceProvider_Get"; + //Profile + static String GetProviderDocument = baseUrlServices + "api/ServiceProviders/ServiceProviderDocument_Get"; +} + class GlobalConsts { static String isRememberMe = "remember_me"; static String email = "email"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 16f7736..6b5deea 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -6,6 +6,7 @@ import 'package:car_provider_app/pages/user/login_method_selection_page.dart'; import 'package:car_provider_app/pages/user/login_verification_page.dart'; import 'package:car_provider_app/pages/user/login_verify_account_page.dart'; import 'package:car_provider_app/pages/user/login_with_password_page.dart'; +import 'package:car_provider_app/pages/user/profile/define_license_page.dart'; import 'package:car_provider_app/pages/user/profile/profile_1_page.dart'; import 'package:car_provider_app/pages/user/profile/profile_2_page.dart'; import 'package:car_provider_app/pages/user/profile/profile_3_page.dart'; @@ -28,6 +29,7 @@ class AppRoutes { static final String profile1 = "/profile1"; static final String profile2 = "/profile2"; static final String profile3 = "/profile3"; + static final String defineLicense = "/defineLicese"; static final String dashboard = "/dashboard"; @@ -47,6 +49,7 @@ class AppRoutes { profile1: (context) => Profile1Page(), profile2: (context) => Profile2Page(), profile3: (context) => Profile3Page(), + defineLicense: (context) => DefineLicensePage(), //Home page dashboard: (context) => DashboardPage(), diff --git a/lib/models/profile/document.dart b/lib/models/profile/document.dart new file mode 100644 index 0000000..ff568c9 --- /dev/null +++ b/lib/models/profile/document.dart @@ -0,0 +1,80 @@ +// To parse this JSON data, do +// +// final document = documentFromJson(jsonString); + +import 'dart:convert'; + +Document documentFromJson(String str) => Document.fromJson(json.decode(str)); + +String documentToJson(Document data) => json.encode(data.toJson()); + +class Document { + Document({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Document.fromJson(Map json) => Document( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => Datum.fromJson(x))), + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "data": data == null ? null : List.from(data!.map((x) => x.toJson())), + "messageStatus": messageStatus == null ? null : messageStatus, + "message": message == null ? null : message, + }; +} + +class Datum { + Datum({ + this.id, + this.serviceProviderId, + this.documentId, + this.documentUrl, + this.status, + this.comment, + this.isActive, + this.document, + }); + + int? id; + int? serviceProviderId; + int? documentId; + dynamic? documentUrl; + int? status; + dynamic? comment; + bool? isActive; + String? document; + + factory Datum.fromJson(Map json) => Datum( + id: json["id"] == null ? null : json["id"], + serviceProviderId: json["serviceProviderID"] == null ? null : json["serviceProviderID"], + documentId: json["documentID"] == null ? null : json["documentID"], + documentUrl: json["documentURL"], + status: json["status"] == null ? null : json["status"], + comment: json["comment"], + isActive: json["isActive"] == null ? null : json["isActive"], + document: null, + ); + + Map toJson() => { + "id": id == null ? null : id, + "serviceProviderID": serviceProviderId == null ? null : serviceProviderId, + "documentID": documentId == null ? null : documentId, + "documentURL": documentUrl, + "status": status == null ? null : status, + "comment": comment, + "isActive": isActive == null ? null : isActive, + }; +} diff --git a/lib/models/user.dart b/lib/models/user.dart deleted file mode 100644 index e09c282..0000000 --- a/lib/models/user.dart +++ /dev/null @@ -1,9 +0,0 @@ -class User { - int id; - - User(this.id, this.userName, this.userImage, this.createdDate); - - String userName; - String userImage; - String createdDate; -} diff --git a/lib/models/user/country.dart b/lib/models/user/country.dart new file mode 100644 index 0000000..f4036cf --- /dev/null +++ b/lib/models/user/country.dart @@ -0,0 +1,81 @@ +// To parse this JSON data, do +// +// final country = countryFromJson(jsonString); + +import 'dart:convert'; + +Country countryFromJson(String str) => Country.fromJson(json.decode(str)); + +String countryToJson(Country data) => json.encode(data.toJson()); + +class Country { + Country({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Country.fromJson(Map json) => Country( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => CountryData.fromJson(x))), + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "data": data == null ? null : List.from(data!.map((x) => x.toJson())), + "messageStatus": messageStatus == null ? null : messageStatus, + "message": message == null ? null : message, + }; +} + +class CountryData { + CountryData({ + this.id, + this.countryName, + this.countryNameN, + this.nationality, + this.nationalityN, + this.countryCode, + this.alpha2Code, + this.alpha3Code, + }); + + int? id; + String? countryName; + String? countryNameN; + String? nationality; + String? nationalityN; + String? countryCode; + String? alpha2Code; + String? alpha3Code; + + factory CountryData.fromJson(Map json) => CountryData( + id: json["id"] == null ? null : json["id"], + countryName: json["countryName"] == null ? null : json["countryName"], + countryNameN: json["countryNameN"] == null ? null : json["countryNameN"], + nationality: json["nationality"] == null ? null : json["nationality"], + nationalityN: json["nationalityN"] == null ? null : json["nationalityN"], + countryCode: json["countryCode"] == null ? null : json["countryCode"], + alpha2Code: json["alpha2Code"] == null ? null : json["alpha2Code"], + alpha3Code: json["alpha3Code"] == null ? null : json["alpha3Code"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "countryName": countryName == null ? null : countryName, + "countryNameN": countryNameN == null ? null : countryNameN, + "nationality": nationality == null ? null : nationality, + "nationalityN": nationalityN == null ? null : nationalityN, + "countryCode": countryCode == null ? null : countryCode, + "alpha2Code": alpha2Code == null ? null : alpha2Code, + "alpha3Code": alpha3Code == null ? null : alpha3Code, + }; +} diff --git a/lib/models/user/role.dart b/lib/models/user/role.dart new file mode 100644 index 0000000..2ea0054 --- /dev/null +++ b/lib/models/user/role.dart @@ -0,0 +1,65 @@ +// To parse this JSON data, do +// +// final role = roleFromJson(jsonString); + +import 'dart:convert'; + +Role roleFromJson(String str) => Role.fromJson(json.decode(str)); + +String roleToJson(Role data) => json.encode(data.toJson()); + +class Role { + Role({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Role.fromJson(Map json) => Role( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => RoleData.fromJson(x))), + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "data": data == null ? null : List.from(data!.map((x) => x.toJson())), + "messageStatus": messageStatus == null ? null : messageStatus, + "message": message == null ? null : message, + }; +} + +class RoleData { + RoleData({ + this.id, + this.roleName, + this.roleNameN, + this.isActive, + }); + + int? id; + String? roleName; + String? roleNameN; + bool? isActive; + + factory RoleData.fromJson(Map json) => RoleData( + id: json["id"] == null ? null : json["id"], + roleName: json["roleName"] == null ? null : json["roleName"], + roleNameN: json["roleNameN"] == null ? null : json["roleNameN"], + isActive: json["isActive"] == null ? null : json["isActive"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "roleName": roleName == null ? null : roleName, + "roleNameN": roleNameN == null ? null : roleNameN, + "isActive": isActive == null ? null : isActive, + }; +} diff --git a/lib/pages/dashboard/dashboard_page.dart b/lib/pages/dashboard/dashboard_page.dart index a0726b6..b9ed74e 100644 --- a/lib/pages/dashboard/dashboard_page.dart +++ b/lib/pages/dashboard/dashboard_page.dart @@ -1,4 +1,5 @@ import 'package:car_provider_app/api/shared_prefrence.dart'; +import 'package:car_provider_app/config/routes.dart'; import 'package:car_provider_app/theme/colors.dart'; import 'package:car_provider_app/utils/navigator.dart'; import 'package:car_provider_app/widgets/app_bar.dart'; @@ -7,6 +8,7 @@ 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:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; class DashboardPage extends StatefulWidget { @override @@ -82,19 +84,34 @@ class _DashboardPageState extends State { ), ), ListTile( - leading: Icon(Icons.notifications), + leading: SvgPicture.asset("assets/images/ic_notification.svg"), title: "Notifications".toText12(), ), ListTile( - leading: Icon(Icons.settings), + leading: SvgPicture.asset("assets/images/ic_settings.svg"), title: "General".toText12(), ), ListTile( - leading: Icon(Icons.person), - title: "Account".toText12(), + leading: SvgPicture.asset("assets/images/ic_notes.svg"), + title: "Define Licenses".toText12(), + onTap: (){ + navigateWithName(context, AppRoutes.defineLicense); + }, + ), + ListTile( + leading: SvgPicture.asset("assets/images/ic_car.svg"), + title: "Dealership Settings".toText12(), + ), + ListTile( + leading: SvgPicture.asset("assets/images/ic_lock.svg"), + title: "Change Password".toText12(), + ), + ListTile( + leading: SvgPicture.asset("assets/images/ic_mobile.svg"), + title: "Change Mobile".toText12(), ), ListTile( - leading: Icon(Icons.logout), + leading: SvgPicture.asset("assets/images/ic_logout.svg"), title: "Sign Out".toText12(), onTap: () { pop(context); diff --git a/lib/pages/user/complete_profile_page.dart b/lib/pages/user/complete_profile_page.dart index 161371e..4c9f21c 100644 --- a/lib/pages/user/complete_profile_page.dart +++ b/lib/pages/user/complete_profile_page.dart @@ -1,4 +1,4 @@ -import 'package:car_provider_app/api/user_api_client.dart'; +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/models/user/basic_otp.dart'; diff --git a/lib/pages/user/login_method_selection_page.dart b/lib/pages/user/login_method_selection_page.dart index 68ef39a..87fb136 100644 --- a/lib/pages/user/login_method_selection_page.dart +++ b/lib/pages/user/login_method_selection_page.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:car_provider_app/api/shared_prefrence.dart'; -import 'package:car_provider_app/api/user_api_client.dart'; +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/constants.dart'; import 'package:car_provider_app/config/routes.dart'; diff --git a/lib/pages/user/login_verification_page.dart b/lib/pages/user/login_verification_page.dart index f7579a2..b217367 100644 --- a/lib/pages/user/login_verification_page.dart +++ b/lib/pages/user/login_verification_page.dart @@ -1,7 +1,8 @@ import 'dart:convert'; import 'package:car_provider_app/api/shared_prefrence.dart'; -import 'package:car_provider_app/api/user_api_client.dart'; +import 'package:car_provider_app/api/client/user_api_client.dart'; +import 'package:car_provider_app/classes/app_state.dart'; import 'package:car_provider_app/classes/utils.dart'; import 'package:car_provider_app/config/constants.dart'; import 'package:car_provider_app/config/routes.dart'; @@ -69,6 +70,8 @@ class _LoginVerificationPageState extends State { RegisterUser verifiedUser = RegisterUser.fromJson(jsonDecode(response2.body)); if (verifiedUser.messageStatus == 1) { User user = User.fromJson(jsonDecode(response2.body)); + AppState().setUser = user; + print(user.data!.userInfo!.providerId.toString()); navigateReplaceWithName(context, AppRoutes.dashboard); } else { Utils.showToast(verifiedUser.message ?? ""); diff --git a/lib/pages/user/login_verify_account_page.dart b/lib/pages/user/login_verify_account_page.dart index 4acdb5c..ec1aee3 100644 --- a/lib/pages/user/login_verify_account_page.dart +++ b/lib/pages/user/login_verify_account_page.dart @@ -1,4 +1,4 @@ -import 'package:car_provider_app/api/user_api_client.dart'; +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/constants.dart'; import 'package:car_provider_app/config/routes.dart'; diff --git a/lib/pages/user/login_with_password_page.dart b/lib/pages/user/login_with_password_page.dart index ba83bf3..f4d9646 100644 --- a/lib/pages/user/login_with_password_page.dart +++ b/lib/pages/user/login_with_password_page.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:car_provider_app/api/shared_prefrence.dart'; -import 'package:car_provider_app/api/user_api_client.dart'; +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/constants.dart'; import 'package:car_provider_app/config/routes.dart'; diff --git a/lib/pages/user/profile/define_license_page.dart b/lib/pages/user/profile/define_license_page.dart new file mode 100644 index 0000000..e54076c --- /dev/null +++ b/lib/pages/user/profile/define_license_page.dart @@ -0,0 +1,96 @@ +import 'dart:io'; + +import 'package:car_provider_app/api/client/profile_api_client.dart'; +import 'package:car_provider_app/classes/app_state.dart'; +import 'package:car_provider_app/models/profile/document.dart'; +import 'package:car_provider_app/widgets/txt_field.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:car_provider_app/extensions/int_extensions.dart'; + +class DefineLicensePage extends StatefulWidget { + @override + State createState() => _DefineLicensePageState(); +} + +class _DefineLicensePageState extends State { + Document? document; + + @override + void initState() { + // TODO: implement initState + super.initState(); + getDocuments(); + } + + getDocuments() async { + document = await ProfileApiClent().getServiceProviderDocument(AppState().getUser.data!.userInfo!.providerId ?? 0); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Define Licenses"), + ), + body: Container( + width: double.infinity, + height: double.infinity, + child: showWidget(), + ), + ); + } + + Widget showWidget() { + if (document != null) { + return document!.data!.length == 0 + ? Text("Something went wrong") + : ListView.separated( + itemBuilder: (context, index) { + return Row( + children: [ + Flexible( + child: TxtField( + hint: "Select Attachment", + value: document?.data![index].documentUrl ?? "", + isNeedClickAll: true, + maxLines: 2, + ), + ), + IconButton( + onPressed: () { + selectFile(index); + }, + icon: Icon(Icons.insert_link_rounded), + ) + ], + ); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + padding: EdgeInsets.all(12), + itemCount: document!.data!.length, + ); + } else { + return Center( + child: CircularProgressIndicator(), + ); + } + } + + selectFile(int index) async { + FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg']); + + if (result != null) { + File file = File(result.files.single.path ?? ""); + + setState(() { + document!.data![index].documentUrl = result.files.single.path ?? ""; + }); + } else { + // User canceled the picker + } + } +} diff --git a/lib/pages/user/profile/profile_3_page.dart b/lib/pages/user/profile/profile_3_page.dart index a6e9824..2acb565 100644 --- a/lib/pages/user/profile/profile_3_page.dart +++ b/lib/pages/user/profile/profile_3_page.dart @@ -25,13 +25,13 @@ class Profile3Page extends StatelessWidget { "Complete Profile 3/3".toText16(), "Branch Info and Services".toText14(), 12.height, - DropdownField( - hint: "Country", - ), - 12.height, - DropdownField( - hint: "City", - ), + // DropdownField( + // hint: "Country", + // ), + // 12.height, + // DropdownField( + // hint: "City", + // ), 12.height, TxtField( hint: "Address", diff --git a/lib/pages/user/register_page.dart b/lib/pages/user/register_page.dart index 35a8511..4531c52 100644 --- a/lib/pages/user/register_page.dart +++ b/lib/pages/user/register_page.dart @@ -1,14 +1,18 @@ import 'package:car_provider_app/api/api_client.dart'; -import 'package:car_provider_app/api/user_api_client.dart'; +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/models/user/basic_otp.dart'; +import 'package:car_provider_app/models/user/country.dart'; import 'package:car_provider_app/models/user/register_user.dart'; +import 'package:car_provider_app/models/user/role.dart'; +import 'package:car_provider_app/provider/counter.dart'; import 'package:car_provider_app/utils/navigator.dart'; import 'package:car_provider_app/utils/utils.dart'; 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/otp_dialog.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/extensions/int_extensions.dart'; import 'package:car_provider_app/extensions/string_extensions.dart'; @@ -17,7 +21,8 @@ import 'package:car_provider_app/widgets/txt_field.dart'; import 'package:flutter/material.dart'; class RegisterPage extends StatelessWidget { - String phoneNum = ""; + String phoneNum = "", countryCode = ""; + int role = -1, countryId = -1; @override Widget build(BuildContext context) { @@ -31,6 +36,40 @@ class RegisterPage extends StatelessWidget { children: [ "Enter Phone Number".toText24(), 12.height, + FutureBuilder( + future: UserApiClent().getRoles(), + builder: (context, snapshot) { + if (snapshot.hasData) { + List dropList = []; + snapshot.data?.data?.forEach((element) { + dropList.add(new DropValue(element.id ?? 0, element.roleName ?? "", "")); + }); + return DropdownField((DropValue value) { + role = value.id; + }, list: dropList, hint: "Chosse Role"); + } else { + return CircularProgressIndicator(); + } + }, + ), + 12.height, + FutureBuilder( + future: UserApiClent().getAllCountries(), + builder: (context, snapshot) { + if (snapshot.hasData) { + List dropList = []; + snapshot.data?.data?.forEach((element) { + dropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + }); + return DropdownField((DropValue value) { + countryCode = value.subValue; + countryId = value.id; + }, list: dropList, hint: "Chosse Country"); + } else { + return CircularProgressIndicator(); + } + }, + ), TxtField( hint: "Enter Phone number to Register", onChanged: (v) { @@ -42,7 +81,7 @@ class RegisterPage extends StatelessWidget { title: "Continue", width: double.infinity, onPressed: () { - performBasicOtp(context); + if (validation()) performBasicOtp(context); }, ), ], @@ -53,36 +92,40 @@ class RegisterPage extends StatelessWidget { Future performBasicOtp(BuildContext context) async { Utils.showLoading(context); - BasicOtp basicOtp = await UserApiClent().basicOtp(phoneNum); + BasicOtp basicOtp = await UserApiClent().basicOtp(countryCode + phoneNum,roleId: role); Utils.hideLoading(context); if (basicOtp.messageStatus == 1) { showMDialog(context, child: OtpDialog( onClick: (String code) async { pop(context); Utils.showLoading(context); - RegisterUser user = await UserApiClent().basicVerify(phoneNum, code, basicOtp.data!.userToken ?? ""); + RegisterUser user = await UserApiClent().basicVerify(countryCode + phoneNum, code, basicOtp.data!.userToken ?? ""); Utils.hideLoading(context); if (user.messageStatus == 1) { Utils.showToast(user.message ?? ""); - navigateReplaceWithName(context, AppRoutes.completeProfile,arguments: user); + navigateReplaceWithName(context, AppRoutes.completeProfile, arguments: user); } else { Utils.showToast(user.message ?? ""); } - // delay(300).then( - // (value) => showMDialog( - // context, - // child: MessageDialog( - // title: "Phone Number Verified", - // onClick: () { - // navigateWithName(context, AppRoutes.completeProfile); - // }, - // ), - // ), - // ); }, )); } else { Utils.showToast(basicOtp.message ?? ""); } } + + bool validation() { + bool isValid = true; + if (role == -1) { + Utils.showToast("Please select Provider Role"); + isValid = false; + } else if (countryCode.isEmpty) { + Utils.showToast("Please select Country Code"); + isValid = false; + } else if (phoneNum.isEmpty) { + Utils.showToast("Please add Phone No"); + isValid = false; + } + return isValid; + } } diff --git a/lib/widgets/dropdown/dropdow_field.dart b/lib/widgets/dropdown/dropdow_field.dart index 3edb326..0aa6239 100644 --- a/lib/widgets/dropdown/dropdow_field.dart +++ b/lib/widgets/dropdown/dropdow_field.dart @@ -3,18 +3,31 @@ import 'package:car_provider_app/utils/utils.dart'; import 'package:car_provider_app/widgets/extensions/string_extensions.dart'; import 'package:flutter/material.dart'; +class DropValue { + int id; + String value; + String subValue; + + DropValue(this.id, this.value,this.subValue); +} + class DropdownField extends StatefulWidget { String? hint; - List? list; + List? list; + Function(DropValue) onSelect; - DropdownField({this.hint, this.list}); + DropdownField(this.onSelect, {this.hint, this.list}); @override State createState() => _DropdownFieldState(); } class _DropdownFieldState extends State { - String? dropdownValue; + DropValue? dropdownValue; + List defaultV = [ + new DropValue(1, "One",""), + new DropValue(2, "Two",""), + ]; @override Widget build(BuildContext context) { @@ -27,7 +40,7 @@ class _DropdownFieldState extends State { ), margin: EdgeInsets.all(2), padding: EdgeInsets.only(left: 8, right: 8), - child: DropdownButton( + child: DropdownButton( value: dropdownValue, icon: const Icon(Icons.keyboard_arrow_down_sharp), elevation: 16, @@ -36,27 +49,21 @@ class _DropdownFieldState extends State { iconDisabledColor: borderColor, isExpanded: true, style: const TextStyle(color: Colors.black), - hint: (widget.hint ?? "").toText24(color: borderColor), + hint: (widget.hint ?? "").toText12(color: borderColor), underline: Container( height: 0, ), - onChanged: (String? newValue) { + onChanged: (DropValue? newValue) { setState(() { dropdownValue = newValue!; + widget.onSelect(newValue); }); }, - items: (widget.list ?? - [ - 'One', - 'Two', - 'Free', - 'Four', - ]) - .map>( - (String value) { - return DropdownMenuItem( + items: (widget.list ?? defaultV).map>( + (DropValue value) { + return DropdownMenuItem( value: value, - child: value.toText24(), + child: value.value.toText12(), ); }, ).toList(), diff --git a/pubspec.lock b/pubspec.lock index aa18217..66b0312 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -99,6 +99,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.2" + file_picker: + dependency: "direct main" + description: + name: file_picker + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" flutter: dependency: "direct main" description: flutter @@ -116,13 +123,20 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" flutter_svg: dependency: "direct main" description: name: flutter_svg url: "https://pub.dartlang.org" source: hosted - version: "0.22.0" + version: "1.0.3" flutter_test: dependency: "direct dev" description: flutter @@ -216,14 +230,14 @@ packages: name: path_drawing url: "https://pub.dartlang.org" source: hosted - version: "0.5.1+1" + version: "1.0.0" path_parsing: dependency: transitive description: name: path_parsing url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "1.0.0" path_provider: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 61ec9bf..cc926b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,10 +40,12 @@ dependencies: easy_localization: ^3.0.0 http: ^0.13.3 permission_handler: 7.1.0 - flutter_svg: ^0.22.0 + flutter_svg: ^1.0.3 sizer: ^2.0.15 fluttertoast: ^8.0.8 shared_preferences: ^2.0.6 + file_picker: ^4.4.0 + dev_dependencies: flutter_test: