diff --git a/android/app/build.gradle b/android/app/build.gradle index 5043ee5..9aa40ce 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -43,9 +43,9 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.car_provider_app" - minSdkVersion 16 - targetSdkVersion 30 + applicationId "com.ejada.hmg" + minSdkVersion 23 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..dd4038c --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,42 @@ +{ + "project_info": { + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", + "android_client_info": { + "package_name": "com.ejada.hmg" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0f28367..34c7045 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,8 @@ package="com.example.car_provider_app"> - + + @@ -17,6 +18,7 @@ the Android process has started. This theme is visible to the user while the Flutter UI initializes. After that, this theme continues to determine the Window background behind the Flutter UI. --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/ic_close_account.svg b/assets/icons/ic_close_account.svg new file mode 100644 index 0000000..93adb61 --- /dev/null +++ b/assets/icons/ic_close_account.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/ic_provider.svg b/assets/icons/ic_provider.svg new file mode 100644 index 0000000..e22c356 --- /dev/null +++ b/assets/icons/ic_provider.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/ic_services.svg b/assets/icons/ic_services.svg new file mode 100644 index 0000000..b0d0606 --- /dev/null +++ b/assets/icons/ic_services.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/icons/ic_settings.svg b/assets/icons/ic_settings.svg new file mode 100644 index 0000000..6435135 --- /dev/null +++ b/assets/icons/ic_settings.svg @@ -0,0 +1,4 @@ + + + + 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..2724eb2 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -68,12 +68,14 @@ class ApiClient { var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes); try { if (!kReleaseMode) { - print("res:" + response.body); + print("res121:" + response.body); + print("res121:" + response.statusCode.toString()); } var jsonData = jsonDecode(response.body); return factoryConstructor(jsonData); } catch (ex) { - print("exception:" + response.body); + print(ex); + print("exception:" + ex.toString()); throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex); } } @@ -92,7 +94,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 +116,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"); @@ -144,6 +157,9 @@ class ApiClient { } else { throw APIException(APIException.OTHER, arguments: e); } + }catch (ex) { + print("exception1:" + ex.toString()); + throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex); } } @@ -160,4 +176,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/branch_api_client.dart b/lib/api/client/branch_api_client.dart new file mode 100644 index 0000000..a56e93f --- /dev/null +++ b/lib/api/client/branch_api_client.dart @@ -0,0 +1,69 @@ +import 'dart:async'; +import 'package:car_provider_app/classes/app_state.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/profile/categroy.dart'; +import 'package:car_provider_app/models/profile/document.dart'; +import 'package:car_provider_app/models/profile/services.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 BranchApiClent { + static final BranchApiClent _instance = BranchApiClent._internal(); + + BranchApiClent._internal(); + + factory BranchApiClent() => _instance; + + Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async { + var postParams = { + // "id": 0, + "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", + "branchName": branchName, + "branchDescription": branchDescription, + "cityID": cityId, + "address": address, + "latitude": latitude, + "longitude": longitude, + "isActive": true + }; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t); + } + + Future fetchAllBranches() 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.ServiceProviderBranchGet, queryParameters: postParams, token: t); + } + + Future fetchBranchCategory() async { + var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().getJsonForObject((json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get, queryParameters: postParams, token: t); + } + + Future fetchServices(String serviceCategoryId) async { + var postParams = {"ServiceCategoryID": serviceCategoryId}; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen " + t); + return await ApiClient().getJsonForObject((json) => Services.fromJson(json), ApiConsts.Services_Get, queryParameters: postParams, token: t); + } + + Future createService(List> map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); + } +} diff --git a/lib/api/client/profile_api_client.dart b/lib/api/client/profile_api_client.dart new file mode 100644 index 0000000..588f3ee --- /dev/null +++ b/lib/api/client/profile_api_client.dart @@ -0,0 +1,53 @@ +import 'dart:async'; +import 'package:car_provider_app/classes/app_state.dart'; +import 'package:car_provider_app/models/m_response.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 serviceProviderDocumentsUpdate(List? documents) async { + List> map = []; + for (int i = 0; i < documents!.length; i++) { + if(documents[i].document!=null){ + var postParams = { + "id": documents[i].id, + "serviceProviderID": documents[i].serviceProviderId, + "documentID": documents[i].documentId, + "documentExt": documents[i].fileExt, + "documentImage": documents[i].document, + "isActive": true + }; + map.add(postParams); + } + + } + String t=AppState().getUser.data!.accessToken ?? ""; + print("tokeen "+t); + return await ApiClient().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderDocument_Update, map, token: t); + } +} diff --git a/lib/api/user_api_client.dart b/lib/api/client/user_api_client.dart similarity index 79% rename from lib/api/user_api_client.dart rename to lib/api/client/user_api_client.dart index 67c0440..9984852 100644 --- a/lib/api/user_api_client.dart +++ b/lib/api/client/user_api_client.dart @@ -1,4 +1,7 @@ import 'dart:async'; +import 'package:car_provider_app/models/user/cities.dart'; +import 'package:car_provider_app/models/user/country.dart'; +import 'package:car_provider_app/models/user/role.dart'; import 'package:car_provider_app/models/user/confirm_password.dart'; import 'package:car_provider_app/models/user/forget_password_otp_compare.dart'; import 'package:car_provider_app/models/user/forget_password_otp_request.dart'; @@ -19,8 +22,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); } @@ -60,6 +63,22 @@ class UserApiClent { 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 getAllCites(String countryId) async { + var postParams = { + "CountryID": countryId, + }; + return await ApiClient().getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams); + } + + Future getRoles() async { + return await ApiClient().getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); + } + Future ForgetPasswordOTPRequest(String userName, int otpType) async { var postParams = { "userName": userName, 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 600d74a..e751d32 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -2,30 +2,36 @@ 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"; + static String GetAllCities = baseUrlServices + "api/Master/City_Get"; static String ForgetPasswordOTPRequest = baseUrlServices + "api/Account/ForgetPasswordOTPRequest"; static String ForgetPasswordOTPCompare = baseUrlServices + "api/Account/ForgetPasswordOTPCompare"; static String ForgetPassword = baseUrlServices + "api/Account/ForgetPassword"; + //Profile + static String GetProviderDocument = baseUrlServices + "api/ServiceProviders/ServiceProviderDocument_Get"; + static String ServiceProviderDocument_Update = baseUrlServices + "api/ServiceProviders/ServiceProviderDocument_Update"; - - - - + //Branch + static String createProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Create"; + 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"; + static String ServiceProviderService_Create = baseUrlServices + "api/ServiceProviders/ServiceProviderService_Create"; } - class GlobalConsts { static String isRememberMe = "remember_me"; static String email = "email"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 51fe26d..eb02a91 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -13,8 +13,6 @@ import 'package:car_provider_app/pages/user/register_page.dart'; import 'package:car_provider_app/pages/user/register_selection_page.dart'; import 'package:car_provider_app/pages/user/splash_page.dart'; import 'package:flutter/material.dart'; -import 'package:car_provider_app/pages/user/vertify_password_page.dart'; -import 'package:car_provider_app/pages/user/confirm_new_password_page.dart'; class AppRoutes { //User @@ -32,9 +30,15 @@ class AppRoutes { static final String profile3 = "/profile3"; static final String vertifyPassword = "/vertifyPassword"; static final String confirmNewPasswordPage = "/confirmNewPasswordPage"; + static final String defineLicense = "/defineLicese"; static final String dashboard = "/dashboard"; + //settings + static final String dealershipSetting = "/dealershipSetting"; + static final String defineBranch = "/defineBranch"; + static final String createServices = "/createServices"; + static final String initialRoute = splash; static final Map routes = { @@ -51,10 +55,16 @@ class AppRoutes { profile1: (context) => Profile1Page(), profile2: (context) => Profile2Page(), profile3: (context) => Profile3Page(), + defineLicense: (context) => DefineLicensePage(), vertifyPassword: (context) => VerifyPasswordPage(), confirmNewPasswordPage: (context) => ConfirmNewPasswordPage(ModalRoute.of(context)!.settings.arguments as String), //Home page dashboard: (context) => DashboardPage(), + + //setting + dealershipSetting: (context) => DealershipPage(), + defineBranch: (context) => DefineBranchPage(), + createServices: (context) => CreateServicesPage(), }; } diff --git a/lib/models/m_response.dart b/lib/models/m_response.dart new file mode 100644 index 0000000..bd9d3a1 --- /dev/null +++ b/lib/models/m_response.dart @@ -0,0 +1,33 @@ +// To parse this JSON data, do +// +// final mResponse = mResponseFromJson(jsonString); + +import 'dart:convert'; + +MResponse mResponseFromJson(String str) => MResponse.fromJson(json.decode(str)); + +String mResponseToJson(MResponse data) => json.encode(data.toJson()); + +class MResponse { + MResponse({ + this.totalItemsCount, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + int? messageStatus; + String? message; + + factory MResponse.fromJson(Map json) => MResponse( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "messageStatus": messageStatus == null ? null : messageStatus, + "message": message == null ? null : message, + }; +} diff --git a/lib/models/profile/branch.dart b/lib/models/profile/branch.dart new file mode 100644 index 0000000..cc7d68a --- /dev/null +++ b/lib/models/profile/branch.dart @@ -0,0 +1,85 @@ +// To parse this JSON data, do +// +// final branch = branchFromJson(jsonString); + +import 'dart:convert'; + +Branch branchFromJson(String str) => Branch.fromJson(json.decode(str)); + +String branchToJson(Branch data) => json.encode(data.toJson()); + +class Branch { + Branch({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Branch.fromJson(Map json) => Branch( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => BranchData.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 BranchData { + BranchData({ + this.id, + this.serviceProviderId, + this.branchName, + this.branchDescription, + this.cityId, + this.address, + this.latitude, + this.longitude, + this.status, + }); + + int? id; + int? serviceProviderId; + String? branchName; + String? branchDescription; + 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"], + cityId: json["cityID"] == null ? null : json["cityID"], + address: json["address"] == null ? null : json["address"], + latitude: json["latitude"] == null ? null : json["latitude"], + longitude: json["longitude"] == null ? null : json["longitude"], + status: json["status"] == null ? null : json["status"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "serviceProviderID": serviceProviderId == null ? null : serviceProviderId, + "branchName": branchName == null ? null : branchName, + "branchDescription": branchDescription == null ? null : branchDescription, + "cityID": cityId == null ? null : cityId, + "address": address == null ? null : address, + "latitude": latitude == null ? null : latitude, + "longitude": longitude == null ? null : longitude, + "status": status == null ? null : status, + }; +} diff --git a/lib/models/profile/categroy.dart b/lib/models/profile/categroy.dart new file mode 100644 index 0000000..6f566f1 --- /dev/null +++ b/lib/models/profile/categroy.dart @@ -0,0 +1,69 @@ +// To parse this JSON data, do +// +// final category = categoryFromJson(jsonString); + +import 'dart:convert'; + +Category categoryFromJson(String str) => Category.fromJson(json.decode(str)); + +String categoryToJson(Category data) => json.encode(data.toJson()); + +class Category { + Category({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Category.fromJson(Map json) => Category( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => CategoryData.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 CategoryData { + CategoryData({ + this.id, + this.categoryName, + this.categoryNameN, + this.serviceCategoryIconUrl, + this.serviceCategoryImageUrl, + }); + + int? id; + String? categoryName; + String? categoryNameN; + dynamic? serviceCategoryIconUrl; + dynamic? serviceCategoryImageUrl; + + factory CategoryData.fromJson(Map json) => CategoryData( + id: json["id"] == null ? null : json["id"], + categoryName: json["categoryName"] == null ? null : json["categoryName"], + categoryNameN: json["categoryNameN"] == null ? null : json["categoryNameN"], + serviceCategoryIconUrl: json["serviceCategoryIconUrl"], + serviceCategoryImageUrl: json["serviceCategoryImageUrl"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "categoryName": categoryName == null ? null : categoryName, + "categoryNameN": categoryNameN == null ? null : categoryNameN, + "serviceCategoryIconUrl": serviceCategoryIconUrl, + "serviceCategoryImageUrl": serviceCategoryImageUrl, + }; +} diff --git a/lib/models/profile/document.dart b/lib/models/profile/document.dart new file mode 100644 index 0000000..da082b3 --- /dev/null +++ b/lib/models/profile/document.dart @@ -0,0 +1,83 @@ +// 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) => DocumentData.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 DocumentData { + DocumentData({ + this.id, + this.serviceProviderId, + this.documentId, + this.documentUrl, + this.status, + this.comment, + this.isActive, + this.document, + this.fileExt, + }); + + int? id; + int? serviceProviderId; + int? documentId; + dynamic? documentUrl; + int? status; + dynamic? comment; + bool? isActive; + String? document; + String? fileExt; + + factory DocumentData.fromJson(Map json) => DocumentData( + 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, + fileExt: 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/profile/services.dart b/lib/models/profile/services.dart new file mode 100644 index 0000000..d296300 --- /dev/null +++ b/lib/models/profile/services.dart @@ -0,0 +1,80 @@ +// To parse this JSON data, do +// +// final services = servicesFromJson(jsonString); + +import 'dart:convert'; + +Services servicesFromJson(String str) => Services.fromJson(json.decode(str)); + +String servicesToJson(Services data) => json.encode(data.toJson()); + +class Services { + Services({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Services.fromJson(Map json) => Services( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => ServicesData.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 ServicesData { + ServicesData({ + this.id, + this.description, + this.descriptionN, + this.serviceIconUrl, + this.serviceImageUrl, + this.serviceCategoryId, + this.categoryName, + this.isSelected, + }); + + int? id; + String? description; + String? descriptionN; + dynamic? serviceIconUrl; + dynamic? serviceImageUrl; + int? serviceCategoryId; + dynamic? categoryName; + bool? isSelected; + + factory ServicesData.fromJson(Map json) => ServicesData( + id: json["id"] == null ? null : json["id"], + description: json["description"] == null ? null : json["description"], + descriptionN: json["descriptionN"] == null ? null : json["descriptionN"], + serviceIconUrl: json["serviceIconUrl"], + serviceImageUrl: json["serviceImageUrl"], + serviceCategoryId: json["serviceCategoryID"] == null ? null : json["serviceCategoryID"], + categoryName: json["categoryName"], + isSelected: false, + ); + + Map toJson() => { + "id": id == null ? null : id, + "description": description == null ? null : description, + "descriptionN": descriptionN == null ? null : descriptionN, + "serviceIconUrl": serviceIconUrl, + "serviceImageUrl": serviceImageUrl, + "serviceCategoryID": serviceCategoryId == null ? null : serviceCategoryId, + "categoryName": categoryName, + }; +} 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/cities.dart b/lib/models/user/cities.dart new file mode 100644 index 0000000..5c32405 --- /dev/null +++ b/lib/models/user/cities.dart @@ -0,0 +1,65 @@ +// To parse this JSON data, do +// +// final cities = citiesFromJson(jsonString); + +import 'dart:convert'; + +Cities citiesFromJson(String str) => Cities.fromJson(json.decode(str)); + +String citiesToJson(Cities data) => json.encode(data.toJson()); + +class Cities { + Cities({ + this.totalItemsCount, + this.data, + this.messageStatus, + this.message, + }); + + int? totalItemsCount; + List? data; + int? messageStatus; + String? message; + + factory Cities.fromJson(Map json) => Cities( + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : List.from(json["data"].map((x) => CityData.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 CityData { + CityData({ + this.id, + this.cityName, + this.cityNameN, + this.countryId, + }); + + int? id; + String? cityName; + String? cityNameN; + int? countryId; + + factory CityData.fromJson(Map json) => CityData( + id: json["id"] == null ? null : json["id"], + cityName: json["cityName"] == null ? null : json["cityName"], + cityNameN: json["cityNameN"] == null ? null : json["cityNameN"], + countryId: json["countryID"] == null ? null : json["countryID"], + ); + + Map toJson() => { + "id": id == null ? null : id, + "cityName": cityName == null ? null : cityName, + "cityNameN": cityNameN == null ? null : cityNameN, + "countryID": countryId == null ? null : countryId, + }; +} 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..6097ed0 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,37 @@ 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(), + onTap: (){ + navigateWithName(context, AppRoutes.dealershipSetting); + }, + ), + 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/location/map_selection_widget.dart b/lib/pages/location/map_selection_widget.dart new file mode 100644 index 0000000..c086913 --- /dev/null +++ b/lib/pages/location/map_selection_widget.dart @@ -0,0 +1,59 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +class AppMap extends StatefulWidget { + final CameraPositionCallback onCameraMove; + Map initialCamera; + + late AppMapState _state; + final Function onMapCreated; + + AppMap(this.initialCamera, {required this.onCameraMove, required this.onMapCreated}); + + @override + State createState() => _state = AppMapState(); + + moveTo({required CameraPosition cameraPostion}) { + _state.googleMapController.animateCamera(CameraUpdate.newCameraPosition(cameraPostion)); + } +} + +class AppMapState extends State { + bool isHuawei = false; + + Completer _googleMapControllerComp = Completer(); + late GoogleMapController googleMapController; + + checkIsHuawei() async { + setState(() {}); + } + + @override + void initState() {} + + @override + Widget build(BuildContext context) { + if (isHuawei == null) return CircularProgressIndicator(); + return googleMap(); + } + + Widget googleMap() { + return GoogleMap( + mapType: MapType.normal, + zoomControlsEnabled: true, + myLocationButtonEnabled: true, + myLocationEnabled: true, + initialCameraPosition: CameraPosition.fromMap(widget.initialCamera) ?? CameraPosition(target: LatLng(-26.1711459, 27.9002758), zoom: 2.0), + onCameraMove: widget.onCameraMove, + onMapCreated: (GoogleMapController controller) { + googleMapController = controller; + _googleMapControllerComp.complete(controller); + widget.onMapCreated(); + }, + ); + } +} diff --git a/lib/pages/location/pick_location_page.dart b/lib/pages/location/pick_location_page.dart new file mode 100644 index 0000000..933d4f9 --- /dev/null +++ b/lib/pages/location/pick_location_page.dart @@ -0,0 +1,156 @@ +import 'dart:async'; + +import 'package:car_provider_app/utils/navigator.dart'; +import 'package:car_provider_app/widgets/show_fill_button.dart'; +import 'package:flutter/material.dart'; +import 'package:geocoding/geocoding.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import 'map_selection_widget.dart'; + +class PickLocationPage extends StatefulWidget { + Function(double, double, String) onPickAddress; + + PickLocationPage({required this.onPickAddress}); + + @override + State createState() => _PickLocationPageState(); +} + +class _PickLocationPageState extends State { + double latitude = 0; + double longitude = 0; + + final Set markers = new Set(); + late AppMap appMap; + + static CameraPosition _kGooglePlex = CameraPosition( + target: LatLng(37.42796133580664, -122.085749655962), + zoom: 14.4746, + ); + late LatLng currentPostion; + Completer mapController = Completer(); + final ValueNotifier _counter = ValueNotifier(""); + + @override + void initState() { + appMap = AppMap( + _kGooglePlex.toMap() as Map, + onCameraMove: (camera) { + _updatePosition(camera); + }, + onMapCreated: () { + // goToCurrentLocation(); + _getUserLocation(); + setState(() {}); + }, + ); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Pick Location"), + ), + body: Container( + child: Stack( + children: [ + if (appMap != null) appMap, + ValueListenableBuilder( + builder: (BuildContext context, String value, Widget? child) { + // This builder will only get called when the _counter + // is updated. + return value.isNotEmpty + ? Container( + width: double.infinity, + margin: EdgeInsets.all(12), + child: Card( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Text(value ?? ""), + )), + ) + : Container(); + }, + valueListenable: _counter, + ), + Align( + alignment: Alignment.center, + child: Icon( + Icons.place, + color: Colors.red, + size: 50, + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: "Pick Address", + onPressed: () { + widget.onPickAddress(latitude, longitude, _counter.value); + pop(context); + }, + ), + ), + ), + ], + ), + ), + ); + } + + Future _updatePosition(CameraPosition _position) async { + latitude = _position.target.latitude; + longitude = _position.target.longitude; + List placemarks = await placemarkFromCoordinates(latitude, longitude); + _counter.value = (placemarks.first.name) ?? "" + " " + (placemarks.first.street ?? "") + " " + (placemarks.first.country ?? ""); + } + + void _getUserLocation() async { + if (await Permission.location.request().isGranted) { + var position = await GeolocatorPlatform.instance.getCurrentPosition(); + currentPostion = LatLng(position.latitude, position.longitude); + latitude = position.latitude; + longitude = position.longitude; + setMap(); + } else { + requestPermissions().then( + (value) async { + if (value[Permission.location]!.isGranted) { + var position = await GeolocatorPlatform.instance.getCurrentPosition(); + currentPostion = LatLng(position.latitude, position.longitude); + latitude = position.latitude; + longitude = position.longitude; + setMap(); + } + }, + ); + } + } + + setMap() { + setState(() { + _kGooglePlex = CameraPosition( + target: currentPostion, + zoom: 14.4746, + ); + appMap.moveTo(cameraPostion: _kGooglePlex); + }); + } + + Future getCurrentAddress() async { + List placemarks = await placemarkFromCoordinates(latitude, longitude); + return placemarks.first.name ?? ""; + } +} + +Future> requestPermissions() async { + var permissionResults = [Permission.calendar].request(); + return permissionResults; +} diff --git a/lib/pages/settings/create_services_page.dart b/lib/pages/settings/create_services_page.dart new file mode 100644 index 0000000..847f82e --- /dev/null +++ b/lib/pages/settings/create_services_page.dart @@ -0,0 +1,185 @@ +import 'package:car_provider_app/api/client/branch_api_client.dart'; +import 'package:car_provider_app/classes/utils.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/profile/categroy.dart'; +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:flutter/material.dart'; +import 'package:car_provider_app/extensions/int_extensions.dart'; +import 'package:car_provider_app/extensions/string_extensions.dart'; + +class CreateServicesPage extends StatefulWidget { + @override + State createState() => _CreateServicesPageState(); +} + +class _CreateServicesPageState extends State { + String? branchName; + int categoryId = -1, branchId = -1; + + List countryDropList = []; + List categoryDropList = []; + + Branch? branch; + Category? category; + Services? services; + + @override + void initState() { + // TODO: implement initState + super.initState(); + fetchBranches(); + } + + fetchBranches() async { + branch = await BranchApiClent().fetchAllBranches(); + setState(() { + branch!.data?.forEach((element) { + countryDropList.add(new DropValue(element.id ?? 0, ((element.branchName!.isEmpty ? "N/A" : element.branchName) ?? "N/A"), "")); + }); + }); + } + + fetchBrancheCategory() async { + 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"), "")); + }); + }); + } + + fetchServices() async { + services = await BranchApiClent().fetchServices(categoryId.toString()); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Define Services"), + ), + body: Container( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + children: [ + branch != null + ? DropdownField((DropValue value) { + setState(() { + // countryCode = value.subValue; + // countryId = value.id; + // fetchCites(); + branchId = value.id; + fetchBrancheCategory(); + }); + }, list: countryDropList, hint: "Select Branch") + : CircularProgressIndicator(), + 12.height, + (category != null) + ? DropdownField((DropValue value) { + setState(() { + // countryCode = value.subValue; + // countryId = value.id; + // fetchCites(); + categoryId = value.id; + fetchServices(); + }); + }, list: categoryDropList, hint: "Select Service Category") + : branchId == -1 + ? Container() + : CircularProgressIndicator(), + 12.height, + if (services != null) + ListView.separated( + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Checkbox( + value: services!.data![index].isSelected, + onChanged: (v) { + setState(() { + services!.data![index].isSelected = v; + }); + }, + ), + 12.width, + (services!.data![index].description ?? "").toText12() + ], + ), + ); + }, + separatorBuilder: (context, index) { + return 1.height; + }, + itemCount: services!.data!.length, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + ) + ], + ), + ), + ), + ), + if (checkServicesSelection()) + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: "Save", + width: double.infinity, + onPressed: () { + createService(); + }, + ), + ), + ], + ), + ), + ); + } + + bool checkServicesSelection() { + bool isServiceSelected = false; + try { + services!.data!.forEach((element) { + if (element.isSelected ?? false) isServiceSelected = true; + }); + } catch (e) { + isServiceSelected = false; + } + + return isServiceSelected; + } + + createService() async { + List> map = []; + for (int i = 0; i < services!.data!.length; i++) { + if (services!.data![i].isSelected ?? false) { + var postParams = { + // "id": services!.data![i].id, + "providerBranchID": branchId, + "serviceID": services!.data![i].id, + "isAllowAppointment": true, + "isActive": true + }; + map.add(postParams); + } + } + Utils.showLoading(context); + MResponse mResponse = await BranchApiClent().createService(map); + Utils.hideLoading(context); + Utils.showToast(mResponse.message ?? ""); + } +} diff --git a/lib/pages/settings/dealership_page.dart b/lib/pages/settings/dealership_page.dart new file mode 100644 index 0000000..76de101 --- /dev/null +++ b/lib/pages/settings/dealership_page.dart @@ -0,0 +1,50 @@ +import 'package:car_provider_app/config/routes.dart'; +import 'package:car_provider_app/extensions/string_extensions.dart'; +import 'package:car_provider_app/utils/navigator.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class DealershipPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Dealership Setting"), + ), + body: Container( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + ListTile( + leading: SvgPicture.asset("assets/icons/ic_settings.svg"), + title: "General".toText12(), + ), + ListTile( + leading: SvgPicture.asset("assets/icons/ic_branchs.svg"), + title: "Define Branches".toText12(), + onTap: () { + navigateWithName(context, AppRoutes.defineBranch); + }, + ), + ListTile( + leading: SvgPicture.asset("assets/icons/ic_services.svg"), + title: "Define Services".toText12(), + onTap: () { + navigateWithName(context, AppRoutes.createServices); + }, + ), + ListTile( + leading: SvgPicture.asset("assets/icons/ic_provider.svg"), + title: "Define Providers".toText12(), + ), + ListTile( + leading: SvgPicture.asset("assets/icons/ic_close_account.svg"), + title: "Close Account".toText12(), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings/define_branch_page.dart b/lib/pages/settings/define_branch_page.dart new file mode 100644 index 0000000..b078fcf --- /dev/null +++ b/lib/pages/settings/define_branch_page.dart @@ -0,0 +1,163 @@ +import 'package:car_provider_app/api/client/branch_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/extensions/int_extensions.dart'; +import 'package:car_provider_app/models/m_response.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'; +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:flutter/material.dart'; + +class DefineBranchPage extends StatefulWidget { + @override + State createState() => _DefineBranchPageState(); +} + +class _DefineBranchPageState extends State { + String countryCode = "", address = "", branchName = "", branchDescription = ""; + double latitude = 0, longitude = 0; + int role = -1, countryId = -1, cityId = -1; + + List countryDropList = []; + List citiesDropList = []; + + Country? country; + Cities? cities; + + @override + void initState() { + // TODO: implement initState + super.initState(); + fetchCountry(); + } + + fetchCountry() async { + country = await UserApiClent().getAllCountries(); + setState(() { + country!.data?.forEach((element) { + countryDropList.add(new DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + }); + }); + } + + fetchCites() async { + cities = await UserApiClent().getAllCites(countryId.toString()); + setState(() { + cities!.data?.forEach((element) { + citiesDropList.add(new DropValue(element.id ?? 0, (element.cityName ?? ""), element.id.toString() ?? "")); + }); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + "Define Branch", + ), + ), + body: Container( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + children: [ + country != null + ? DropdownField((DropValue value) { + setState(() { + countryCode = value.subValue; + countryId = value.id; + fetchCites(); + }); + }, list: countryDropList, hint: "Chosse Country") + : CircularProgressIndicator(), + 12.height, + if (countryId != -1) + cities != null + ? DropdownField((DropValue value) { + setState(() { + // countryCode = value.subValue; + cityId = value.id; + }); + }, list: citiesDropList, hint: "Chosse City") + : CircularProgressIndicator(), + 12.height, + if (cityId != -1) + Column( + children: [ + TxtField( + hint: "Branch Name", + value: branchName, + onChanged: (v) { + branchName = v; + }, + ), + 12.height, + TxtField( + hint: "Branch Description", + value: branchDescription, + onChanged: (v) { + branchDescription = v; + }, + ), + 12.height, + TxtField( + hint: "Address", + isNeedClickAll: true, + maxLines: 5, + value: address, + // onChanged: (v) {}, + ), + 12.height, + ShowFillButton( + title: "Pick Address", + onPressed: () { + navigateTo( + context, + PickLocationPage( + onPickAddress: (double latitude, double longitude, String address) { + setState(() { + this.latitude = latitude; + this.longitude = longitude; + this.address = address; + }); + }, + ), + ); + }, + ), + ], + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: "Create Branch", + 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 ?? ""); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings/define_license_page.dart b/lib/pages/settings/define_license_page.dart new file mode 100644 index 0000000..2bbee50 --- /dev/null +++ b/lib/pages/settings/define_license_page.dart @@ -0,0 +1,126 @@ +import 'dart:convert'; +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/classes/utils.dart'; +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: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: Column( + children: [ + Expanded( + child: showWidget(), + ), + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: "Update", + 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"); + } else { + Utils.showToast(value.message ?? ""); + } + }); + }, + ), + ), + ], + ), + ), + ); + } + + 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 ?? ""); + + document!.data![index].document = convertFileToBase64(file); + document!.data![index].fileExt = checkFileExt(file.path); + setState(() { + document!.data![index].documentUrl = result.files.single.path ?? ""; + }); + } else { + // User canceled the picker + } + } +} 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 ecd1600..06ff1ed 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/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/utils/utils.dart b/lib/utils/utils.dart index 4b07a10..0f50532 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; @@ -8,6 +9,7 @@ import 'package:car_provider_app/widgets/extensions/int_extensions.dart'; import 'package:car_provider_app/widgets/extensions/string_extensions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:path/path.dart' as p; import 'package:sizer/sizer.dart'; Color getColorFromHex(String hexColor) { @@ -27,6 +29,17 @@ Widget spacerVertical(double v) { ); } +String convertFileToBase64(File file) { + List imageBytes = file.readAsBytesSync(); + return base64Encode(imageBytes); +} + +String checkFileExt(String path) { + String ex=p.extension(path); + var parts = ex.split('.'); + return parts[1]??"png"; // '.dart' +} + Future delay(int millis) async { return await Future.delayed(Duration(milliseconds: millis)); } 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..b0e4f93 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 @@ -140,6 +154,76 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "8.0.8" + geocoding: + dependency: "direct main" + description: + name: geocoding + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + geocoding_platform_interface: + dependency: transitive + description: + name: geocoding_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + geolocator: + dependency: "direct main" + description: + name: geolocator + url: "https://pub.dartlang.org" + source: hosted + version: "8.2.0" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1+1" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.3" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" + google_maps_flutter: + dependency: "direct main" + description: + name: google_maps_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + google_maps_flutter_platform_interface: + dependency: transitive + description: + name: google_maps_flutter_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" http: dependency: "direct main" description: @@ -216,14 +300,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: @@ -279,7 +363,21 @@ packages: name: permission_handler url: "https://pub.dartlang.org" source: hosted - version: "7.1.0" + version: "9.2.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + url: "https://pub.dartlang.org" + source: hosted + version: "9.0.2" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + url: "https://pub.dartlang.org" + source: hosted + version: "9.0.2" permission_handler_platform_interface: dependency: transitive description: @@ -287,6 +385,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.7.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" petitparser: dependency: transitive description: @@ -307,7 +412,7 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.1.2" process: dependency: transitive description: @@ -411,6 +516,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -475,5 +587,5 @@ packages: source: hosted version: "5.3.1" sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=2.5.0" + dart: ">=2.15.0 <3.0.0" + flutter: ">=2.8.0" diff --git a/pubspec.yaml b/pubspec.yaml index 61ec9bf..d9cf5ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,11 +39,20 @@ dependencies: provider: ^6.0.0 easy_localization: ^3.0.0 http: ^0.13.3 - permission_handler: 7.1.0 - flutter_svg: ^0.22.0 + permission_handler: ^9.2.0 + flutter_svg: ^1.0.3 sizer: ^2.0.15 fluttertoast: ^8.0.8 shared_preferences: ^2.0.6 + file_picker: ^4.4.0 + + + # google + google_maps_flutter: ^2.1.1 + geolocator: any + geocoding: ^2.0.2 + + dev_dependencies: flutter_test: