diff --git a/assets/icons/ic_ads.svg b/assets/icons/ic_ads.svg new file mode 100644 index 0000000..dad55fd --- /dev/null +++ b/assets/icons/ic_ads.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/ic_appoinments.svg b/assets/icons/ic_appoinments.svg new file mode 100644 index 0000000..ebf91e9 --- /dev/null +++ b/assets/icons/ic_appoinments.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/ic_branches.svg b/assets/icons/ic_branches.svg new file mode 100644 index 0000000..c0ba51c --- /dev/null +++ b/assets/icons/ic_branches.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/ic_home.svg b/assets/icons/ic_home.svg new file mode 100644 index 0000000..758dd1b --- /dev/null +++ b/assets/icons/ic_home.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/ic_requests.svg b/assets/icons/ic_requests.svg new file mode 100644 index 0000000..c6fd34a --- /dev/null +++ b/assets/icons/ic_requests.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 4819948..8f999cb 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; import 'package:http/io_client.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/exceptions/api_exception.dart'; import 'package:mc_common_app/models/user/refresh_token.dart'; @@ -295,7 +295,7 @@ class ApiClientImp implements ApiClient { // Future refreshTokenAPI(String token, String refreshToken) async { // var postParams = {"token": token, "refreshToken": refreshToken}; -// // String t = AppStateCm().getUser.data!.accessToken ?? ""; +// // String t = AppState().getUser.data!.accessToken ?? ""; // return await postJsonForObject((json) => RefreshToken.fromJson(json), ApiConsts.RefreshToken, postParams); // } @@ -306,7 +306,7 @@ class ApiClientImp implements ApiClient { Future refreshTokenAPI(String token, String refreshToken) async { var postParams = {"token": token, "refreshToken": refreshToken}; - // String t = AppStateCm().getUser.data!.accessToken ?? ""; + // String t = AppState().getUser.data!.accessToken ?? ""; return await postJsonForObject((json) => RefreshToken.fromJson(json), ApiConsts.RefreshToken, postParams); } @@ -320,7 +320,7 @@ class ApiClientImp implements ApiClient { UserInfo info = UserInfo.fromJson(jsonDecode(mdata)); User user = User(); user.data = UserData(accessToken: refresh.data!.accessToken ?? "", refreshToken: refresh.data!.refreshToken ?? "", userInfo: info); - AppStateCm().setUser = user; + AppState().setUser = user; return refresh.data!.accessToken??""; } } diff --git a/lib/classes/app_state_cm.dart b/lib/classes/app_state.dart similarity index 62% rename from lib/classes/app_state_cm.dart rename to lib/classes/app_state.dart index dcd2f86..32a5f71 100644 --- a/lib/classes/app_state_cm.dart +++ b/lib/classes/app_state.dart @@ -1,16 +1,15 @@ - -import 'package:injector/injector.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:mc_common_app/models/post_params_model.dart'; import 'package:mc_common_app/models/user/user.dart'; -class AppStateCm { - static final AppStateCm _instance = AppStateCm._internal(); +class AppState { + static final AppState _instance = AppState._internal(); - AppStateCm._internal(); + AppState._internal(); - factory AppStateCm() => _instance; + factory AppState() => _instance; bool isLogged = false; @@ -32,4 +31,11 @@ class AppStateCm { void setPostParamsModel(PostParamsModel _postParams) { this._postParams = _postParams; } + + LatLng currentLocation = const LatLng(0, 0); + + set setCurrentLocation(v) => currentLocation = v; + + LatLng get getCurrentLocation => currentLocation; + } diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index f08f443..5c5854e 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -37,11 +37,17 @@ class ApiConsts { static String ServiceProviderDocument_Update = baseUrlServices + "api/ServiceProviders/ServiceProviderDocument_Update"; //Branch + static String getProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Get"; static String createProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Create"; + static String updateProviderBranch = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Update"; static String ServiceProviderBranchGet = baseUrlServices + "api/ServiceProviders/ServiceProviderBranch_Get"; static String ServiceCategory_Get = baseUrlServices + "api/Master/ServiceCategory_Get"; static String Services_Get = baseUrlServices + "api/ServiceProviders/Services_Get"; static String ServiceProviderService_Create = baseUrlServices + "api/ServiceProviders/ServiceProviderService_Create"; + static String ServiceProviderService_Update = baseUrlServices + "api/ServiceProviders/ServiceProviderService_Update"; + + static String ServiceProviderService_Get= baseUrlServices + "api/ServiceProviders/ServiceProviderService_Get"; + static String BranchesAndServices= baseUrlServices + "api/ServiceProviders/ServiceProviderDetail_Get"; } class GlobalConsts { diff --git a/lib/config/dependencies.dart b/lib/config/dependencies.dart index 857bc62..c9710dc 100644 --- a/lib/config/dependencies.dart +++ b/lib/config/dependencies.dart @@ -5,7 +5,7 @@ import 'package:injector/injector.dart'; import 'package:mc_common_app/api/api_client.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/repositories/user_repo.dart'; import 'package:mc_common_app/services/services.dart'; @@ -15,7 +15,7 @@ class AppDependencies { static void addDependencies() { //services - injector.registerSingleton(() => AppStateCm()); + injector.registerSingleton(() => AppState()); injector.registerSingleton(() => ApiClientImp()); injector.registerSingleton(() => CommonServicesImp()); diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 0c17e79..8d47fa8 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -42,7 +42,6 @@ class AppRoutes { static const String profile3 = "/profile3"; static const String verifyPassword = "/vertifyPassword"; static const String confirmNewPasswordPage = "/confirmNewPasswordPage"; - static const String defineLicense = "/defineLicese"; static const String changePassword = "/changePassword"; static const String forgetPasswordMethodPage = "/forgetPasswordMethodPage"; static const String changeMobilePage = "/changeMobilePage"; @@ -51,10 +50,7 @@ class AppRoutes { static const String dashboard = "/dashboard"; - //settings - static const String dealershipSetting = "/dealershipSetting"; - static const String defineBranch = "/defineBranch"; - static const String createServices = "/createServices"; + static const String initialRoute = splash; diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart deleted file mode 100644 index 474cbee..0000000 --- a/lib/extensions/widget_extensions.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; - -extension WidgetExtensions on Widget { - Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); - - Widget paddingAll(double _value) => Padding(padding: EdgeInsets.all(_value), child: this); - - Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) => - Padding(padding: EdgeInsets.only(left: left, right: right, top: top, bottom: bottom), child: this); -} diff --git a/lib/main.dart b/lib/main.dart index 9ad34b6..4b2e9ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,9 +3,11 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/theme/app_theme.dart'; import 'package:injector/injector.dart'; @@ -14,7 +16,7 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:sizer/sizer.dart'; -late AppStateCm appStateCm; +late AppState appState; final navigatorKey = GlobalKey(); @@ -35,7 +37,7 @@ Future main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - // AppStateCm().setPostParamsInitConfig(); + // AppState().setPostParamsInitConfig(); HttpOverrides.global = MyHttpOverrides(); runApp( @@ -72,7 +74,7 @@ class MyApp extends StatelessWidget { DeviceType deviceType, ) { List> delegates = context.localizationDelegates; - // AppStateCm().setPostParamsModel( + // AppState().setPostParamsModel( // PostParamsModel( // languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, // ), @@ -97,8 +99,8 @@ class MyApp extends StatelessWidget { // class MyApp extends StatelessWidget { // MyApp({super.key}) { // AppDependencies.addDependencies(); -// AppStateCm = Injector.appInstance.get(); -// // AppStateCm.setPostParamsInitConfig(); +// AppState = Injector.appInstance.get(); +// // AppState.setPostParamsInitConfig(); // } // // @override @@ -112,7 +114,7 @@ class MyApp extends StatelessWidget { // ) { // SizeConfig().init(constraints, orientation); // List> delegates = context.localizationDelegates; -// // AppStateCm().setPostParamsModel( +// // AppState().setPostParamsModel( // // PostParamsModel( // // languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, // // ), diff --git a/lib/models/account.dart b/lib/models/account.dart index 699bfba..ecafb24 100644 --- a/lib/models/account.dart +++ b/lib/models/account.dart @@ -28,17 +28,17 @@ class Account { : List.from( json["parentList"].map((x) => ParentList.fromJson(x))), selectedItem: - json["selectedItem"], + json["selectedItem"] == null ? null : json["selectedItem"], ); Map toJson() => { "parentList": parentList == null ? null : List.from(parentList!.map((x) => x.toJson())), - "selectedItem": selectedItem, + "selectedItem": selectedItem == null ? null : selectedItem, }; Map toJsonData() => { - "selectedItem": selectedItem, + "selectedItem": selectedItem == null ? null : selectedItem, }; } diff --git a/lib/models/model/branch2.dart b/lib/models/model/branch2.dart new file mode 100644 index 0000000..dd9df37 --- /dev/null +++ b/lib/models/model/branch2.dart @@ -0,0 +1,184 @@ +// To parse this JSON data, do +// +// final branch2 = branch2FromJson(jsonString); + +import 'dart:convert'; + +import 'package:mc_common_app/models/profile/categroy.dart'; + + + +Branch2 branch2FromJson(String str) => Branch2.fromJson(json.decode(str)); + +String branch2ToJson(Branch2 data) => json.encode(data.toJson()); + +class Branch2 { + Branch2({ + this.messageStatus, + this.totalItemsCount, + this.data, + this.message, + }); + + final int? messageStatus; + final int? totalItemsCount; + final Data? data; + final String? message; + + factory Branch2.fromJson(Map json) => Branch2( + messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], + totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + data: json["data"] == null ? null : Data.fromJson(json["data"]), + message: json["message"] == null ? null : json["message"], + ); + + Map toJson() => { + "messageStatus": messageStatus == null ? null : messageStatus, + "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "data": data == null ? null : data!.toJson(), + "message": message == null ? null : message, + }; +} + +class Data { + Data({ + this.id, + this.companyName, + this.countryName, + this.companyDescription, + this.allDocStatus, + this.isValidSubscription, + this.userId, + this.serviceProviderBranch, + this.countryID, + }); + + final int? id; + final String? companyName; + final String? countryName; + int? countryID; + final String? companyDescription; + final int? allDocStatus; + final bool? isValidSubscription; + final String? userId; + final List? serviceProviderBranch; + + factory Data.fromJson(Map json) => Data( + id: json["id"] == null ? null : json["id"], + companyName: json["companyName"] == null ? null : json["companyName"], + countryName: json["countryName"] == null ? null : json["countryName"], + countryID: json["countryID"] == null ? null : json["countryID"], + companyDescription: json["companyDescription"] == null ? null : json["companyDescription"], + allDocStatus: json["allDocStatus"] == null ? null : json["allDocStatus"], + isValidSubscription: json["isValidSubscription"] == null ? null : json["isValidSubscription"], + userId: json["userID"] == null ? null : json["userID"], + serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => ServiceProviderBranch.fromJson(x))), + ); + + Map toJson() => { + "id": id == null ? null : id, + "companyName": companyName == null ? null : companyName, + "companyDescription": companyDescription == null ? null : companyDescription, + "allDocStatus": allDocStatus == null ? null : allDocStatus, + "isValidSubscription": isValidSubscription == null ? null : isValidSubscription, + "userID": userId == null ? null : userId, + "serviceProviderBranch": serviceProviderBranch == null ? null : List.from(serviceProviderBranch!.map((x) => x.toJson())), + }; +} + +class ServiceProviderBranch { + ServiceProviderBranch({ + this.id, + this.cityId, + this.cityName, + this.branchName, + this.branchDescription, + this.address, + this.latitude, + this.longitude, + this.status, + this.serviceProviderServices, + this.countryID, + this.countryName, + this.categories, + }); + + final int? id; + int? countryID; + String? countryName; + final int? cityId; + final dynamic? cityName; + final String? branchName; + final String? branchDescription; + final String? address; + final String? latitude; + final String? longitude; + final int? status; + final List? serviceProviderServices; + List? categories; + + factory ServiceProviderBranch.fromJson(Map json) => ServiceProviderBranch( + id: json["id"] == null ? null : json["id"], + countryID: 0, + countryName: "", + cityId: json["cityID"] == null ? null : json["cityID"], + cityName: json["cityName"], + branchName: json["branchName"] == null ? null : json["branchName"], + branchDescription: json["branchDescription"] == null ? null : json["branchDescription"], + 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"], + serviceProviderServices: json["serviceProviderServices"] == null ? null : List.from(json["serviceProviderServices"].map((x) => ServiceProviderService.fromJson(x))), + categories: [], + ); + + Map toJson() => { + "id": id == null ? null : id, + "cityID": cityId == null ? null : cityId, + "cityName": cityName, + "branchName": branchName == null ? null : branchName, + "branchDescription": branchDescription == null ? null : branchDescription, + "address": address == null ? null : address, + "latitude": latitude == null ? null : latitude, + "longitude": longitude == null ? null : longitude, + "status": status == null ? null : status, + "serviceProviderServices": serviceProviderServices == null ? null : List.from(serviceProviderServices!.map((x) => x.toJson())), + }; +} + +class ServiceProviderService { + ServiceProviderService({ + this.serviceId, + this.serviceName, + this.serviceNameN, + this.categoryId, + this.categoryName, + this.serviceStatus, + }); + + final int? serviceId; + final String? serviceName; + final String? serviceNameN; + final int? categoryId; + final String? categoryName; + final int? serviceStatus; + + factory ServiceProviderService.fromJson(Map json) => ServiceProviderService( + serviceId: json["serviceID"] == null ? null : json["serviceID"], + serviceName: json["serviceName"] == null ? null : json["serviceName"], + serviceNameN: json["serviceNameN"] == null ? null : json["serviceNameN"], + categoryId: json["categoryID"] == null ? null : json["categoryID"], + categoryName: json["categoryName"] == null ? null : json["categoryName"], + serviceStatus: json["serviceStatus"] == null ? null : json["serviceStatus"], + ); + + Map toJson() => { + "serviceID": serviceId == null ? null : serviceId, + "serviceName": serviceName == null ? null : serviceName, + "serviceNameN": serviceNameN == null ? null : serviceNameN, + "categoryID": categoryId == null ? null : categoryId, + "categoryName": categoryName == null ? null : categoryName, + "serviceStatus": serviceStatus == null ? null : serviceStatus, + }; +} diff --git a/lib/models/profile/categroy.dart b/lib/models/profile/categroy.dart index 6f566f1..25fd487 100644 --- a/lib/models/profile/categroy.dart +++ b/lib/models/profile/categroy.dart @@ -4,6 +4,9 @@ import 'dart:convert'; +import 'package:equatable/equatable.dart'; +import 'package:mc_common_app/models/model/branch2.dart'; + Category categoryFromJson(String str) => Category.fromJson(json.decode(str)); String categoryToJson(Category data) => json.encode(data.toJson()); @@ -22,27 +25,29 @@ class Category { 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"], - ); + 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, - }; + "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 { +// ignore: must_be_immutable +class CategoryData extends Equatable { CategoryData({ this.id, this.categoryName, this.categoryNameN, this.serviceCategoryIconUrl, this.serviceCategoryImageUrl, + this.services, }); int? id; @@ -50,20 +55,25 @@ class CategoryData { String? categoryNameN; dynamic? serviceCategoryIconUrl; dynamic? serviceCategoryImageUrl; + List? services; 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"], - ); + 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"], + services: [], + ); Map toJson() => { - "id": id == null ? null : id, - "categoryName": categoryName == null ? null : categoryName, - "categoryNameN": categoryNameN == null ? null : categoryNameN, - "serviceCategoryIconUrl": serviceCategoryIconUrl, - "serviceCategoryImageUrl": serviceCategoryImageUrl, - }; + "id": id == null ? null : id, + "categoryName": categoryName == null ? null : categoryName, + "categoryNameN": categoryNameN == null ? null : categoryNameN, + "serviceCategoryIconUrl": serviceCategoryIconUrl, + "serviceCategoryImageUrl": serviceCategoryImageUrl, + }; + + @override + List get props => [id ?? 0]; } diff --git a/lib/models/profile/document.dart b/lib/models/profile/document.dart index da082b3..0876cb0 100644 --- a/lib/models/profile/document.dart +++ b/lib/models/profile/document.dart @@ -47,6 +47,7 @@ class DocumentData { this.isActive, this.document, this.fileExt, + this.documentName, }); int? id; @@ -58,6 +59,7 @@ class DocumentData { bool? isActive; String? document; String? fileExt; + String? documentName; factory DocumentData.fromJson(Map json) => DocumentData( id: json["id"] == null ? null : json["id"], @@ -69,6 +71,7 @@ class DocumentData { isActive: json["isActive"] == null ? null : json["isActive"], document: null, fileExt: null, + documentName: json["documentName"] == null ? null : json["documentName"], ); Map toJson() => { diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index 8b13789..a61bb90 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -1 +1,35 @@ +import 'package:mc_common_app/api/api_client.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/models/user/cities.dart'; +import 'package:mc_common_app/models/user/country.dart'; +import 'package:mc_common_app/models/user/role.dart'; + +abstract class CommonRepo { + Future getAllCountries(); + + Future getAllCites(String countryId); + + Future getRoles(); +} + +class CommonRepoImp implements CommonRepo { + @override + Future getAllCountries() async { + return await injector.get().getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry); + } + + @override + Future getAllCites(String countryId) async { + var postParams = { + "CountryID": countryId, + }; + return await injector.get().getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams); + } + + @override + Future getRoles() async { + return await injector.get().getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); + } +} \ No newline at end of file diff --git a/lib/repositories/dashboard_repo.dart b/lib/repositories/dashboard_repo.dart deleted file mode 100644 index e69de29..0000000 diff --git a/lib/repositories/user_repo.dart b/lib/repositories/user_repo.dart index 4bed7d6..278cf92 100644 --- a/lib/repositories/user_repo.dart +++ b/lib/repositories/user_repo.dart @@ -4,7 +4,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; import 'package:mc_common_app/api/api_client.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; import 'package:mc_common_app/models/m_response.dart'; @@ -134,7 +134,7 @@ class UserRepoImp implements UserRepo { @override Future refreshTokenAPI(String token, String refreshToken) async { var postParams = {"token": token, "refreshToken": refreshToken}; - // String t = AppStateCm().getUser.data!.accessToken ?? ""; + // String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => RefreshToken.fromJson(json), ApiConsts.RefreshToken, postParams); } @@ -197,7 +197,7 @@ class UserRepoImp implements UserRepo { }; // return await injector.get().postJsonForResponse(ApiConsts.ChangePassword, postParams); - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; debugPrint("token " + t); return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ChangePassword, postParams, token: t); } @@ -205,7 +205,7 @@ class UserRepoImp implements UserRepo { @override Future changeMobileNoOTPRequest(countryID, String mobileNo, String password) async { var postParams = {"countryID": 1, "mobileNo": mobileNo, "password": password}; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => ChangeMobileRespModel.fromJson(json), ApiConsts.ChangeMobileNoOTPRequest, postParams, token: t); } @@ -215,21 +215,21 @@ class UserRepoImp implements UserRepo { "userToken": userToken, "userOTP": userOTP, }; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => ConfirmMobileRespModel.fromJson(json), ApiConsts.ChangeMobileNo, postParams, token: t); } @override Future changeEmailOTPRequest(String email, String password) async { var postParams = {"email": email, "password": password}; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => ChanEmailRespModel.fromJson(json), ApiConsts.ChangeEmailOTPRequest, postParams, token: t); } @override Future changeEmail(String userToken, String userOTP) async { var postParams = {"userToken": userToken, "userOTP": userOTP}; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => ConfirmEmailRespModel.fromJson(json), ApiConsts.ChangeEmail, postParams, token: t); } @@ -238,11 +238,11 @@ class UserRepoImp implements UserRepo { var postParams = { // "email": email, // "userID": userID, - "email": AppStateCm().getUser.data!.userInfo!.email ?? "", - "userID": AppStateCm().getUser.data!.userInfo!.userId ?? "", + "email": AppState().getUser.data!.userInfo!.email ?? "", + "userID": AppState().getUser.data!.userInfo!.userId ?? "", }; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => VerifyEmailRespModel.fromJson(json), ApiConsts.EmailVerify, postParams, token: t); } @@ -250,16 +250,16 @@ class UserRepoImp implements UserRepo { Future emailVerifyOTPVerify(String userToken, String userOTP) async { var postParams = {"userToken": userToken, "userOTP": userOTP}; - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.EmailVerifyOTPVerify, postParams, token: t); } @override Future updateUserImage(String image) async { - var postParams = {"userID": AppStateCm().getUser.data!.userInfo!.userId, "userImage": image}; + var postParams = {"userID": AppState().getUser.data!.userInfo!.userId, "userImage": image}; // return await injector.get().postJsonForResponse(ApiConsts.ChangePassword, postParams); - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; debugPrint("token " + t); return await injector.get().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t); } @@ -269,7 +269,7 @@ class UserRepoImp implements UserRepo { var postParams = {}; // return await injector.get().postJsonForResponse(ApiConsts.ChangePassword, postParams); - String t = AppStateCm().getUser.data!.accessToken ?? ""; + String t = AppState().getUser.data!.accessToken ?? ""; debugPrint("token " + t); return await injector.get().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t); } @@ -285,7 +285,7 @@ class UserRepoImp implements UserRepo { UserInfo info = UserInfo.fromJson(jsonDecode(mdata)); User user = User(); user.data = UserData(accessToken: refresh.data!.accessToken ?? "", refreshToken: refresh.data!.refreshToken ?? "", userInfo: info); - AppStateCm().setUser = user; + AppState().setUser = user; return refresh.data!.accessToken ?? ""; } } diff --git a/lib/services/services.dart b/lib/services/services.dart index 8dd371f..c1e72f7 100644 --- a/lib/services/services.dart +++ b/lib/services/services.dart @@ -1,9 +1,13 @@ import 'dart:io'; +import 'package:file_picker/file_picker.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:mc_common_app/utils/utils.dart'; abstract class CommonServices { Future pickImageFromPhone(int sourceFlag); + + Future pickFile({FileType fileType = FileType.custom, List? allowedExtensions}); } class CommonServicesImp implements CommonServices { @@ -16,4 +20,23 @@ class CommonServicesImp implements CommonServices { final pickedImageFile = File(pickedImage!.path); return pickedImageFile; } -} \ No newline at end of file + + @override + Future pickFile({FileType fileType = FileType.custom, List? allowedExtensions}) async { + FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg']); + + if (result != null) { + File file = File(result.files.single.path ?? ""); + int sizeInBytes = file.lengthSync(); + // double sizeInMb = sizeInBytes / (1024 * 1024); + if (sizeInBytes > 1000) { + Utils.showToast("File is larger then 1KB"); + } else { + return file; + } + } else { + // User canceled the picker + return null; + } + } +} diff --git a/lib/utils/permission_handler.dart b/lib/utils/AppPermissionHandler.dart similarity index 63% rename from lib/utils/permission_handler.dart rename to lib/utils/AppPermissionHandler.dart index 3e3877e..287e645 100644 --- a/lib/utils/permission_handler.dart +++ b/lib/utils/AppPermissionHandler.dart @@ -1,3 +1,4 @@ + import 'package:permission_handler/permission_handler.dart'; import 'dialogs.dart'; @@ -34,3 +35,33 @@ Future requestPermissionGranted( return false; } } + + +class AppPermissions{ + static void location(Function(bool) completion) { + Permission.location.isGranted.then((isGranted){ + if(!isGranted){ + Permission.location.request().then((granted){ + completion(granted == PermissionStatus.granted); + }); + } + completion(isGranted); + }); + + } + + static void checkAll(Function(bool) completion){ + [ + Permission.location + ].request().then((value){ + + bool allGranted = false; + value.values.forEach((element) { + allGranted = allGranted && element == PermissionStatus.granted; + }); + + completion(allGranted); + + }); + } +} \ No newline at end of file diff --git a/lib/utils/dialogs.dart b/lib/utils/dialogs.dart index c0fabd8..46409c5 100644 --- a/lib/utils/dialogs.dart +++ b/lib/utils/dialogs.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:mc_common_app/utils/AppPermissionHandler.dart'; + -import 'permission_handler.dart'; Future showConfirmDialogs( context, msg, positiveText, negativeText) async { diff --git a/lib/utils/location/Location.dart b/lib/utils/location/Location.dart new file mode 100644 index 0000000..b8ba710 --- /dev/null +++ b/lib/utils/location/Location.dart @@ -0,0 +1,249 @@ +import 'dart:async'; +import 'dart:math'; +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:geolocator/geolocator.dart'; + +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:mc_common_app/utils/AppPermissionHandler.dart'; + +import 'package:mc_common_app/utils/utils.dart'; + +// import 'package:geodesy/geodesy.dart' as geodesy; + +//Created By Mr.Zohaib +class Location { + static _Map map = _Map(); + + static void havePermission(Function(bool) callback) { + Geolocator.checkPermission().then((value) async { + if (value == LocationPermission.denied) { + value = await Geolocator.requestPermission(); + callback(![LocationPermission.denied, LocationPermission.deniedForever].contains(value)); + } else { + callback(true); + } + }); + } + + static void isEnabled(Function(bool) callback) { + Geolocator.isLocationServiceEnabled().then((value) => callback(value)); + } + + static bool _listeningSettingChange = true; + + static void listenGPS({bool change = true, Function(bool)? onChange}) async { + _listeningSettingChange = change; + if (change == false) return; + + Future.doWhile(() async { + await Utils.delay(1000); + var enable = await Geolocator.isLocationServiceEnabled(); + onChange!(enable); + return _listeningSettingChange; + }); + } + + static void getCurrentLocation(Function(LatLng?) callback) { + void done(Position position) { + //AppStorage.sp.saveLocation(position); + + LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude); + callback(myCurrentLocation); + } + + AppPermissions.location((granted) { + if (granted) { + Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) { + if (value == null) { + Geolocator.getCurrentPosition().then((value) { + done(value); + }); + } else { + done(value); + } + }); + } + }); + } + + // static LatLng locationAwayFrom( + // {required LatLng loc1, num distanceMeters = 200.0, num bearing = 270.0}) { + // geodesy.LatLng l1 = geodesy.LatLng(loc1.latitude, loc1.longitude); + // geodesy.LatLng destinationPoint = geodesy.Geodesy() + // .destinationPointByDistanceAndBearing(l1, distanceMeters, bearing); + // return LatLng(destinationPoint.latitude, destinationPoint.longitude); + // } + + static Future distanceTo(LatLng destination) async { + var myLoc = await Geolocator.getLastKnownPosition(); + var distance = 0.0; + if (myLoc != null) { + distance = Geolocator.distanceBetween(destination.latitude, destination.longitude, myLoc.latitude, myLoc.longitude); + } + return distance; + } +} + +class _Map { + Marker createMarker( + String id, { + required LatLng coordinates, + BitmapDescriptor? icon, + VoidCallback? onTap, + }) { + final MarkerId markerId = MarkerId(id); + return Marker( + icon: icon ?? BitmapDescriptor.defaultMarker, + markerId: markerId, + position: coordinates, + flat: false, + // infoWindow: InfoWindow(title: id, snippet: '*'), + onTap: onTap, + ); + } + + CameraPosition initialCamera({required Completer mapController, LatLng? position, double zoom = 12}) { + position = position ?? LatLng(24.7249303, 46.5416656); + CameraPosition riyadhEye = CameraPosition( + target: position, + zoom: zoom, + ); + mapController.future.then((controller) { + controller.animateCamera(CameraUpdate.newCameraPosition(riyadhEye)); + }); + return riyadhEye; + } + + CameraPosition moveTo(LatLng location, {double zoom = 12, double direction = 0.0, required Completer mapController, bool? animation}) { + var camera = CameraPosition(target: location, zoom: zoom, bearing: direction); + mapController.future.then((controller) { + animation ?? false ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera)); + }); + return camera; + } + + void moveCamera(CameraPosition camera, @required Completer mapController, bool animation) { + mapController.future.then((controller) { + animation ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera)); + }); + } + + void scrollBy({double x = 0, double y = 0, required Completer mapController, bool animation = true}) { + var camera = CameraUpdate.scrollBy(x, y); + mapController.future.then((controller) { + animation ? controller.animateCamera(camera) : controller.moveCamera(camera); + }); + } + + void goToCurrentLocation({Completer? mapController, double? direction = 0.0, bool? animation}) { + Location.getCurrentLocation((location) { + moveTo(location!, zoom: 17, mapController: mapController!, animation: animation, direction: direction!); + }); + } + + // var routes = Map(); + // + // void setRoutePolylines(LatLng? source, LatLng? destination, Set polylines, Completer mapController, Function(DirectionsRoute?) completion) { + // if (source == null || destination == null) { + // completion(null); + // return; + // } + // + // var origin = '${source.latitude},${source.longitude}'; + // var destin = '${destination.latitude},${destination.longitude}'; + // var routeId = '$origin->$destination'; + // + // void createPolyline(DirectionsRoute results) { + // List polylineCoordinates = results.overviewPath!.map((e) => LatLng(e.latitude, e.longitude)).toList(); + // PolylineId id = PolylineId("route"); + // Polyline polyline = Polyline( + // polylineId: id, + // color: accentColor, + // width: 5, + // jointType: JointType.round, + // startCap: Cap.roundCap, + // endCap: Cap.roundCap, + // points: polylineCoordinates, + // ); + // + // polylines.removeWhere((element) => true); + // polylines.add(polyline); + // + // LatLngBounds bound = getBounds(coordinates: polylineCoordinates); + // focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: 100); + // completion(routes[routeId]); + // } + // + // var availableRoute = routes[routeId]; + // if (availableRoute == null) { + // var request = DirectionsRequest(origin: origin, destination: destin); + // DirectionsService().route(request, (response, status) { + // if (status == DirectionsStatus.ok && response.routes!.isNotEmpty) { + // routes[routeId] = response.routes!.first; + // createPolyline(response.routes!.first); + // } + // }); + // } else { + // createPolyline(availableRoute); + // } + // } + + LatLngBounds getBounds({required List coordinates}) { + var lngs = coordinates.map((c) => c.longitude).toList(); + var lats = coordinates.map((c) => c.latitude).toList(); + + double bottomMost = lngs.reduce(min); + double topMost = lngs.reduce(max); + double leftMost = lats.reduce(min); + double rightMost = lats.reduce(max); + + LatLngBounds bounds = LatLngBounds( + northeast: LatLng(rightMost, topMost), + southwest: LatLng(leftMost, bottomMost), + ); + return bounds; + + double? x0, x1, y0, y1; + for (LatLng latLng in coordinates) { + if (x0 == null) { + x0 = x1 = latLng.latitude; + y0 = y1 = latLng.longitude; + } else { + if (latLng.latitude > x1!) x1 = latLng.latitude; + if (latLng.latitude < x0) x0 = latLng.latitude; + if (latLng.longitude > y1!) y1 = latLng.longitude; + if (latLng.longitude < y0!) y0 = latLng.longitude; + } + } + return LatLngBounds(northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!)); + } + + void focusCameraToLatLngBounds({LatLngBounds? bound, Completer? mapController, double? padding}) async { + if (bound == null) return; + + CameraUpdate camera = CameraUpdate.newLatLngBounds(bound, padding!); + final GoogleMapController controller = await mapController!.future; + controller.animateCamera(camera); + } + + void focusCameraTo2Points({LatLng? point1, LatLng? point2, Completer? mapController, double? padding}) async { + var source = point1; + var destination = point2; + if (source != null && destination != null) { + // 'package:google_maps_flutter_platform_interface/src/types/location.dart': Failed assertion: line 72 pos 16: 'southwest.latitude <= northeast.latitude': is not true. + LatLngBounds bound; + if (source.latitude <= destination.latitude) { + bound = LatLngBounds(southwest: source, northeast: destination); + } else { + bound = LatLngBounds(southwest: destination, northeast: source); + } + + if (bound == null) return; + + focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: padding); + } + } +} diff --git a/lib/utils/navigator.dart b/lib/utils/navigator.dart index ef3900c..58cd370 100644 --- a/lib/utils/navigator.dart +++ b/lib/utils/navigator.dart @@ -12,3 +12,7 @@ navigateReplaceWithName(BuildContext context, String routeName, {Object? argumen pop(BuildContext context) { Navigator.of(context).pop(); } + +navigateTo(context, page) { + Navigator.push(context, MaterialPageRoute(builder: (context) => page)); +} \ No newline at end of file diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 2438d79..bb4a190 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -2,9 +2,8 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; - import 'package:flutter/material.dart'; - +import 'package:path/path.dart' as p; import 'package:fluttertoast/fluttertoast.dart'; import 'package:mc_common_app/exceptions/api_exception.dart'; @@ -172,6 +171,12 @@ class Utils { ); } + static String checkFileExt(String path) { + String ex = p.extension(path); + var parts = ex.split('.'); + return parts[1] ?? "png"; // '.dart' + } + static spacer() { return const SizedBox( height: 8, @@ -300,7 +305,7 @@ class Utils { return regExp.hasMatch(value); } - static bool isEmailValid(String email) { + static bool isEmailValid(String email) { String p = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; RegExp regExp = RegExp(p); return regExp.hasMatch(email); diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 81eb08f..e8256ee 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -5,7 +5,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; @@ -251,7 +251,7 @@ class UserVM extends BaseVM { MResponse otpCompare = await userRepo.emailVerifyOTPVerify(otpRequest.data!.userToken ?? "", code); Utils.hideLoading(context); if (otpCompare.messageStatus == 1) { - AppStateCm().getUser.data!.userInfo!.isEmailVerified = true; + AppState().getUser.data!.userInfo!.isEmailVerified = true; Utils.showToast(LocaleKeys.emailVerified.tr()); } else { Utils.showToast(otpCompare.message ?? ""); @@ -335,7 +335,7 @@ class UserVM extends BaseVM { if (verifiedUser.messageStatus == 1) { User user = User.fromJson(jsonDecode(response2.body)); if (user.data!.userInfo!.roleId == 4) { - AppStateCm().setUser = user; + AppState().setUser = user; SharedPrefManager.setUserToken(user.data!.accessToken ?? ""); SharedPrefManager.setUserId(user.data!.userInfo!.userId ?? ""); SharedPrefManager.setRefreshToken(user.data!.refreshToken ?? ""); @@ -388,7 +388,7 @@ class UserVM extends BaseVM { RegisterUserRespModel verifiedUser = RegisterUserRespModel.fromJson(jsonDecode(response2.body)); if (verifiedUser.messageStatus == 1) { User user = User.fromJson(jsonDecode(response2.body)); - AppStateCm().setUser = user; + AppState().setUser = user; navigateReplaceWithName(context, AppRoutes.dashboard); } else { Utils.showToast(verifiedUser.message ?? ""); diff --git a/lib/views/user/edit_account_page.dart b/lib/views/user/edit_account_page.dart index ddeb756..91e42a7 100644 --- a/lib/views/user/edit_account_page.dart +++ b/lib/views/user/edit_account_page.dart @@ -1,4 +1,4 @@ -import 'package:mc_common_app/classes/app_state_cm.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; @@ -109,11 +109,11 @@ class _EditAccountPageState extends State { 20.width, Expanded(child: LocaleKeys.changeEmail.tr().toText(isBold: true, fontSize: 12)), InkWell( - child: ((AppStateCm().getUser.data!.userInfo!.isEmailVerified ?? false) ? LocaleKeys.verified.tr() : LocaleKeys.verify.tr()).toText( + child: ((AppState().getUser.data!.userInfo!.isEmailVerified ?? false) ? LocaleKeys.verified.tr() : LocaleKeys.verify.tr()).toText( color: Colors.green, fontSize: 12, ), - onTap: (AppStateCm().getUser.data!.userInfo!.isEmailVerified ?? false) + onTap: (AppState().getUser.data!.userInfo!.isEmailVerified ?? false) ? null : () async { await userVM.verifyEmail(context, email: email, userID: userID); diff --git a/lib/views/user/login_verification_page.dart b/lib/views/user/login_verification_page.dart index bbd0766..dd4dd61 100644 --- a/lib/views/user/login_verification_page.dart +++ b/lib/views/user/login_verification_page.dart @@ -27,7 +27,6 @@ class _LoginVerificationPageState extends State { @override void initState() { - // TODO: implement initState super.initState(); scheduleMicrotask(() async { userVM = Provider.of(context, listen: false); diff --git a/lib/views/user/register_provider_page.dart b/lib/views/user/register_provider_page.dart new file mode 100644 index 0000000..5f165d0 --- /dev/null +++ b/lib/views/user/register_provider_page.dart @@ -0,0 +1,425 @@ +import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/user/country.dart'; +import 'package:mc_common_app/models/user/role.dart'; +import 'package:mc_common_app/repositories/user_repo.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/view_models/user_view_model.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; + +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/show_fill_button.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/widgets/tab/role_type_tab.dart'; + +import 'package:provider/provider.dart'; +import '../../theme/colors.dart'; + +class RegisterPage extends StatefulWidget { + const RegisterPage({Key? key}) : super(key: key); + + @override + State createState() => _RegisterPageState(); +} + +class _RegisterPageState extends State { + String phoneNum = "", countryCode = ""; + + int role = -1, countryId = -1; + + TextEditingController emailController = TextEditingController(); + + Future? futureRoles; + Future? futureCountries; + + @override + void initState() { + super.initState(); + fetchData(); + } + + fetchData() { + UserRepo userRepo = injector.get(); + userRepo.getRoles().then((value) { + setState(() { + futureRoles = Future.value(value); + }); + }); + userRepo.getAllCountries().then((value) { + setState(() { + futureCountries = Future.value(value); + }); + }); + } + + @override + Widget build(BuildContext context) { + final UserVM userVM = context.read(); + return Scaffold( + appBar: const CustomAppBar(isRemoveBackButton: false, title: ""), + body: Container( + width: double.infinity, + height: double.infinity, + padding: const EdgeInsets.all(20), + child: SingleChildScrollView( + child: SizedBox( + height: MediaQuery.of(context).size.height, + child: Column( + children: [ + 12.height, + LocaleKeys.signUp.tr().toText( + fontSize: 20, + letterSpacing: -1.44, + ), + LocaleKeys.enterPhoneNumber.tr().toText( + color: MyColors.lightTextColor, + textAlign: TextAlign.center, + fontSize: 14, + height: 23 / 24, + letterSpacing: -0.48, + ), + 30.height, + FutureBuilder( + future: futureRoles, + builder: (context, snapshot) { + if (snapshot.hasData) { + List dropList = []; + snapshot.data?.data?.forEach((element) { + dropList.add(DropValue(element.id ?? 0, EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? element.roleNameN ?? "" : element.roleName ?? "", "")); + }); + if (role == -1) { + role = snapshot.data?.data?.first.id ?? -1; + } + return RoleTypeTab( + 0, + dropList, + onSelect: (DropValue value) { + role = value.id; + }, + ); + } else { + return const CircularProgressIndicator(); + } + }, + ), + 18.height, + FutureBuilder( + future: futureCountries, + builder: (context, snapshot) { + if (snapshot.hasData) { + List dropList = []; + snapshot.data?.data?.forEach((element) { + dropList.add(DropValue( + element.id ?? 0, + EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" + ? (element.countryNameN ?? "") + " " + (element.countryCode ?? "") + : (element.countryName ?? "") + " " + (element.countryCode ?? ""), + element.countryCode ?? "")); + }); + return Column( + children: [ + LocaleKeys.selectYourCountry.tr().toText( + fontSize: 14, + color: MyColors.lightTextColor, + textAlign: TextAlign.center, + ), + 10.height, + DropdownField( + (DropValue value) { + setState(() { + countryCode = value.subValue; + countryId = value.id; + }); + }, + list: dropList, + hint: LocaleKeys.chooseCountry.tr(), + ), + ], + ); + } else { + return CircularProgressIndicator(); + } + }, + ), + 18.height, + LocaleKeys.enterPhoneForVerfication.tr().toText( + fontSize: 14, + color: MyColors.lightTextColor, + textAlign: TextAlign.center, + ), + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Utils.mExp(1), + Expanded( + flex: 3, + child: Row( + children: [ + Text( + (countryCode.isEmpty ? "+00" : "+" + countryCode), + style: const TextStyle( + fontSize: 20, + color: MyColors.black, + fontWeight: FontWeight.bold, + ), + ), + const Text( + " | ", + style: TextStyle( + fontSize: 20, + color: MyColors.black, + fontWeight: FontWeight.bold, + ), + ), + Flexible( + child: TextField( + controller: emailController, + onChanged: (v) { + phoneNum = v; + }, + style: const TextStyle( + fontSize: 20, + color: MyColors.black, + ), + decoration: const InputDecoration( + hintStyle: TextStyle(color: MyColors.lightTextColor, fontSize: 20), + hintText: "546758594", + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + ), + ), + ), + ], + ), + ), + Utils.mExp(1), + ], + ), + 40.height, + ShowFillButton( + title: LocaleKeys.continu.tr(), + maxWidth: double.infinity, + onPressed: () { + if (validation()) userVM.performBasicOtpRegisterPage(context, countryCode: countryCode, phoneNum: phoneNum, role: role); + // if (validation()) performBasicOtp(context); + }, + ), + ], + ), + ), + ), + ), + ); + } + + // Future performBasicOtp(BuildContext context) async { + // + // Utils.showLoading(context); + // 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(countryCode + phoneNum, code, basicOtp.data!.userToken ?? ""); + // Utils.hideLoading(context); + // if (user.messageStatus == 1) { + // Utils.showToast(user.message ?? ""); + // navigateReplaceWithName(context, AppRoutes.completeProfile, arguments: user); + // } else { + // Utils.showToast(user.message ?? ""); + // } + // }, + // )); + // } 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; + } +} + +// class _RegisterPageState extends State { +// String phoneNum = "", countryCode = ""; +// +// int role = 4, countryId = -1; +// +// TextEditingController emailController = TextEditingController(); +// +// @override +// Widget build(BuildContext context) { +// final UserVM userVM = context.read(); +// return Scaffold( +// appBar:CustomAppBar( +// isRemoveBackButton: false, title: ""), +// body: Container( +// width: double.infinity, +// height: double.infinity, +// padding: const EdgeInsets.all(20), +// child: SingleChildScrollView( +// child: SizedBox( +// height: MediaQuery.of(context).size.height, +// child: Column( +// children: [ +// 12.height, +// LocaleKeys.signUp.tr().toText(fontSize: 20, letterSpacing: -1.44,), +// 20.height, +// LocaleKeys.enterPhoneNumber.tr().toText( +// color: MyColors.lightTextColor, +// textAlign: TextAlign.center, +// fontSize: 14, +// height: 23 / 24, +// letterSpacing: -0.48, +// ), +// 30.height, +// FutureBuilder( +// future: userVM.getAllCountries(), +// builder: (context, snapshot) { +// if (snapshot.hasData) { +// List dropList = []; +// snapshot.data?.data?.forEach((element) { +// dropList.add(DropValue( +// element.id ?? 0, +// EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" +// ? (element.countryNameN ?? "") + " " + (element.countryCode ?? "") +// : (element.countryName ?? "") + " " + (element.countryCode ?? ""), +// element.countryCode ?? "")); +// }); +// return Column( +// children: [ +// LocaleKeys.selectYourCountry.tr().toText( +// color: MyColors.lightTextColor, +// textAlign: TextAlign.center, +// fontSize: 14, +// height: 23 / 24, +// letterSpacing: -0.48, +// ), +// 10.height, +// DropdownField( +// (DropValue value) { +// setState(() { +// countryCode = value.subValue; +// countryId = value.id; +// }); +// }, +// list: dropList, +// hint: LocaleKeys.chooseCountry.tr(), +// ), +// ], +// ); +// } else { +// return const CircularProgressIndicator(); +// } +// }, +// ), +// 18.height, +// LocaleKeys.enterPhoneForVerfication.tr().toText( +// color: MyColors.lightTextColor, +// textAlign: TextAlign.center, +// fontSize: 14, +// height: 23 / 24, +// letterSpacing: -0.48, +// ), +// 10.height, +// Row( +// mainAxisAlignment: MainAxisAlignment.center, +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// Utils.mExp(1), +// Expanded( +// flex: 3, +// child: Row( +// children: [ +// Text( +// (countryCode.isEmpty ? "+00" : "+" + countryCode), +// style: const TextStyle( +// fontSize: 20, +// color: MyColors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// const Text( +// " | ", +// style: TextStyle( +// fontSize: 20, +// color: MyColors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Flexible( +// child: TextField( +// controller: emailController, +// onChanged: (v) { +// phoneNum = v; +// }, +// style: const TextStyle( +// fontSize: 20, +// color: MyColors.black, +// ), +// decoration: const InputDecoration( +// hintStyle: TextStyle(color: MyColors.lightTextColor, fontSize: 20), +// hintText: "546758594", +// contentPadding: EdgeInsets.zero, +// border: InputBorder.none, +// ), +// ), +// ), +// ], +// ), +// ), +// Utils.mExp(1), +// ], +// ), +// 40.height, +// ShowFillButton( +// title: LocaleKeys.continu.tr(), +// maxWidth: double.infinity, +// onPressed: () { +// if (validation()) userVM.performBasicOtpRegisterPage(context, countryCode: countryCode, phoneNum: phoneNum, role: role); +// }, +// ), +// ], +// ), +// ), +// ), +// ), +// ); +// } +// +// bool validation() { +// bool isValid = true; +// if (role == -1) { +// Utils.showToast(LocaleKeys.selectProviderRole.tr()); +// //("Please select Provider Role"); +// isValid = false; +// } else if (countryCode.isEmpty) { +// Utils.showToast(LocaleKeys.selectCountryCode.tr()); +// //("Please select Country Code"); +// isValid = false; +// } else if (phoneNum.isEmpty) { +// Utils.showToast(LocaleKeys.addPhoneNo.tr()); +// //("Please add Phone No"); +// isValid = false; +// } +// return isValid; +// } +// } diff --git a/lib/widgets/common_widgets/app_bar.dart b/lib/widgets/common_widgets/app_bar.dart index 7ff234e..3145c75 100644 --- a/lib/widgets/common_widgets/app_bar.dart +++ b/lib/widgets/common_widgets/app_bar.dart @@ -77,7 +77,7 @@ class CustomAppBar extends StatelessWidget with PreferredSizeWidget { this.title, this.isDrawerEnabled = false, this.profileImageUrl = "", - required this.isRemoveBackButton, + this.isRemoveBackButton = false, this.backgroundColor, this.actions, this.backIconColor, @@ -95,23 +95,23 @@ class CustomAppBar extends StatelessWidget with PreferredSizeWidget { centerTitle: isTitleCenter ?? true, leading: isDrawerEnabled ? Row( - children: [ - Image.asset( - profileImageUrl, - width: 34, - height: 34, - fit: BoxFit.fill, - ).toCircle(borderRadius: 100), - 10.width, - SvgPicture.asset(MyAssets.dashboardDrawerIcon), - ], - ).paddingOnly(left: 21) + children: [ + Image.asset( + profileImageUrl, + width: 34, + height: 34, + fit: BoxFit.fill, + ).toCircle(borderRadius: 100), + 10.width, + SvgPicture.asset(MyAssets.dashboardDrawerIcon), + ], + ).paddingOnly(left: 21) : isRemoveBackButton - ? null - : IconButton( - icon: const Icon(Icons.arrow_back_ios, color: Colors.black), - onPressed: () => Navigator.of(context).pop(), - ), + ? null + : IconButton( + icon: const Icon(Icons.arrow_back_ios, color: Colors.black), + onPressed: () => Navigator.of(context).pop(), + ), iconTheme: IconThemeData( color: backIconColor ?? Colors.black, //change your color here ), diff --git a/lib/widgets/common_widgets/bottom_nav_bar.dart b/lib/widgets/common_widgets/bottom_nav_bar.dart index 8011bdb..e4b01b7 100644 --- a/lib/widgets/common_widgets/bottom_nav_bar.dart +++ b/lib/widgets/common_widgets/bottom_nav_bar.dart @@ -1,10 +1,10 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:mc_common_app/extensions/widget_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; class CustomBottomNavbar extends StatelessWidget { final int selectedNavbarBarIndex; diff --git a/lib/widgets/extensions/extensions_widget.dart b/lib/widgets/extensions/extensions_widget.dart index 669c9d9..fbe672f 100644 --- a/lib/widgets/extensions/extensions_widget.dart +++ b/lib/widgets/extensions/extensions_widget.dart @@ -3,6 +3,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:mc_common_app/theme/colors.dart'; extension ExtendedText on Widget { + showOverlay({double? width, double? height}) { return Container( width: width ?? double.infinity, @@ -38,13 +39,41 @@ extension ContainerExt on Widget { ); } - Widget toContainer({required double borderRadius, required Color backgroundColor, required EdgeInsetsGeometry padding}) { - return Container( - decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(borderRadius)), - padding: padding, - child: this, - ); - } + // Widget toContainer({required double borderRadius, required Color backgroundColor, required EdgeInsetsGeometry padding}) { + // return Container( + // decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(borderRadius)), + // padding: padding, + // child: this, + // ); + // } + + Widget toContainer({double borderRadius = 8, + double paddingAll = 10, + double marginAll = 0, + EdgeInsetsGeometry? margin, + EdgeInsetsGeometry? padding, + Color backgroundColor = Colors.white, + bool isShadowEnabled = false, + double? width}) => + Container( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.circular(borderRadius), + boxShadow: !isShadowEnabled + ? null + : [ + BoxShadow( + color: const Color(0xff000000).withOpacity(.05), + blurRadius: 26, + offset: const Offset(0, -3), + ), + ], + ), + padding: padding ?? EdgeInsets.all(paddingAll), + margin: margin ?? EdgeInsets.all(marginAll), + width: width, + child: this, + ); } extension ImageExt on Image { @@ -168,7 +197,6 @@ extension WidgetExt on Widget { ); } - Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) => Padding(padding: EdgeInsets.only(left: left, right: right, top: top, bottom: bottom), child: this); @@ -282,3 +310,8 @@ extension BuildSVG on String { ); } } + +extension WidgetExtensions on Widget { + Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); + +} diff --git a/lib/widgets/tab/role_type_tab.dart b/lib/widgets/tab/role_type_tab.dart new file mode 100644 index 0000000..ec80506 --- /dev/null +++ b/lib/widgets/tab/role_type_tab.dart @@ -0,0 +1,61 @@ + +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; + +class RoleTypeTab extends StatefulWidget { + int selectedIndex; + List dropList; + Function(DropValue value) onSelect; + + RoleTypeTab(this.selectedIndex, this.dropList, {required this.onSelect}); + + @override + State createState() => _RoleTypeTabState(); +} + +class _RoleTypeTabState extends State { + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: 45, + child: ListView.separated( + itemBuilder: (context, index) { + return InkWell( + onTap: () { + setState(() { + widget.selectedIndex = index; + widget.onSelect(widget.dropList[index]); + }); + }, + child: Container( + width: (MediaQuery.of(context).size.width / 2)-30, + height: 45, + decoration: BoxDecoration( + color: widget.selectedIndex == index ? MyColors.darkPrimaryColor : Colors.grey[200], + // border: Border.all(color: type == ClassType.NUMBER ? MyColors.darkPrimaryColor : Colors.transparent, width: 2), + borderRadius: const BorderRadius.all(Radius.circular(0)), + ), + child: Center( + child: Text( + widget.dropList[index].value, + style: TextStyle( + color: widget.selectedIndex == index ? MyColors.white : Colors.black, + fontSize: 10, + ), + ), + ), + ), + ); + }, + separatorBuilder: (context, index) { + return 12.width; + }, + itemCount: widget.dropList.length, + scrollDirection: Axis.horizontal, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 6993d82..4c300d1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + badges: + dependency: "direct main" + description: + name: badges + sha256: "461031a60efbb95276f52107f63d5d45008b5ca1eb7f8ca440cadda9ec2143b0" + url: "https://pub.dev" + source: hosted + version: "3.0.2" boolean_selector: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7a2d993..cd55b0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,6 +32,8 @@ dependencies: hexcolor: ^2.0.4 cached_network_image: any url_launcher: ^6.1.7 + carousel_slider: any + badges: ^3.0.2 # google