diff --git a/lib/config/provider_routes.dart b/lib/config/provider_routes.dart index b6c1765..9b4f985 100644 --- a/lib/config/provider_routes.dart +++ b/lib/config/provider_routes.dart @@ -4,6 +4,7 @@ import 'package:car_provider_app/views/requests/request_detail_page.dart'; import 'package:car_provider_app/views/requests/send_offer_page.dart'; import 'package:car_provider_app/views/settings/branch/branch_detail_page.dart'; import 'package:car_provider_app/views/settings/branch/branch_list_page.dart'; +import 'package:car_provider_app/views/settings/branch/dealer/dealer_user_page.dart'; import 'package:car_provider_app/views/settings/branch/define_branch_page.dart'; import 'package:car_provider_app/views/settings/create_services_page.dart'; import 'package:car_provider_app/views/settings/schedule/add_schedules_page.dart'; @@ -13,15 +14,18 @@ import 'package:car_provider_app/views/settings/services/create_services_page2.d import 'package:car_provider_app/views/settings/dealership_page.dart'; import 'package:car_provider_app/views/settings/define_license_page.dart'; import 'package:car_provider_app/views/settings/services/create_services_page3.dart'; +import 'package:car_provider_app/views/settings/services/duplication/matched_services_page.dart'; +import 'package:car_provider_app/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart'; import 'package:car_provider_app/views/settings/services/items_list_page.dart'; import 'package:car_provider_app/views/settings/services/services_list_page.dart'; import 'package:car_provider_app/views/subscriptions/my_subscritions_page.dart'; import 'package:car_provider_app/views/subscriptions/subscriptions_page.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; import 'package:flutter/material.dart'; +import 'package:mc_common_app/models/model/provider_model.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; import 'package:mc_common_app/views/advertisement/ads_detail_view.dart'; import 'package:mc_common_app/views/advertisement/create_ad_view.dart'; @@ -44,6 +48,7 @@ class ProviderAppRoutes { static const String sendOfferPage = "/sendOfferPage"; //Services + static const String dealerUser = "/dealerUser"; static const String servicesList = "/servicesList"; static const String itemsList = "/itemsList"; static const String createItem = "/createItem"; @@ -55,19 +60,21 @@ class ProviderAppRoutes { static const String schedulesList = "/schedulesList"; static const String addSchedule = "/addSchedule"; + //Bracnh Duplication + static const String matchServices = "/matchServices"; + static final Map routes = { //Home page AppRoutes.dashboard: (context) => const DashboardPage(), AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel), AppRoutes.createAdView: (context) => const CreateAdView(), - //setting defineLicense: (context) => DefineLicensePage(), dealershipSetting: (context) => DealershipPage(), // branchList: (context) => BranchListPage(), - defineBranch: (context) => DefineBranchPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch)), - branchDetail: (context) => BranchDetailPage(ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch), + defineBranch: (context) => DefineBranchPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as BranchModel)), + branchDetail: (context) => BranchDetailPage(ModalRoute.of(context)!.settings.arguments as BranchModel), //Appointments appointmentDetailList: (context) => const AppointmentDetailListPage(), @@ -82,6 +89,7 @@ class ProviderAppRoutes { AppRoutes.subscriptionsPage: (context) => const SubscriptionsPage(), //Services + dealerUser: (context) => DealerUserPage(ModalRoute.of(context)!.settings.arguments as String), servicesList: (context) => const ServicesListPage(), itemsList: (context) => ItemsListPage(), createItem: (context) => const CreateItemPage(), @@ -90,7 +98,10 @@ class ProviderAppRoutes { createServices3: (context) => CreateServicesPage3((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as CreateBranchModel)), //Schedules - schedulesList: (context) => SchedulesListPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as String)), - addSchedule: (context) => AddSchedulesPage(), + schedulesList: (context) => SchedulesListPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as String)), + addSchedule: (context) => AddSchedulesPage(), + + //Branch Duplication + matchServices: (context) => MatchedServicesPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as MatchServicesArguments)), }; } diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index f73cd2f..2e2b1e6 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -9,7 +9,8 @@ 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'; -import 'package:mc_common_app/models/model/branch2.dart'; + +import 'package:mc_common_app/models/model/provider_model.dart'; import 'package:mc_common_app/models/profile/branch.dart'; import 'package:mc_common_app/models/profile/categroy.dart'; import 'package:mc_common_app/models/profile/document.dart'; @@ -33,11 +34,23 @@ abstract class BranchRepo { Future serviceProviderDocumentsUpdate(List? documents); - Future getBranchAndServices(); + Future getBranchAndServices(); Future createService(List> map); Future updateService(List> map); + + Future getMatchedServices(int oldBranchId, int newBranchId, int categoryId); + + Future duplicateItems(Map map); + + Future getAllProviderDealers(Map map); + + Future getBranchUsers(Map map); + + Future assignDealerToBranch(Map map); + + Future removeDealerFromBranch(Map map); } class BranchRepoImp implements BranchRepo { @@ -122,11 +135,11 @@ class BranchRepoImp implements BranchRepo { } @override - Future getBranchAndServices() async { + Future getBranchAndServices() async { var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; print("tokeen121 " + t); - return await injector.get().getJsonForObject((json) => Branch2.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t); + return await injector.get().getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t); } @override @@ -162,4 +175,45 @@ class BranchRepoImp implements BranchRepo { String t = AppState().getUser.data!.accessToken ?? ""; return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Update, map, token: t); } + + @override + Future getMatchedServices(int oldBranchId, int newBranchId, int categoryId) async { + var postParams = { + "ProviderBranchIDExisted": oldBranchId.toString(), + "ProviderBranchIDNew": newBranchId.toString(), + "CategoryID": categoryId.toString(), + }; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getMatchedServices, queryParameters: postParams, token: t); + } + + @override + Future duplicateItems(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map, token: t); + } + + @override + Future getAllProviderDealers(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers, queryParameters: map, token: t); + } + + @override + Future getBranchUsers(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getBranchUser, queryParameters: map, token: t); + } + + @override + Future assignDealerToBranch(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map, token: t); + } + + @override + Future removeDealerFromBranch(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.removeDealerFromBranch, map, token: t); + } } diff --git a/lib/view_models/items_view_model.dart b/lib/view_models/items_view_model.dart index 0fe5ada..6747189 100644 --- a/lib/view_models/items_view_model.dart +++ b/lib/view_models/items_view_model.dart @@ -41,7 +41,7 @@ class ItemsVM extends BaseVM { } Future getServiceItems(int serviceId) async { - setState(ViewState.busy); + setOnlyState(ViewState.busy); serviceItems = await itemsRepo.getServiceItems(serviceId); setState(ViewState.idle); return serviceItems; diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index f23885e..438779b 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -1,11 +1,253 @@ +// import 'dart:convert'; +// import 'dart:io'; +// +// import 'package:car_provider_app/repositories/branch_repo.dart'; +// import 'package:mc_common_app/models/m_response.dart'; +// +// import 'package:mc_common_app/models/model/provider_model.dart'; +// import 'package:mc_common_app/models/profile/categroy.dart'; +// import 'package:mc_common_app/models/profile/document.dart'; +// import 'package:mc_common_app/models/profile/services.dart'; +// import 'package:mc_common_app/models/services/branch_model.dart'; +// import 'package:mc_common_app/models/services/item_model.dart'; +// import 'package:mc_common_app/models/services/service_model.dart'; +// import 'package:mc_common_app/models/user/cities.dart'; +// import 'package:mc_common_app/models/user/country.dart'; +// import 'package:mc_common_app/repositories/common_repo.dart'; +// import 'package:mc_common_app/services/common_services.dart'; +// import 'package:mc_common_app/utils/enums.dart'; +// import 'package:mc_common_app/utils/utils.dart'; +// import 'package:mc_common_app/view_models/base_view_model.dart'; +// import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +// import 'package:file_picker/file_picker.dart'; +// +// class ServiceVM extends BaseVM { +// final BranchRepo branchRepo; +// final CommonAppServices commonServices; +// final CommonRepo commonRepo; +// +// ServiceVM({required this.branchRepo, required this.commonServices, required this.commonRepo}); +// +// //Documents & Branches +// int selectedBranchStatus = 3; +// Document? document; +// ProviderModel? branchs; +// Country? country; +// Cities? cities; +// DropValue? countryValue; +// DropValue? cityValue; +// List countryDropList = []; +// List citiesDropList = []; +// double latitude = 0, longitude = 0; +// int role = -1, countryId = -1, cityId = -1; +// String countryCode = "", address = "", branchName = "", branchDescription = ""; +// +// getServiceProviderDocument(int providerId) async { +// setState(ViewState.busy); +// document = await branchRepo.getServiceProviderDocument(providerId); +// setState(ViewState.idle); +// } +// +// selectFile(int index) async { +// File? file = await commonServices.pickFile(fileType: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg']); +// +// if (file != null) { +// int sizeInBytes = file.lengthSync(); +// // double sizeInMb = sizeInBytes / (1024 * 1024); +// if (sizeInBytes > 1000) { +// Utils.showToast("File is larger then 1KB"); +// } else { +// document!.data![index].document = Utils.convertFileToBase64(file); +// document!.data![index].fileExt = Utils.checkFileExt(file.path); +// document!.data![index].documentUrl = file.path; +// setState(ViewState.idle); +// } +// } else { +// // User canceled the picker +// } +// } +// +// Future updateDocument(List? data) async { +// return await branchRepo.serviceProviderDocumentsUpdate(data); +// } +// +// //Create new branch +// getBranchAndServices() async { +// setState(ViewState.busy); +// branchs = await branchRepo.getBranchAndServices(); +// setState(ViewState.idle); +// } +// +// getAllCountriesList(BranchModel? branchData, String countryCode) async { +// setState(ViewState.busy); +// resetValues(); +// country = await commonRepo.getAllCountries(); +// country!.data?.forEach((element) { +// if (branchData != null) if (branchData.id != null) { +// if (element.id == branchData.countryID) { +// countryValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? ""); +// } +// } +// countryDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "")); +// }); +// if (branchData != null) if (branchData.id != null) getAllCities(branchData, countryCode); +// setState(ViewState.idle); +// } +// +// getAllCities(BranchModel? branchData, String countryCode) async { +// setState(ViewState.busy); +// citiesDropList.clear(); +// cities = null; +// cityId = -1; +// cities = await commonRepo.getAllCites(countryId.toString()); +// cities!.data?.forEach((element) { +// if (branchData != null && branchData.id != null) { +// if (element.id == branchData.cityId) { +// address = branchData.address!; +// branchName = branchData.branchName!; +// branchDescription = branchData.branchDescription!; +// latitude = double.parse(branchData.latitude ?? ""); +// longitude = double.parse(branchData.longitude ?? ""); +// countryId = branchData.countryID!; +// cityId = branchData.cityId!; +// cityValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? ""); +// } +// } +// citiesDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? "")); +// }); +// setState(ViewState.idle); +// } +// +// Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async { +// return await branchRepo.createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); +// } +// +// Future updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async { +// return await branchRepo.updateBranch(id ?? 0, branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); +// } +// +// resetValues() { +// countryCode = ""; +// address = ""; +// branchName = ""; +// branchDescription = ""; +// latitude = 0; +// longitude = 0; +// role = -1; +// countryId = -1; +// cityId = -1; +// countryDropList.clear(); +// countryId = -1; +// cityId = -1; +// cities = null; +// categoryDropList = []; +// servicesDropList = []; +// services = null; +// } +// +// //Create Services +// Services? services; +// List categoryDropList = []; +// List servicesDropList = []; +// +// fetchBranchCategory(String countryCode) async { +// categoryDropList.clear(); +// servicesDropList = []; +// services = null; +// setState(ViewState.busy); +// Category? category = await branchRepo.fetchBranchCategory(); +// category.data?.forEach((element) { +// categoryDropList.add(DropValue( +// element.id ?? 0, +// ((element.categoryName!.isEmpty +// ? "N/A" +// : countryCode == "SA" +// ? element.categoryNameN +// : element.categoryName) ?? +// "N/A"), +// "")); +// }); +// setState(ViewState.idle); +// } +// +// fetchServicesByCategoryId(String categoryId) async { +// servicesDropList = []; +// setState(ViewState.busy); +// services = await branchRepo.fetchServicesByCategoryId(categoryId); +// +// for (var element in services!.data!) { +// servicesDropList.add(DropValue(element.id ?? 0, element.description ?? "N/aA", "")); +// } +// setState(ViewState.idle); +// } +// +// Future createService(List> map) async { +// return await branchRepo.createService(map); +// } +// +// Future updateServices(List> map) async { +// return await branchRepo.updateService(map); +// } +// +// updateSelectedBranchType(int status) { +// selectedBranchStatus = status; +// notifyListeners(); +// } +// +// List? matchedServices; +// bool isAllSelected = false; +// +// getAllMatchedServices(int oldBranchId, int newBranchId, int categoryId) async { +// matchedServices = null; +// MResponse response = await branchRepo.getMatchedServices(oldBranchId, newBranchId, categoryId); +// matchedServices = []; +// if (response.messageStatus == 1) { +// matchedServices = List.from(response.data.map((x) => ServiceModel.fromJson(x))); +// } +// notifyListeners(); +// } +// +// selectAllServices(bool value) { +// for (var element in matchedServices!) { +// element.isExpandedOrSelected = value; +// for (var item in element.serviceItems!) { +// item.isUpdateOrSelected = value; +// } +// } +// isAllSelected = value; +// notifyListeners(); +// } +// +// updateServiceItem(int serviceIndex, bool value) { +// for (var element in matchedServices![serviceIndex].serviceItems!) { +// element.isUpdateOrSelected = value; +// } +// notifyListeners(); +// } +// +// copyItems(int index, List copiedItems) { +// matchedServices![index].serviceItems = copiedItems; +// notifyListeners(); +// } +// +// Future duplicateItems(Map map) async { +// return await branchRepo.duplicateItems(map); +// } +// } + +import 'dart:convert'; import 'dart:io'; import 'package:car_provider_app/repositories/branch_repo.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:mc_common_app/models/m_response.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; +import 'package:mc_common_app/models/model/provider_model.dart'; import 'package:mc_common_app/models/profile/categroy.dart'; import 'package:mc_common_app/models/profile/document.dart'; import 'package:mc_common_app/models/profile/services.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; +import 'package:mc_common_app/models/services/item_model.dart'; +import 'package:mc_common_app/models/services/service_model.dart'; import 'package:mc_common_app/models/user/cities.dart'; import 'package:mc_common_app/models/user/country.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; @@ -14,36 +256,66 @@ import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/base_view_model.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; -import 'package:file_picker/file_picker.dart'; +import 'package:mc_common_app/models/user/branch_user.dart'; class ServiceVM extends BaseVM { final BranchRepo branchRepo; final CommonAppServices commonServices; final CommonRepo commonRepo; - ServiceVM({required this.branchRepo, required this.commonServices, required this.commonRepo}); + ServiceVM({ + required this.branchRepo, + required this.commonServices, + required this.commonRepo, + }); - //Documents & Branches + // Documents & Branches + int selectedBranchStatus = 3; Document? document; - Branch2? branchs; + ProviderModel? branches; Country? country; Cities? cities; DropValue? countryValue; DropValue? cityValue; List countryDropList = []; List citiesDropList = []; - double latitude = 0, longitude = 0; - int role = -1, countryId = -1, cityId = -1; - String countryCode = "", address = "", branchName = "", branchDescription = ""; + double latitude = 0; + double longitude = 0; + int role = -1; + int countryId = -1; + int cityId = -1; + String countryCode = ""; + String address = ""; + String branchName = ""; + String branchDescription = ""; - getServiceProviderDocument(int providerId) async { + Future getServiceProviderDocument(int providerId) async { setState(ViewState.busy); document = await branchRepo.getServiceProviderDocument(providerId); setState(ViewState.idle); } - selectFile(int index) async { - File? file = await commonServices.pickFile(fileType: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg']); + Future selectFile(int index) async { + final File? file = await commonServices.pickFile( + fileType: FileType.custom, + allowedExtensions: ['png', 'pdf', 'jpeg'], + ); + + // if (result != null) { + // final File file = File(result.files.single.path!); + // final int sizeInBytes = file.lengthSync(); + // + // if (sizeInBytes > 1000) { + // Utils.showToast("File is larger than 1KB"); + // } else { + // document!.data![index].document = Utils.convertFileToBase64(file); + // document!.data![index].fileExt = Utils.checkFileExt(file.path); + // document!.data![index].documentUrl = file.path; + // setState(ViewState.idle); + // } + // } else { + // // User canceled the picker + // } if (file != null) { int sizeInBytes = file.lengthSync(); @@ -65,30 +337,42 @@ class ServiceVM extends BaseVM { return await branchRepo.serviceProviderDocumentsUpdate(data); } - //Create new branch - getBranchAndServices() async { + // Create new branch + Future getBranchAndServices() async { setState(ViewState.busy); - branchs = await branchRepo.getBranchAndServices(); + branches = await branchRepo.getBranchAndServices(); setState(ViewState.idle); } - getAllCountriesList(ServiceProviderBranch? branchData, String countryCode) async { + Future getAllCountriesList(BranchModel? branchData, String countryCode) async { setState(ViewState.busy); resetValues(); country = await commonRepo.getAllCountries(); country!.data?.forEach((element) { - if (branchData != null) if (branchData.id != null) { + if (branchData != null && branchData.id != null) { if (element.id == branchData.countryID) { - countryValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? ""); + countryValue = DropValue( + element.id ?? 0, + countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), + element.countryCode ?? "", + ); } } - countryDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "")); + countryDropList.add( + DropValue( + element.id ?? 0, + countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), + element.countryCode ?? "", + ), + ); }); - if (branchData != null) if (branchData.id != null) getAllCities(branchData, countryCode); + if (branchData != null && branchData.id != null) { + await getAllCities(branchData, countryCode); + } setState(ViewState.idle); } - getAllCities(ServiceProviderBranch? branchData, String countryCode) async { + Future getAllCities(BranchModel? branchData, String countryCode) async { setState(ViewState.busy); citiesDropList.clear(); cities = null; @@ -104,10 +388,20 @@ class ServiceVM extends BaseVM { longitude = double.parse(branchData.longitude ?? ""); countryId = branchData.countryID!; cityId = branchData.cityId!; - cityValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? ""); + cityValue = DropValue( + element.id ?? 0, + countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), + element.id.toString() ?? "", + ); } } - citiesDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? "")); + citiesDropList.add( + DropValue( + element.id ?? 0, + countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), + element.id.toString() ?? "", + ), + ); }); setState(ViewState.idle); } @@ -116,11 +410,28 @@ class ServiceVM extends BaseVM { return await branchRepo.createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); } - Future updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async { - return await branchRepo.updateBranch(id ?? 0, branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString()); + Future updateBranch( + int id, + String branchName, + String branchDescription, + String cityId, + String address, + String latitude, + String longitude, { + bool isNeedToDelete = true, + }) async { + return await branchRepo.updateBranch( + id ?? 0, + branchName, + branchDescription, + cityId.toString(), + address, + latitude.toString(), + longitude.toString(), + ); } - resetValues() { + void resetValues() { countryCode = ""; address = ""; branchName = ""; @@ -139,19 +450,20 @@ class ServiceVM extends BaseVM { services = null; } - //Create Services + // Create Services Services? services; List categoryDropList = []; List servicesDropList = []; - fetchBranchCategory(String countryCode) async { + Future fetchBranchCategory(String countryCode) async { categoryDropList.clear(); servicesDropList = []; services = null; - setState(ViewState.busy); + setOnlyState(ViewState.busy); Category? category = await branchRepo.fetchBranchCategory(); category.data?.forEach((element) { - categoryDropList.add(DropValue( + categoryDropList.add( + DropValue( element.id ?? 0, ((element.categoryName!.isEmpty ? "N/A" @@ -159,18 +471,26 @@ class ServiceVM extends BaseVM { ? element.categoryNameN : element.categoryName) ?? "N/A"), - "")); + "", + ), + ); }); setState(ViewState.idle); } - fetchServicesByCategoryId(String categoryId) async { + Future fetchServicesByCategoryId(String categoryId) async { servicesDropList = []; setState(ViewState.busy); services = await branchRepo.fetchServicesByCategoryId(categoryId); for (var element in services!.data!) { - servicesDropList.add(DropValue(element.id ?? 0, element.description ?? "N/aA", "")); + servicesDropList.add( + DropValue( + element.id ?? 0, + element.description ?? "N/A", + "", + ), + ); } setState(ViewState.idle); } @@ -182,4 +502,84 @@ class ServiceVM extends BaseVM { Future updateServices(List> map) async { return await branchRepo.updateService(map); } + + void updateSelectedBranchType(int status) { + selectedBranchStatus = status; + notifyListeners(); + } + + List? matchedServices; + bool isAllSelected = false; + + Future getAllMatchedServices(int oldBranchId, int newBranchId, int categoryId) async { + matchedServices = null; + final MResponse response = await branchRepo.getMatchedServices(oldBranchId, newBranchId, categoryId); + matchedServices = []; + + if (response.messageStatus == 1) { + matchedServices = List.from(response.data.map((x) => ServiceModel.fromJson(x))); + } + notifyListeners(); + } + + void selectAllServices(bool value) { + for (var element in matchedServices!) { + element.isExpandedOrSelected = value; + for (var item in element.serviceItems!) { + item.isUpdateOrSelected = value; + } + } + isAllSelected = value; + notifyListeners(); + } + + void updateServiceItem(int serviceIndex, bool value) { + for (var element in matchedServices![serviceIndex].serviceItems!) { + element.isUpdateOrSelected = value; + } + notifyListeners(); + } + + void copyItems(int index, List copiedItems) { + matchedServices![index].serviceItems = copiedItems; + notifyListeners(); + } + + Future duplicateItems(Map map) async { + return await branchRepo.duplicateItems(map); + } + + // Branch Users + List allProviderDealersList = []; + List branchUserList = []; + + getAllProviderDealers(Map map) async { + setState(ViewState.busy); + MResponse response = await branchRepo.getAllProviderDealers(map); + if (response.messageStatus == 1) { + allProviderDealersList=[]; + allProviderDealersList = List.from(response.data.map((x) => BranchUser.fromJson(x))); + } + setState(ViewState.idle); + } + + Future getBranchUsers(Map map) async { + setState(ViewState.busy); + MResponse response = await branchRepo.getBranchUsers(map); + if (response.messageStatus == 1) { + branchUserList=[]; + branchUserList = List.from(response.data.map((x) => BranchUser.fromJson(x))); + } + setState(ViewState.idle); + } + + Future assignDealerToBranch(Map map) async { + MResponse response = await branchRepo.assignDealerToBranch(map); + return response; + } + + Future removeDealerFromBranch(Map map) async { + MResponse response = await branchRepo.removeDealerFromBranch(map); + return response; + } } diff --git a/lib/views/dashboard/widget/my_service_provider.dart b/lib/views/dashboard/widget/my_service_provider.dart index 8fdce1d..e66240b 100644 --- a/lib/views/dashboard/widget/my_service_provider.dart +++ b/lib/views/dashboard/widget/my_service_provider.dart @@ -24,12 +24,12 @@ class ServiceProviderWidget extends StatelessWidget { if (model.state == ViewState.busy) { return const Center(child: CircularProgressIndicator()); } else { - return model.branchs!.data! == null + return model.branches!.data! == null ? const Center(child: Text("No Branch Found")) - : model.branchs!.data!.serviceProviderBranch!.isEmpty + : model.branches!.data!.serviceProviderBranch!.isEmpty ? Center(child: Text(LocaleKeys.no_branch.tr())) : ListView.builder( - itemCount: model.branchs!.data!.serviceProviderBranch!.length, + itemCount: model.branches!.data!.serviceProviderBranch!.length, scrollDirection: Axis.horizontal, shrinkWrap: true, itemBuilder: (BuildContext context, int index) { @@ -44,7 +44,7 @@ class ServiceProviderWidget extends StatelessWidget { fit: BoxFit.cover, ).toCircle(borderRadius: 100), 8.height, - model.branchs!.data!.serviceProviderBranch![index].branchName!.toText( + model.branches!.data!.serviceProviderBranch![index].branchName!.toText( fontSize: 14, isBold: true, textAlign: TextAlign.center, @@ -53,9 +53,9 @@ class ServiceProviderWidget extends StatelessWidget { ), ).onPress( () { - model.branchs!.data!.serviceProviderBranch![index].countryID = model.branchs!.data!.countryID; - model.branchs!.data!.serviceProviderBranch![index].countryName = model.branchs!.data!.countryName; - navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: model.branchs!.data!.serviceProviderBranch![index]); + model.branches!.data!.serviceProviderBranch![index].countryID = model.branches!.data!.countryID; + model.branches!.data!.serviceProviderBranch![index].countryName = model.branches!.data!.countryName; + navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: model.branches!.data!.serviceProviderBranch![index]); }, ); }, diff --git a/lib/views/settings/branch/branch_detail_page.dart b/lib/views/settings/branch/branch_detail_page.dart index 6f87967..f1f4c1d 100644 --- a/lib/views/settings/branch/branch_detail_page.dart +++ b/lib/views/settings/branch/branch_detail_page.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:car_provider_app/config/provider_routes.dart'; import 'package:car_provider_app/view_models/service_view_model.dart'; import 'package:car_provider_app/views/settings/services/services_list_page.dart'; @@ -6,13 +9,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:car_provider_app/view_models/branch_view_model.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/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; +import 'package:mc_common_app/models/model/provider_model.dart'; import 'package:mc_common_app/models/profile/categroy.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; @@ -23,7 +29,7 @@ import 'package:provider/provider.dart'; import '../../../generated/locale_keys.g.dart'; class BranchDetailPage extends StatelessWidget { - ServiceProviderBranch branchData; + BranchModel branchData; BranchDetailPage(this.branchData); @@ -31,7 +37,7 @@ class BranchDetailPage extends StatelessWidget { @override Widget build(BuildContext context) { - branchData.serviceProviderServices!.forEach((element) { + branchData.branchServices!.forEach((element) { categories.add( CategoryData( id: element.categoryId, @@ -42,7 +48,7 @@ class BranchDetailPage extends StatelessWidget { }); categories = categories.toSet().toList(); for (var payment in categories) { - branchData.serviceProviderServices!.forEach((element) { + branchData.branchServices!.forEach((element) { if (payment.id == element.categoryId) { payment.services ??= []; payment.services!.add(element); @@ -83,8 +89,8 @@ class BranchDetailPage extends StatelessWidget { ), Column( children: [ - showData("${LocaleKeys.country.tr()}:", branchData.countryName.toString()), - showData("${LocaleKeys.city.tr()}:", branchData.cityName.toString()), + showData("${LocaleKeys.country.tr()}:", "branchData.countryName".toString()), + showData("${LocaleKeys.city.tr()}:", "branchData.cityName".toString()), showData("${LocaleKeys.branchName.tr()}:", branchData.branchName.toString()), showData("${LocaleKeys.branchDescription.tr()}:", branchData.branchDescription.toString()), showData("${LocaleKeys.address.tr()}:", branchData.address.toString()), @@ -122,6 +128,43 @@ class BranchDetailPage extends StatelessWidget { ).onPress(() { navigateWithName(context, ProviderAppRoutes.schedulesList, arguments: branchData.id.toString()); }), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.add, + color: Colors.white, + ).toContainer( + borderRadius: 100, + paddingAll: 3, + backgroundColor: MyColors.darkIconColor, + ), + 8.width, + "Add Services".toText( + fontSize: 14, + color: MyColors.lightTextColor, + isBold: true, + ), + ], + ) + .toContainer( + borderRadius: 0, + backgroundColor: MyColors.darkWhiteColor, + width: double.infinity, + paddingAll: 20, + margin: const EdgeInsets.only(left: 20, right: 20, top: 20), + ) + .onPress(() { + navigateWithName( + context, + ProviderAppRoutes.createServices3, + arguments: CreateBranchModel( + branchId: branchData.id.toString(), + branchName: branchData.branchName.toString(), + ), + ); + }), categories.isEmpty ? LocaleKeys.no_branch.tr().toText(fontSize: 12) : ListView.separated( @@ -171,8 +214,8 @@ class BranchDetailPage extends StatelessWidget { itemBuilder: (context, index) { return Container( child: (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" - ? categories[pIndex].services![index].serviceNameN.toString() - : categories[pIndex].services![index].serviceName.toString()) + ? categories[pIndex].services![index].serviceDescriptionN.toString() + : categories[pIndex].services![index].serviceDescription.toString()) .toText( fontSize: 12, color: MyColors.lightTextColor, @@ -223,25 +266,23 @@ class BranchDetailPage extends StatelessWidget { Container( width: double.infinity, height: 1, - color: Colors.grey, + color: Colors.grey[100], ), - Padding( - padding: const EdgeInsets.all(12.0), - child: ShowFillButton( - title: "Add Services", - maxWidth: double.infinity, - onPressed: () { - navigateWithName( - context, - ProviderAppRoutes.createServices3, - arguments: CreateBranchModel( - branchId: branchData.id.toString(), - branchName: branchData.branchName.toString(), - ), - ); - }, + if (AppState().userType == UserType.providerDealer) + Padding( + padding: const EdgeInsets.all(12.0), + child: ShowFillButton( + title: "Assign Dealer User", + maxWidth: double.infinity, + backgroundColor: Colors.transparent, + borderColor: MyColors.darkPrimaryColor, + txtColor: MyColors.darkPrimaryColor, + isFilled: false, + onPressed: () { + navigateWithName(context, ProviderAppRoutes.dealerUser, arguments: branchData.id.toString()); + }, + ), ), - ), ], ), ); @@ -280,6 +321,3 @@ class BranchDetailPage extends StatelessWidget { ); } } - - - diff --git a/lib/views/settings/branch/branch_list_page.dart b/lib/views/settings/branch/branch_list_page.dart index c84f803..71dc50c 100644 --- a/lib/views/settings/branch/branch_list_page.dart +++ b/lib/views/settings/branch/branch_list_page.dart @@ -7,19 +7,20 @@ import 'package:geolocator/geolocator.dart'; import 'package:car_provider_app/generated/locale_keys.g.dart'; -import 'package:car_provider_app/view_models/branch_view_model.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/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/m_response.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/utils.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/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/tab/role_type_tab.dart'; import 'package:provider/provider.dart'; @@ -50,113 +51,123 @@ class BranchListPage extends StatelessWidget { body: SizedBox( width: double.infinity, height: double.infinity, - child: Consumer( - builder: (context, model, _) { - if (model.state == ViewState.busy) { - return const Center(child: CircularProgressIndicator()); - } else { - return model.branchs?.data == null - ? const Center(child: Text("No Branch Found")) - : model.branchs!.data!.serviceProviderBranch!.isEmpty - ? Center(child: Text(LocaleKeys.no_branch.tr())) - : ListView.separated( - itemBuilder: (context, index) { - return Row( - children: [ - Container( - width: 74, - height: 50, - decoration: const BoxDecoration( - color: MyColors.darkPrimaryColor, - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - padding: const EdgeInsets.all(6), - child: SvgPicture.asset( - MyAssets.icBranches, - color: Colors.white, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(left: 21, right: 21, top: 21), + child: RoleTypeTab( + context.watch().selectedBranchStatus == 3 ? 0 : context.watch().selectedBranchStatus, + [ + DropValue(3, "Active", ""), + DropValue(1, "Requested", ""), + ], + onSelect: (DropValue value) { + context.read().updateSelectedBranchType(value.id); + }, + ), + ), + Expanded( + child: Consumer( + builder: (context, model, _) { + if (model.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + List branches = []; + if (model.branches!.data != null) { + branches = model.branches!.data!.serviceProviderBranch!.where((element) => model.selectedBranchStatus == element.statusId).toList(); + } + return branches.isEmpty + ? Center(child: Text(LocaleKeys.no_branch.tr())) + : ListView.separated( + itemBuilder: (context, index) { + return Row( + children: [ + Container( + width: 74, + height: 50, + decoration: const BoxDecoration( + color: MyColors.darkPrimaryColor, + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + MyAssets.icBranches, + color: Colors.white, + ), ), - ), - 12.width, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - children: [ - const Icon( - Icons.place, - size: 12, - color: MyColors.darkPrimaryColor, + 12.width, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + const Icon( + Icons.place, + size: 12, + color: MyColors.darkPrimaryColor, + ), + Geolocator.distanceBetween(AppState().currentLocation.latitude, AppState().currentLocation.latitude, double.parse(branches[index].latitude ?? "0"), + double.parse(branches[index].longitude ?? "0")) + .toStringAsFixed(2) + .toText( + fontSize: 12, + color: MyColors.darkPrimaryColor, + ) + ], + ), + Text( + branches[index].branchName ?? "", + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, ), - Geolocator.distanceBetween( - AppState().currentLocation.latitude, - AppState().currentLocation.latitude, - double.parse(model.branchs!.data!.serviceProviderBranch![index].latitude ?? "0"), - double.parse(model.branchs!.data!.serviceProviderBranch![index].longitude ?? "0")) - .toStringAsFixed(2) - .toText( - fontSize: 12, - color: MyColors.darkPrimaryColor, - ) - ], - ), - Text( - model.branchs!.data!.serviceProviderBranch![index].branchName ?? "", - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, ), - ), - LocaleKeys.tapToEdit.tr().toText(fontSize: 10, color: MyColors.grey70Color), - ], + LocaleKeys.tapToEdit.tr().toText(fontSize: 10, color: MyColors.grey70Color), + ], + ), ), - ), - 12.width, - IconButton( - onPressed: () async { - Utils.showLoading(context); - MResponse res = await model.updateBranch( - model.branchs!.data!.serviceProviderBranch![index].id ?? 0, - model.branchs!.data!.serviceProviderBranch![index].branchName ?? "", - model.branchs!.data!.serviceProviderBranch![index].branchDescription ?? "", - model.branchs!.data!.serviceProviderBranch![index].cityId.toString(), - model.branchs!.data!.serviceProviderBranch![index].address ?? "", - model.branchs!.data!.serviceProviderBranch![index].latitude.toString(), - model.branchs!.data!.serviceProviderBranch![index].longitude.toString(), - isNeedToDelete: false); - Utils.hideLoading(context); - if (res.messageStatus == 1) { - Utils.showToast(LocaleKeys.branch_deleted.tr()); - model.setState(ViewState.idle); - } else { - Utils.showToast(res.message ?? ""); - } - }, - icon: const Icon(Icons.delete), - color: Colors.red, - ), - const Icon( - Icons.arrow_forward_rounded, - size: 16, - ), - ], - ).toContainer().onPress(() async { - // await navigateWithName(context, AppRoutes.defineBranch, arguments: snapshot.data!.data![index]); - // setState(() {}); - model.branchs!.data!.serviceProviderBranch![index].countryID = model.branchs!.data!.countryID; - model.branchs!.data!.serviceProviderBranch![index].countryName = model.branchs!.data!.countryName; - navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: model.branchs!.data!.serviceProviderBranch![index]); - }); - }, - separatorBuilder: (context, index) { - return 12.height; - }, - itemCount: model.branchs!.data!.serviceProviderBranch!.length, - padding: const EdgeInsets.all(12), - ); - } - }, + 12.width, + IconButton( + onPressed: () async { + Utils.showLoading(context); + MResponse res = await model.updateBranch(branches[index].id ?? 0, branches[index].branchName ?? "", branches[index].branchDescription ?? "", + branches[index].cityId.toString(), branches[index].address ?? "", branches[index].latitude.toString(), branches[index].longitude.toString(), + isNeedToDelete: false); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast(LocaleKeys.branch_deleted.tr()); + model.setState(ViewState.idle); + } else { + Utils.showToast(res.message ?? ""); + } + }, + icon: const Icon(Icons.delete), + color: Colors.red, + ), + const Icon( + Icons.arrow_forward_rounded, + size: 16, + ), + ], + ).toContainer().onPress(() async { + branches[index].countryID = model.branches!.data!.countryID; + branches[index].countryName = model.branches!.data!.countryName; + navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: branches[index]); + }); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + itemCount: branches.length, + padding: const EdgeInsets.all(12), + ); + } + }, + ), + ), + ], ), ), ); diff --git a/lib/views/settings/branch/dealer/dealer_user_page.dart b/lib/views/settings/branch/dealer/dealer_user_page.dart new file mode 100644 index 0000000..1fd249f --- /dev/null +++ b/lib/views/settings/branch/dealer/dealer_user_page.dart @@ -0,0 +1,159 @@ +import 'package:car_provider_app/views/settings/branch/dealer/widget/add_phone_num_wiget.dart'; +import 'package:car_provider_app/views/settings/branch/dealer/widget/assign_dealer_user_sheet.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/m_response.dart'; +import 'package:mc_common_app/models/user/branch_user.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/widgets/bottom_sheet.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +import '../../../../view_models/service_view_model.dart'; + +class DealerUserPage extends StatefulWidget { + String branchId; + + DealerUserPage(this.branchId, {Key? key}) : super(key: key); + + @override + State createState() => _DealerUserPageState(); +} + +class _DealerUserPageState extends State { + late ServiceVM provider; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + provider = Provider.of(context, listen: false); + getBranchUsers(); + }); + } + + getBranchUsers() { + provider.getBranchUsers({ + // "id": services!.data![i].id, + "ServiceProviderBranchID": widget.branchId, + "ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "" + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const CustomAppBar( + title: "Dealer User", + ), + body: Column( + children: [ + Expanded( + child: Consumer(builder: (context, model, _) { + if (model.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + if (model.branchUserList.isEmpty) { + return const Center(child: Text("No User Added Yet")); + } else { + return ListView.separated( + itemBuilder: (context, index) { + return dealerUsersWidget(model, index); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + padding: const EdgeInsets.all(12), + itemCount: model.branchUserList.length, + ); + } + } + }), + ), + Container( + width: double.infinity, + height: 1, + color: Colors.grey[100], + ), + ShowFillButton( + title: "Assign Dealer User", + maxWidth: double.infinity, + onPressed: () { + showMyBottomSheet( + context, + child: AssignDealerUserSheet( + branchId: widget.branchId, + callBackFunc: () { + getBranchUsers(); + }, + ), + ); + }, + ).paddingAll(12), + ], + ), + ); + } + + Widget dealerUsersWidget(ServiceVM model, int index) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ("${model.branchUserList[index].firstName} ${model.branchUserList[index].lastName}").toText(fontSize: 16, isBold: true), + 8.height, + itemWidget("Role", "Dealer User"), + itemWidget("Email", model.branchUserList[index].email), + itemWidget("Phone", model.branchUserList[index].mobileNo) + ], + ), + ), + 4.width, + IconButton( + onPressed: () async { + var map = { + "id": model.branchUserList[index].id, + "dealershipUserID": model.branchUserList[index].dealershipUserID, + "serviceProviderBranchID": widget.branchId, + "isActive": false, + }; + Utils.showLoading(context); + MResponse response = await provider.removeDealerFromBranch(map); + Utils.hideLoading(context); + if (response.messageStatus == 1) { + getBranchUsers(); + } else { + Utils.showToast(response.message.toString()); + } + }, + icon: const Icon(Icons.delete_outline), + ), + + ], + ).toWhiteContainer( + width: double.infinity, + borderRadius: 12, + pading: const EdgeInsets.only(left: 14, right: 2, top: 12, bottom: 12), + ); + } + + Widget itemWidget(String title, String value) { + return Row( + children: [ + (title + ": ").toText(isBold: true, color: MyColors.lightTextColor), + value.toText(isBold: true), + ], + ); + } +} diff --git a/lib/views/settings/branch/dealer/widget/add_phone_num_wiget.dart b/lib/views/settings/branch/dealer/widget/add_phone_num_wiget.dart new file mode 100644 index 0000000..596fe39 --- /dev/null +++ b/lib/views/settings/branch/dealer/widget/add_phone_num_wiget.dart @@ -0,0 +1,135 @@ +import 'dart:async'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:car_provider_app/generated/locale_keys.g.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/user/country.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/navigator.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/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/tab/login_email_tab.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; + +class AddPhoneNumWidget extends StatefulWidget { + const AddPhoneNumWidget({Key? key}) : super(key: key); + + @override + State createState() => _AddPhoneNumWidgetState(); +} + +class _AddPhoneNumWidgetState extends State { + String phoneNum = "", countryCode = ""; + late UserVM userVM; + Country? _country; + + @override + void initState() { + super.initState(); + + scheduleMicrotask(() { + userVM = Provider.of(context, listen: false); + getCountryList(); + }); + } + + getCountryList() async { + _country = await userVM.getAllCountries(); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Container( + width: double.infinity, + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + "Enter Phone Number".toText(fontSize: 16, isBold: true), + 8.height, + getCountry(context), + 8.height, + TxtField( + keyboardType: TextInputType.phone, + hint: "546758594", + value: phoneNum, + isSidePaddingZero: true, + onChanged: (v) { + phoneNum = v; + }, + ), + 16.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + title: "Cancel", + backgroundColor: MyColors.greyButtonColor, + txtColor: Colors.black, + onPressed: () { + pop(context); + }, + ), + ), + 12.width, + Expanded( + child: ShowFillButton( + title: "Send OTP", + onPressed: () { + //User Role: Dealer|Manager for a branch + FocusScope.of(context).unfocus(); + if (validation()) + userVM.performBasicOtpRegisterPage(context, countryCode: countryCode, phoneNum: phoneNum, role: 7, isNeedToPassToken: true, reloadPage: () { + pop(context); + }); + }, + ), + ), + ], + ) + ], + ), + ), + ); + } + + Widget getCountry(BuildContext context) { + if (_country != null) { + List dropList = []; + _country!.data?.forEach((element) { + dropList.add(DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? "")); + }); + return DropdownField((DropValue value) { + countryCode = value.subValue; + }, list: dropList, hint: LocaleKeys.selectCountryCode.tr()); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + } + + bool validation() { + bool isValid = true; + 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/views/settings/branch/dealer/widget/assign_dealer_user_sheet.dart b/lib/views/settings/branch/dealer/widget/assign_dealer_user_sheet.dart new file mode 100644 index 0000000..eecc724 --- /dev/null +++ b/lib/views/settings/branch/dealer/widget/assign_dealer_user_sheet.dart @@ -0,0 +1,189 @@ +import 'package:car_provider_app/view_models/service_view_model.dart'; +import 'package:car_provider_app/views/settings/branch/dealer/widget/add_phone_num_wiget.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/m_response.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/widgets/bottom_sheet.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class AssignDealerUserSheet extends StatefulWidget { + String branchId; + VoidCallback callBackFunc; + + AssignDealerUserSheet({required this.branchId, required this.callBackFunc, Key? key}) : super(key: key); + + @override + State createState() => _AssignDealerUserSheetState(); +} + +class _AssignDealerUserSheetState extends State { + late ServiceVM provider; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + provider = Provider.of(context, listen: false); + getBranchUsers(); + }); + } + + getBranchUsers() { + provider.getAllProviderDealers({ + // "id": services!.data![i].id, + "ServiceProviderBranchID": widget.branchId, + "ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "" + }); + } + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height / 1.2, + color: Colors.white, + child: Column( + children: [ + Expanded( + child: Consumer(builder: (context, model, _) { + if (model.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + if (model.allProviderDealersList.isEmpty) { + return const Center(child: Text("No User Added Yet")); + } else { + return ListView.separated( + itemBuilder: (context, index) { + return dealerUsersWidget(model, index); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + padding: const EdgeInsets.all(12), + itemCount: model.allProviderDealersList.length, + ); + } + } + }), + ), + Container( + width: double.infinity, + height: 1, + color: Colors.grey[100], + ), + Column( + children: [ + ShowFillButton( + title: "Assign Dealer User", + maxWidth: double.infinity, + onPressed: () async { + if (validation()) { + Utils.showLoading(context); + List userIds = []; + for (var element in provider.allProviderDealersList) { + if (element.isBranchUser) { + userIds.add(element.id); + } + } + var map = { + "dealershipUserIDs": userIds, + "serviceProviderBranchID": widget.branchId, + }; + MResponse response = await provider.assignDealerToBranch(map); + Utils.hideLoading(context); + if (response.messageStatus == 1) { + Utils.showToast(response.message.toString()); + pop(context); + widget.callBackFunc(); + } else { + Utils.showToast(response.message.toString()); + } + } + }, + ), + 12.height, + ShowFillButton( + title: "+ Create New User", + maxWidth: double.infinity, + backgroundColor: Colors.transparent, + borderColor: MyColors.darkPrimaryColor, + txtColor: MyColors.darkPrimaryColor, + isFilled: false, + onPressed: () { + showMyBottomSheet( + context, + isDismissible: false, + child: const AddPhoneNumWidget(), + callBackFunc: () { + getBranchUsers(); + }, + ); + }, + ) + ], + ).paddingAll(12), + ], + ), + ); + } + + Widget dealerUsersWidget(ServiceVM model, int index) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: model.allProviderDealersList[index].isBranchUser, + onChanged: (v) { + model.allProviderDealersList[index].isBranchUser = v ?? false; + model.notifyListeners(); + }), + 4.width, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ("${model.allProviderDealersList[index].firstName} ${model.allProviderDealersList[index].lastName}").toText(fontSize: 16, isBold: true), + 8.height, + itemWidget("Role", "Dealer User"), + itemWidget("Email", model.allProviderDealersList[index].email), + itemWidget("Phone", model.allProviderDealersList[index].mobileNo) + ], + ), + ), + ], + ).toWhiteContainer( + width: double.infinity, + borderRadius: 12, + pading: const EdgeInsets.symmetric(horizontal: 6, vertical: 12), + ); + } + + Widget itemWidget(String title, String value) { + return Row( + children: [ + (title + ": ").toText(isBold: true, color: MyColors.lightTextColor), + value.toText(isBold: true), + ], + ); + } + + bool validation() { + bool isValid = false; + provider.allProviderDealersList.forEach((element) { + if (element.isBranchUser) { + isValid = true; + } + }); + return isValid; + } +} diff --git a/lib/views/settings/branch/define_branch_page.dart b/lib/views/settings/branch/define_branch_page.dart index 8d9d9ba..c57619e 100644 --- a/lib/views/settings/branch/define_branch_page.dart +++ b/lib/views/settings/branch/define_branch_page.dart @@ -8,7 +8,8 @@ import 'package:car_provider_app/views/location/pick_location_page.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/m_response.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; +import 'package:mc_common_app/models/model/provider_model.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -21,7 +22,7 @@ import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; class DefineBranchPage extends StatelessWidget { - ServiceProviderBranch? branchData; + BranchModel? branchData; DefineBranchPage(this.branchData); diff --git a/lib/views/settings/services/create_item_page.dart b/lib/views/settings/services/create_item_page.dart index ed505f7..053a216 100644 --- a/lib/views/settings/services/create_item_page.dart +++ b/lib/views/settings/services/create_item_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/m_response.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; + import 'package:mc_common_app/models/services/item_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/AppPermissionHandler.dart'; @@ -210,11 +210,11 @@ class _CreateItemPageState extends State { ), ), ShowFillButton( - title: (itemData!.isUpdate ?? false) ? "Update Item" : "Create Item", + title: (itemData!.isUpdateOrSelected ?? false) ? "Update Item" : "Create Item", maxWidth: double.infinity, onPressed: () async { if (validation()) { - if (!(itemData?.isUpdate ?? false)) { + if (!(itemData?.isUpdateOrSelected ?? false)) { Map map = { "name": name, "price": price, diff --git a/lib/views/settings/services/create_services_page3.dart b/lib/views/settings/services/create_services_page3.dart index 39025e4..2a4a10e 100644 --- a/lib/views/settings/services/create_services_page3.dart +++ b/lib/views/settings/services/create_services_page3.dart @@ -102,7 +102,7 @@ class CreateServicesPage3 extends StatelessWidget { 12.height, branchModel!.serviceProviderService != null ? Text( - branchModel!.serviceProviderService!.serviceName ?? "N/A", + branchModel!.serviceProviderService!.serviceDescription ?? "N/A", style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, diff --git a/lib/views/settings/services/duplication/matched_services_page.dart b/lib/views/settings/services/duplication/matched_services_page.dart new file mode 100644 index 0000000..01eaf37 --- /dev/null +++ b/lib/views/settings/services/duplication/matched_services_page.dart @@ -0,0 +1,192 @@ +import 'dart:convert'; + +import 'package:car_provider_app/view_models/service_view_model.dart'; +import 'package:car_provider_app/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart'; +import 'package:car_provider_app/views/settings/services/duplication/sheet/items_selection_sheet.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mc_common_app/models/m_response.dart'; +import 'package:mc_common_app/models/services/item_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/widgets/bottom_sheet.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdown_text.dart'; +import 'package:mc_common_app/widgets/empty_widget.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class MatchedServicesPage extends StatefulWidget { + MatchServicesArguments? matchServicesArguments; + + MatchedServicesPage(this.matchServicesArguments, {Key? key}) : super(key: key); + + @override + State createState() => _MatchedServicesPageState(); +} + +class _MatchedServicesPageState extends State { + late ServiceVM serviceVM; + + @override + void initState() { + super.initState(); + serviceVM = Provider.of(context, listen: false); + getMatchedServices(); + } + + getMatchedServices() { + serviceVM.getAllMatchedServices(widget.matchServicesArguments!.oldBranch, widget.matchServicesArguments!.newBranch, widget.matchServicesArguments!.categoryId); + } + + @override + Widget build(BuildContext context) { + print(widget.matchServicesArguments!.oldBranch); + print(widget.matchServicesArguments!.newBranch); + print(widget.matchServicesArguments!.categoryId); + return Scaffold( + appBar: const CustomAppBar( + title: "Select Services", + ), + body: SizedBox( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + DropDownText(widget.matchServicesArguments!.oldBranchName).toContainer( + padding: const EdgeInsets.only( + left: 14, + right: 14, + top: 21, + ), + ), + 12.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Checkbox( + value: context.watch().isAllSelected, + onChanged: (v) { + serviceVM.selectAllServices(v ?? false); + }, + ), + "Select All".toText( + isBold: true, + ) + ], + ), + Container( + alignment: Alignment.centerRight, + child: "Unselect All".toText( + color: MyColors.primaryColor, + isUnderLine: true, + isBold: true, + ), + margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 7), + ).onPress(() { + serviceVM.selectAllServices(false); + }), + ], + ), + 12.height, + Expanded( + child: Consumer(builder: (context, model, _) { + if (model.matchedServices == null) { + return const Center(child: CircularProgressIndicator()); + } else if (model.matchedServices!.isEmpty) { + return const EmptyWidget(); + } + return ListView.separated( + itemBuilder: (context, index) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Checkbox( + value: model.matchedServices![index].isExpandedOrSelected, + onChanged: (v) { + if (model.matchedServices![index].serviceItems!.isEmpty) { + Utils.showToast("No Items Available in this service"); + } else { + model.matchedServices![index].isExpandedOrSelected = v ?? false; + model.updateServiceItem(index, model.matchedServices![index].isExpandedOrSelected); + } + }, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + model.matchedServices![index].serviceDescription.toString().toText(fontSize: 16, isBold: true), + "${model.matchedServices![index].serviceItems!.where((c) => c.isUpdateOrSelected == true).length} items selected out of ${model.matchedServices![index].serviceItems!.length}" + .toText(color: MyColors.lightTextColor) + ], + ), + ), + SvgPicture.asset( + MyAssets.icEdit, + width: 16, + height: 16, + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 8).onPress( + () { + showMyBottomSheet( + context, + child: ItemsSelectionSheet( + model.matchedServices![index].serviceItems ?? [], + onItemCopied: (List selected) { + model.copyItems(index, selected); + }, + ), + ); + }, + ); + }, + separatorBuilder: (context, index) { + return 8.height; + }, + padding: const EdgeInsets.symmetric(horizontal: 14), + itemCount: model.matchedServices!.length, + ); + }), + ), + 12.height, + ShowFillButton( + title: "Copy Selected Services", + maxWidth: double.infinity, + margin: const EdgeInsets.all(14), + onPressed: () async { + Utils.showLoading(context); + List items = []; + for (var element in serviceVM.matchedServices!) { + items.addAll(element.serviceItems!.where((e) => e.isUpdateOrSelected == true).map((e) => e.id ?? 0).toList()); + } + Map map = { + "providerBranchID": widget.matchServicesArguments!.newBranch.toString(), + "serviceItems": items, + }; + print(jsonEncode(map)); + MResponse mResponse = await serviceVM.duplicateItems(map); + Utils.hideLoading(context); + Utils.showToast(mResponse.message ?? ""); + pop(context); + pop(context); + }, + ), + ], + ), + ), + + + ); + } +} diff --git a/lib/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart b/lib/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart new file mode 100644 index 0000000..3e040a4 --- /dev/null +++ b/lib/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart @@ -0,0 +1,141 @@ +import 'package:car_provider_app/config/provider_routes.dart'; +import 'package:car_provider_app/view_models/service_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/classes/consts.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/services/branch_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:geolocator/geolocator.dart'; + +class MatchServicesArguments { + int oldBranch, newBranch, categoryId; + String oldBranchName; + + MatchServicesArguments({required this.oldBranch, required this.oldBranchName, required this.newBranch, required this.categoryId}); +} + +class ApprovedBranchesListSheet extends StatelessWidget { + int newBranch, categoryId; + + ApprovedBranchesListSheet({required this.newBranch, required this.categoryId, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + height: MediaQuery.of(context).size.height / 1.2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Select Branch".toText(fontSize: 20, isBold: true), + "Select the branch to copy their items to this branch. You can modify the selection at any time.".toText( + fontSize: 12, + ), + 12.height, + Expanded( + child: Consumer( + builder: (context, model, _) { + if (model.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + List branches = []; + if (model.branches!.data != null) { + branches = model.branches!.data!.serviceProviderBranch!.where((element) => model.selectedBranchStatus == element.statusId).toList(); + } + return branches.isEmpty + ? Center(child: Text(LocaleKeys.no_branch.tr())) + : ListView.separated( + itemBuilder: (context, index) { + return Row( + children: [ + Container( + width: 74, + height: 50, + decoration: const BoxDecoration( + color: MyColors.darkPrimaryColor, + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + MyAssets.icBranches, + color: Colors.white, + ), + ), + 12.width, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + const Icon( + Icons.place, + size: 12, + color: MyColors.darkPrimaryColor, + ), + Geolocator.distanceBetween(AppState().currentLocation.latitude, AppState().currentLocation.latitude, double.parse(branches[index].latitude ?? "0"), + double.parse(branches[index].longitude ?? "0")) + .toStringAsFixed(2) + .toText( + fontSize: 12, + color: MyColors.darkPrimaryColor, + ) + ], + ), + Text( + branches[index].branchName ?? "", + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + "Tap to select".toText(fontSize: 10, color: MyColors.grey70Color), + ], + ), + ), + 12.width, + const Icon( + Icons.arrow_forward_rounded, + size: 16, + ), + ], + ).toContainer(isShadowEnabled: true).onPress(() async { + // branches[index].countryID = model.branchs!.data!.countryID; + // branches[index].countryName = model.branchs!.data!.countryName; + navigateWithName( + context, + ProviderAppRoutes.matchServices, + arguments: MatchServicesArguments( + oldBranch: branches[index].id ?? 0, + oldBranchName: branches[index].branchName ?? "", + newBranch: newBranch, + categoryId: categoryId, + ), + ); + }); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + itemCount: branches.length, + ); + } + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/views/settings/services/duplication/sheet/items_selection_sheet.dart b/lib/views/settings/services/duplication/sheet/items_selection_sheet.dart new file mode 100644 index 0000000..8a85a80 --- /dev/null +++ b/lib/views/settings/services/duplication/sheet/items_selection_sheet.dart @@ -0,0 +1,156 @@ +import 'package:car_provider_app/view_models/service_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/services/item_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; + +class ItemsSelectionSheet extends StatefulWidget { + final List serviceItems; + final Function(List) onItemCopied; + + const ItemsSelectionSheet(this.serviceItems, {required this.onItemCopied, Key? key}) : super(key: key); + + @override + State createState() => _ItemsSelectionSheetState(); +} + +class _ItemsSelectionSheetState extends State { + bool isAllItemsSelected = false; + List? tempItems; + + @override + void initState() { + super.initState(); + //tempItems=List.from(widget.serviceItems); + // tempItems=[...widget.serviceItems]; + //tempItems.addAll(widget.serviceItems); + tempItems = widget.serviceItems + .map( + (item) => ItemData.fromJson(item.toJson()) + + // ItemData( + // id: item.id, + // name: item.name, + // price: item.price, + // manufactureDate: item.manufactureDate, + // description: item.description, + // pictureUrl: item.pictureUrl, + // companyId: item.companyId, + // serviceProviderServiceId: item.serviceProviderServiceId, + // isActive: item.isActive, + // isAllowAppointment: item.isAllowAppointment, + // isAppointmentCompanyLoc: item.isAppointmentCompanyLoc, + // isAppointmentCustomerLoc: item.isAppointmentCompanyLoc, + // isUpdateOrSelected: item.isUpdateOrSelected, + // ), + ) + .toList(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + height: MediaQuery.of(context).size.height / 1.2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Select Items To Copy".toText(fontSize: 16, isBold: true), + 12.height, + TxtField( + hint: "Search Items", + onChanged: (v) {}, + ), + 6.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Checkbox( + // value: context.watch().isAllSelected, + value: isAllItemsSelected, + onChanged: (v) { + isAllItemsSelected = v ?? false; + selectAllTempItems(v ?? false); + }, + ), + "Select All".toText( + isBold: true, + ) + ], + ), + Container( + alignment: Alignment.centerRight, + child: "Unselect All".toText( + color: MyColors.primaryColor, + isUnderLine: true, + isBold: true, + ), + margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 7), + ).onPress(() { + isAllItemsSelected = false; + selectAllTempItems(false); + }), + ], + ), + Flexible( + child: ListView.separated( + itemBuilder: (context, index) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Checkbox( + value: tempItems![index].isUpdateOrSelected, + onChanged: (v) { + isAllItemsSelected = false; + updateTempItem(index, v ?? false); + }, + ), + Expanded( + child: tempItems![index].name.toString().toText(fontSize: 16, isBold: true), + ), + ], + ); + }, + separatorBuilder: (context, index) { + return const Divider(); + }, + itemCount: tempItems!.length, + ).toWhiteContainer(width: double.infinity), + ), + 12.height, + ShowFillButton( + title: "Copy Selected Item", + maxWidth: double.infinity, + onPressed: () { + widget.onItemCopied(tempItems ?? []); + pop(context); + }, + ), + ], + ), + ); + } + + selectAllTempItems(bool value) { + for (var element in tempItems ?? []) { + element.isUpdateOrSelected = value; + } + setState(() {}); + } + + updateTempItem(int index, bool value) { + tempItems![index].isUpdateOrSelected = value; + setState(() {}); + ; + } +} diff --git a/lib/views/settings/services/items_list_page.dart b/lib/views/settings/services/items_list_page.dart index 51faa0b..27ac6ce 100644 --- a/lib/views/settings/services/items_list_page.dart +++ b/lib/views/settings/services/items_list_page.dart @@ -5,8 +5,10 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; +import 'package:mc_common_app/models/model/provider_model.dart'; + import 'package:mc_common_app/models/services/item_model.dart'; +import 'package:mc_common_app/models/services/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -18,17 +20,17 @@ import 'package:provider/provider.dart'; import 'package:flutter_svg/svg.dart'; class ItemsListPage extends StatelessWidget { - ServiceProviderService? serviceProviderService; + ServiceModel? serviceProviderService; ItemsListPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - serviceProviderService ??= ModalRoute.of(context)!.settings.arguments as ServiceProviderService; - context.read().getServiceItems(serviceProviderService!.serviceId ?? 0); + serviceProviderService ??= ModalRoute.of(context)!.settings.arguments as ServiceModel; + context.read().getServiceItems(serviceProviderService!.serviceProviderServiceId ?? 0); return Scaffold( appBar: CustomAppBar( - title: serviceProviderService!.serviceName, + title: serviceProviderService!.serviceDescription, ), body: SizedBox( width: double.infinity, @@ -84,7 +86,7 @@ class ItemsListPage extends StatelessWidget { height: 16, ), ).onPress(() { - model.serviceItems!.data![index].isUpdate = true; + model.serviceItems!.data![index].isUpdateOrSelected = true; navigateWithName(context, ProviderAppRoutes.createItem, arguments: model.serviceItems!.data![index]); }), ], diff --git a/lib/views/settings/services/services_list_page.dart b/lib/views/settings/services/services_list_page.dart index 0ac6122..5b144cc 100644 --- a/lib/views/settings/services/services_list_page.dart +++ b/lib/views/settings/services/services_list_page.dart @@ -1,30 +1,35 @@ - import 'package:car_provider_app/config/provider_routes.dart'; +import 'package:car_provider_app/views/settings/services/duplication/sheet/approved_branches_list_sheet.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:mc_common_app/classes/consts.dart'; -import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package:mc_common_app/models/model/branch2.dart'; import 'package:mc_common_app/models/profile/categroy.dart'; +import 'package:mc_common_app/models/services/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/widgets/bottom_sheet.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/empty_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; -import 'package:mc_common_app/widgets/tab/menu_tabs.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:mc_common_app/widgets/tab/role_type_tab.dart'; class CreateBranchModel { - String branchId; - String branchName; - String? categoryId; - String? categoryName; - ServiceProviderService? serviceProviderService; + final String branchId; + final String branchName; + final String? categoryId; + final String? categoryName; + final ServiceModel? serviceProviderService; - CreateBranchModel({required this.branchId, required this.branchName, this.categoryId, this.categoryName, this.serviceProviderService}); + CreateBranchModel({ + required this.branchId, + required this.branchName, + this.categoryId, + this.categoryName, + this.serviceProviderService, + }); } class ServicesListPage extends StatefulWidget { @@ -35,22 +40,36 @@ class ServicesListPage extends StatefulWidget { } class _ServicesListPageState extends State { - int selectedTap = 0; - int selectedService = ServiceStatus.approvedOrActive.index; + int selectedTab = 0; + ServiceStatusEnum selectedService = ServiceStatusEnum.approvedOrActive; @override Widget build(BuildContext context) { - CategoryData categoryData = ModalRoute.of(context)!.settings.arguments as CategoryData; - List? services = []; - if (selectedService == ServiceStatus.approvedOrActive.index) { - services = categoryData.services!.where((i) => i.serviceStatus == selectedService + 1).toList(); + final categoryData = ModalRoute.of(context)!.settings.arguments as CategoryData; + List services = []; + if (selectedService == ServiceStatusEnum.approvedOrActive) { + services = categoryData.services!.where((i) => i.serviceStatus == ServiceStatusEnum.approvedOrActive.index + 1).toList(); } else { - services = categoryData.services!.where((i) => i.serviceStatus != selectedService + 1).toList(); + services = categoryData.services!.where((i) => i.serviceStatus != ServiceStatusEnum.approvedOrActive.index + 1).toList(); } return Scaffold( - appBar: const CustomAppBar( - title: "Services", + appBar: CustomAppBar( + title: 'Services', + actions: [ + IconButton( + icon: const Icon(Icons.copy), + onPressed: () { + showMyBottomSheet( + context, + child: ApprovedBranchesListSheet( + newBranch: int.parse(categoryData.branchId ?? ''), + categoryId: categoryData.id ?? 0, + ), + ); + }, + ), + ], ), body: SizedBox( width: double.infinity, @@ -59,25 +78,25 @@ class _ServicesListPageState extends State { Padding( padding: const EdgeInsets.only(left: 20, right: 20, top: 20), child: RoleTypeTab( - selectedTap, + selectedTab, [ - DropValue(0, "Active", ""), - DropValue(1, "Requested", ""), + DropValue(0, 'Active', ''), + DropValue(1, 'Requested', ''), ], width: (MediaQuery.of(context).size.width / 2) - 26, onSelect: (DropValue value) { setState(() { - selectedTap = value.id; - if (selectedTap == 0) { - selectedService = ServiceStatus.approvedOrActive.index; + selectedTab = value.id; + if (selectedTab == 0) { + selectedService = ServiceStatusEnum.approvedOrActive; } else { - selectedService = 1; + selectedService = value.id.toServiceStatusEnum(); } }); }, ), ), - 10.height, + const SizedBox(height: 10), Expanded( child: services.isEmpty ? const EmptyWidget() @@ -87,11 +106,15 @@ class _ServicesListPageState extends State { width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ - Expanded(child: services![index].serviceName.toString().toText(fontSize: 16, isBold: true)), + Expanded( + child: Text( + services[index].serviceDescription.toString(), + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ), Padding( padding: const EdgeInsets.all(4.0), child: SvgPicture.asset( @@ -104,16 +127,17 @@ class _ServicesListPageState extends State { context, ProviderAppRoutes.createServices3, arguments: CreateBranchModel( - branchId: categoryData.branchId ?? "", - branchName: categoryData.branchName ?? "", + branchId: categoryData.branchId ?? '', + branchName: categoryData.branchName ?? '', categoryId: categoryData.id.toString(), categoryName: categoryData.categoryName, - serviceProviderService: services![index], + serviceProviderService: services[index], ), ); }), ], ), + const SizedBox(height: 4), Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, @@ -121,13 +145,12 @@ class _ServicesListPageState extends State { Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ - 4.height, - showItem("Available for appointment:", "Yes", valueColor: Colors.green), - showItem("Allowing home service:", (services[index].isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green), - showItem("Home service range:", services[index].customerLocationRange.toString()), - showItem("Charges per KM:", services[index].rangePricePerKm.toString()), + const SizedBox(height: 4), + showItem('Available for appointment:', 'Yes', valueColor: Colors.green), + showItem('Allowing home service:', (services[index].isAllowAppointment ?? false) ? 'Yes' : 'No', valueColor: Colors.green), + showItem('Home service range:', services[index].customerLocationRange.toString()), + showItem('Charges per KM:', services[index].rangePricePerKm.toString()), ], ), ), @@ -146,12 +169,12 @@ class _ServicesListPageState extends State { ) .onPress( () { - navigateWithName(context, ProviderAppRoutes.itemsList, arguments: services![index]); + navigateWithName(context, ProviderAppRoutes.itemsList, arguments: services[index]); }, ); }, separatorBuilder: (context, index) { - return 12.height; + return const SizedBox(height: 12); }, padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10), itemCount: services.length, @@ -166,11 +189,10 @@ class _ServicesListPageState extends State { Widget showItem(String item, String value, {Color valueColor = Colors.black}) { return Row( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ - item.toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - 4.width, - value.toText(fontSize: 12, color: valueColor, isBold: true), + Text(item, style: const TextStyle(fontSize: 12, color: MyColors.lightTextColor, fontWeight: FontWeight.bold)), + const SizedBox(width: 4), + Text(value, style: TextStyle(fontSize: 12, color: valueColor, fontWeight: FontWeight.bold)), ], ); } diff --git a/pubspec.yaml b/pubspec.yaml index a072f4d..791cfc2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,6 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev - # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +.