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/lib/api/api_client.dart b/lib/api/api_client.dart index e2433be..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); } } @@ -155,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); } } 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 index 68227c5..588f3ee 100644 --- a/lib/api/client/profile_api_client.dart +++ b/lib/api/client/profile_api_client.dart @@ -1,5 +1,6 @@ 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'; @@ -29,12 +30,24 @@ class ProfileApiClent { 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); + 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/client/user_api_client.dart b/lib/api/client/user_api_client.dart index 135b017..03add70 100644 --- a/lib/api/client/user_api_client.dart +++ b/lib/api/client/user_api_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import '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:http/http.dart'; @@ -64,8 +65,14 @@ class UserApiClent { 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 { - var postParams = {}; return await ApiClient().getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); } } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 3b12d24..9df397b 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -14,10 +14,19 @@ class ApiConsts { 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"; //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 { diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 6b5deea..092114b 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,12 +1,15 @@ import 'package:car_provider_app/models/user/register_user.dart'; import 'package:car_provider_app/pages/dashboard/dashboard_page.dart'; +import 'package:car_provider_app/pages/settings/create_services_page.dart'; +import 'package:car_provider_app/pages/settings/dealership_page.dart'; +import 'package:car_provider_app/pages/settings/define_branch_page.dart'; import 'package:car_provider_app/pages/user/complete_profile_page.dart'; import 'package:car_provider_app/pages/user/forget_password_page.dart'; 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/settings/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'; @@ -33,6 +36,11 @@ class AppRoutes { 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 = { @@ -53,5 +61,10 @@ class AppRoutes { //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 index ff568c9..da082b3 100644 --- a/lib/models/profile/document.dart +++ b/lib/models/profile/document.dart @@ -17,13 +17,13 @@ class Document { }); int? totalItemsCount; - List? data; + 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))), + 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"], ); @@ -36,8 +36,8 @@ class Document { }; } -class Datum { - Datum({ +class DocumentData { + DocumentData({ this.id, this.serviceProviderId, this.documentId, @@ -46,6 +46,7 @@ class Datum { this.comment, this.isActive, this.document, + this.fileExt, }); int? id; @@ -56,8 +57,9 @@ class Datum { dynamic? comment; bool? isActive; String? document; + String? fileExt; - factory Datum.fromJson(Map json) => Datum( + 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"], @@ -66,6 +68,7 @@ class Datum { comment: json["comment"], isActive: json["isActive"] == null ? null : json["isActive"], document: null, + fileExt: null, ); Map toJson() => { 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/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/pages/dashboard/dashboard_page.dart b/lib/pages/dashboard/dashboard_page.dart index b9ed74e..6097ed0 100644 --- a/lib/pages/dashboard/dashboard_page.dart +++ b/lib/pages/dashboard/dashboard_page.dart @@ -101,6 +101,9 @@ class _DashboardPageState extends State { 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"), 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/user/profile/define_license_page.dart b/lib/pages/settings/define_license_page.dart similarity index 70% rename from lib/pages/user/profile/define_license_page.dart rename to lib/pages/settings/define_license_page.dart index e54076c..2bbee50 100644 --- a/lib/pages/user/profile/define_license_page.dart +++ b/lib/pages/settings/define_license_page.dart @@ -1,8 +1,12 @@ +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'; @@ -37,7 +41,31 @@ class _DefineLicensePageState extends State { body: Container( width: double.infinity, height: double.infinity, - child: showWidget(), + 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 ?? ""); + } + }); + }, + ), + ), + ], + ), ), ); } @@ -86,6 +114,8 @@ class _DefineLicensePageState extends State { 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 ?? ""; }); 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/pubspec.lock b/pubspec.lock index 66b0312..b0e4f93 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -154,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: @@ -293,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: @@ -301,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: @@ -321,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: @@ -425,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: @@ -489,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 cc926b4..d9cf5ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,7 +39,7 @@ dependencies: provider: ^6.0.0 easy_localization: ^3.0.0 http: ^0.13.3 - permission_handler: 7.1.0 + permission_handler: ^9.2.0 flutter_svg: ^1.0.3 sizer: ^2.0.15 fluttertoast: ^8.0.8 @@ -47,6 +47,13 @@ dependencies: file_picker: ^4.4.0 + # google + google_maps_flutter: ^2.1.1 + geolocator: any + geocoding: ^2.0.2 + + + dev_dependencies: flutter_test: sdk: flutter