From b8c890f15e16fd3afc398676ca5710078a3a9681 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Mon, 2 Sep 2024 14:43:17 +0300 Subject: [PATCH] Formatting --- lib/classes/consts.dart | 1 + lib/config/routes.dart | 62 ++------ lib/main.dart | 1 - .../advertisment_models/ad_details_model.dart | 12 +- .../chat_models/chat_message_model.dart | 16 ++- .../general_models/generic_resp_model.dart | 22 +-- .../branch_detail_model.dart | 26 +--- lib/models/requests_models/request_model.dart | 19 ++- lib/repositories/branch_repo.dart | 50 ++++++- lib/repositories/request_repo.dart | 43 +++++- lib/view_models/chat_view_model.dart | 13 +- lib/view_models/requests_view_model.dart | 52 +++---- lib/view_models/service_view_model.dart | 76 +++++++++- .../ads_images_corousel_widget.dart | 105 ++++++++------ .../components/ads_list_widget.dart | 10 +- lib/views/chat/chat_view.dart | 133 +++++++++--------- lib/views/requests/create_request_page.dart | 2 +- lib/views/requests/request_bottomsheets.dart | 110 +++++++++++++++ lib/views/requests/widget/request_item.dart | 12 +- lib/widgets/extensions/extensions_widget.dart | 20 +-- pubspec.yaml | 1 - 21 files changed, 514 insertions(+), 272 deletions(-) create mode 100644 lib/views/requests/request_bottomsheets.dart diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 34d26ba..d3fc14e 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -192,6 +192,7 @@ class GlobalConsts { static String adDurationPhoneNumberError = "Phone number cannot be empty"; static String adReservablePriceErrorConst = "Ad Reservable price cannot be empty"; static String homeLocationEmptyError = "Home location cannot be empty"; + static String fillAllFields = "Please fill out all the fields."; static String reserveAdPriceInfo = "Some dummy description to explain the following concept. This price will be for 24 hours and if a user cancels the reservations before 24 hours then the amount will be automatically refunded to the buyer."; } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 84b8932..ba06962 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -128,72 +128,32 @@ class AppRoutes { forgetPassword: (context) => const ForgetPasswordPage(), loginVerification: (context) => const LoginVerificationPage(), loginWithPassword: (context) => const LoginWithPassword(), - loginMethodSelection: (context) => - LoginMethodSelectionPage(ModalRoute - .of(context)! - .settings - .arguments as String), - completeProfile: (context) => - CompleteProfilePage(ModalRoute - .of(context)! - .settings - .arguments as RegisterUserRespModel), + loginMethodSelection: (context) => LoginMethodSelectionPage(ModalRoute.of(context)!.settings.arguments as String), + completeProfile: (context) => CompleteProfilePage(ModalRoute.of(context)!.settings.arguments as RegisterUserRespModel), verifyPassword: (context) => VerifyPasswordPage(), - confirmNewPasswordPage: (context) => - ConfirmNewPasswordPage(ModalRoute - .of(context)! - .settings - .arguments as String), + confirmNewPasswordPage: (context) => ConfirmNewPasswordPage(ModalRoute.of(context)!.settings.arguments as String), changePassword: (context) => const ChangePasswordPage(), - forgetPasswordMethodPage: (context) => - ForgetPasswordMethodPage(ModalRoute - .of(context)! - .settings - .arguments as String), + forgetPasswordMethodPage: (context) => ForgetPasswordMethodPage(ModalRoute.of(context)!.settings.arguments as String), changeMobilePage: (context) => ChangeMobilePage(), changeEmailPage: (context) => const ChangeEmailPage(), editAccountPage: (context) => const EditAccountPage(), profileView: (context) => const ProfileScreen(), settingOptionsLanguages: (context) => const SettingOptionsLanguage(), settingOptionsHelp: (context) => const SettingOptionsHelp(), - providerLicensePage: (context) => ProviderLicensePage(), + providerLicensePage: (context) => const ProviderLicensePage(), // common pages - AppRoutes.adsDetailView: (context) => - AdsDetailView(adDetails: ModalRoute - .of(context)! - .settings - .arguments as AdDetailsModel), + AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel), AppRoutes.createAdView: (context) => const CreateAdView(), AppRoutes.adsFilterView: (context) => const AdsFilterView(), - AppRoutes.selectAdTypeView: (context) => - SelectAdTypeView(arguments: ModalRoute - .of(context)! - .settings - .arguments as List), - AppRoutes.chatView: (context) => - ChatView(chatViewArguments: ModalRoute - .of(context)! - .settings - .arguments as ChatViewArguments), - AppRoutes.offersListPage: (context) => - OfferListPage(offerListPageArguments: ModalRoute - .of(context)! - .settings - .arguments as OfferListPageArguments), - AppRoutes.adsBuyerChatsListView: (context) => - AdsBuyerChatsView(buyersListViewArguments: ModalRoute - .of(context)! - .settings - .arguments as List), + AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(arguments: ModalRoute.of(context)!.settings.arguments as List), + AppRoutes.chatView: (context) => ChatView(chatViewArguments: ModalRoute.of(context)!.settings.arguments as ChatViewArguments), + AppRoutes.offersListPage: (context) => OfferListPage(offerListPageArguments: ModalRoute.of(context)!.settings.arguments as OfferListPageArguments), + AppRoutes.adsBuyerChatsListView: (context) => AdsBuyerChatsView(buyersListViewArguments: ModalRoute.of(context)!.settings.arguments as List), AppRoutes.createRequestPage: (context) => const CreateRequestPage(), AppRoutes.settingOptionsFaqs: (context) => const SettingOptionsFAQs(), AppRoutes.settingOptionsInviteFriends: (context) => const SettingOptionsInviteFriends(), - AppRoutes.paymentMethodsView: (context) => - PaymentMethodsView(paymentType: ModalRoute - .of(context)! - .settings - .arguments as PaymentTypes), + AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(paymentType: ModalRoute.of(context)!.settings.arguments as PaymentTypes), }; } diff --git a/lib/main.dart b/lib/main.dart index c7e6f71..fffbb02 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'package:logger/logger.dart'; Logger logger = Logger(printer: PrettyPrinter(printEmojis: false, colors: true, printTime: false)); diff --git a/lib/models/advertisment_models/ad_details_model.dart b/lib/models/advertisment_models/ad_details_model.dart index 4ec8bf3..29881a3 100644 --- a/lib/models/advertisment_models/ad_details_model.dart +++ b/lib/models/advertisment_models/ad_details_model.dart @@ -165,7 +165,7 @@ class Vehicle { Condition? sellertype; Condition? transmission; AdsDuration? duration; - List? image; + List? image; List? damagereport; String? vehicleDescription; String? vehicleTitle; @@ -220,9 +220,9 @@ class Vehicle { transmission = json['transmission'] != null ? Condition.fromJson(json['transmission']) : null; duration = json['duration'] != null ? AdsDuration.fromJson(json['duration']) : null; if (json['image'] != null) { - image = []; + image = []; json['image'].forEach((v) { - image!.add(AdImage.fromJson(v)); + image!.add(GenericImageModel.fromJson(v)); }); } if (json['damagereport'] != null) { @@ -363,15 +363,15 @@ class AdsDuration { } } -class AdImage { +class GenericImageModel { int? id; String? imageName; String? imageUrl; bool? isActive; - AdImage({this.id, this.imageName, this.imageUrl, this.isActive}); + GenericImageModel({this.id, this.imageName, this.imageUrl, this.isActive}); - AdImage.fromJson(Map json) { + GenericImageModel.fromJson(Map json) { id = json['id']; imageName = json['imageName']; imageUrl = json['imageUrl']; diff --git a/lib/models/chat_models/chat_message_model.dart b/lib/models/chat_models/chat_message_model.dart index 82b0257..07efb9d 100644 --- a/lib/models/chat_models/chat_message_model.dart +++ b/lib/models/chat_models/chat_message_model.dart @@ -71,7 +71,11 @@ class ReqOffer { int? offerStatus; String? offerStatusText; String? comment; + String? serviceItem; + String? itemManufacturer; + String? manufacturedDate; double? price; + RequestsTypeEnum? requestsTypeEnum; RequestOfferStatusEnum? requestOfferStatusEnum; ReqOffer({ @@ -81,8 +85,12 @@ class ReqOffer { this.offerStatus, this.offerStatusText, this.comment, + this.serviceItem, + this.itemManufacturer, + this.manufacturedDate, this.price, this.requestOfferStatusEnum, + this.requestsTypeEnum, }); ReqOffer.fromJson(Map json) { @@ -92,8 +100,12 @@ class ReqOffer { offerStatus = json['offerStatus']; offerStatusText = json['offerStatusText']; comment = json['comment']; + serviceItem = json['serviceItem']; + itemManufacturer = json['itemManufacturer']; + manufacturedDate = json['manufacturedDate']; price = json['price']; requestOfferStatusEnum = ((json['offerStatus']) as int).toRequestOfferStatusEnum(); + requestsTypeEnum = RequestsTypeEnum.serviceRequest; // TODO: THIS SHOULD COME FROM API } } @@ -104,7 +116,3 @@ class OfferRequestCommentModel { OfferRequestCommentModel({this.index, this.title, this.isSelected}); } - - - - diff --git a/lib/models/general_models/generic_resp_model.dart b/lib/models/general_models/generic_resp_model.dart index c6b23fd..557d725 100644 --- a/lib/models/general_models/generic_resp_model.dart +++ b/lib/models/general_models/generic_resp_model.dart @@ -319,21 +319,19 @@ class VehiclePostingDamageParts { return data; } -@override -String toString() { - return 'VehiclePostingDamageParts{id: $id, comment: $comment, vehicleImageBase64: $vehicleImageBase64, vehicleDamagePartID: $vehicleDamagePartID, vehiclePostingID: $vehiclePostingID, isActive: $isActive}'; -} + @override + String toString() { + return 'VehiclePostingDamageParts{id: $id, comment: $comment, vehicleImageBase64: $vehicleImageBase64, vehicleDamagePartID: $vehicleDamagePartID, vehiclePostingID: $vehiclePostingID, isActive: $isActive}'; + } } - class BranchPostingImages { int? id; String? imageName; String? imageUrl; String? imageStr; - BranchPostingImages( - {this.id, this.imageName, this.imageUrl, this.imageStr}); + BranchPostingImages({this.id, this.imageName, this.imageUrl, this.imageStr}); BranchPostingImages.fromJson(Map json) { id = json['id']; @@ -341,14 +339,4 @@ class BranchPostingImages { imageUrl = json['imageUrl']; imageStr = json['imageStr']; } - - Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['imageName'] = this.imageName; - data['imageUrl'] = this.imageUrl; - data['imageStr'] = this.imageStr; - return data; - } } - diff --git a/lib/models/provider_branches_models/branch_detail_model.dart b/lib/models/provider_branches_models/branch_detail_model.dart index edb4af9..dfbdbd8 100644 --- a/lib/models/provider_branches_models/branch_detail_model.dart +++ b/lib/models/provider_branches_models/branch_detail_model.dart @@ -20,7 +20,7 @@ class BranchDetailModel { String? openTime; String? closeTime; BranchStatusEnum? branchStatus; - List? branchImages; + List? branchImages; int? statusId; String? statusText; String? branchStatusLabel; @@ -32,22 +32,6 @@ class BranchDetailModel { String? countryName; bool isExpanded = false; bool? isFavorite; - -//I/flutter (23146): │ "id": 1021, -// I/flutter (23146): │ "serviceProviderID": 10, -// I/flutter (23146): │ "serviceProviderName": "string", -// I/flutter (23146): │ "cityID": 1, -// I/flutter (23146): │ "cityName": "Riyadh", -// I/flutter (23146): │ "branchName": "Al Arouba Cars", -// I/flutter (23146): │ "branchDescription": "des", -// I/flutter (23146): │ "address": "3289 Hilal Bin Omayah St - حي العليا, حي العليا, الرياض, RHOD3289, Saudi Arabia", -// I/flutter (23146): │ "latitude": "24.708521303151027", -// I/flutter (23146): │ "longitude": "46.666924171149724", -// I/flutter (23146): │ "distanceKM": 0.0, -// I/flutter (23146): │ "openTime": "09:00", -// I/flutter (23146): │ "closeTime": "18:00", -// I/flutter (23146): │ "branchStatus": 3, -// I/flutter (23146): │ "branchStatusText": "ApprovedOrActive", BranchDetailModel({ this.id, this.serviceProviderId, @@ -78,18 +62,18 @@ class BranchDetailModel { required this.isExpanded, }); - List populateBranchImages(value) { - List images = []; + List populateBranchImages(value) { + List images = []; if (value != null) { value.forEach((v) { - images.add(AdImage.fromJson(v)); + images.add(GenericImageModel.fromJson(v)); }); } return images; } BranchDetailModel.fromJson(Map json) { - List images = populateBranchImages(json["serviceProviderBranchImage"]); + List images = populateBranchImages(json["serviceProviderBranchImage"]); id = json["id"]; serviceProviderId = json["serviceProviderID"]; branchProfileImage = images.isNotEmpty ? images.first.imageUrl ?? "" : null; diff --git a/lib/models/requests_models/request_model.dart b/lib/models/requests_models/request_model.dart index 3a0d5c9..8bd7c5b 100644 --- a/lib/models/requests_models/request_model.dart +++ b/lib/models/requests_models/request_model.dart @@ -1,4 +1,5 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/chat_models/chat_message_model.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -24,7 +25,7 @@ class RequestModel { int year; bool isNew; String description; - List requestImages; + List? requestImages; int cityId; dynamic city; double price; @@ -35,8 +36,8 @@ class RequestModel { bool isActive; int createdBy; String? createdOn; - dynamic modifiedBy; - dynamic modifiedOn; + int? modifiedBy; + String? modifiedOn; List chatMessages; RequestModel({ @@ -77,6 +78,16 @@ class RequestModel { required this.chatMessages, }); + List populateRequestImages(value) { + List images = []; + if (value != null) { + value.forEach((v) { + images.add(GenericImageModel.fromJson(v)); + }); + } + return images; + } + factory RequestModel.fromJson(Map json) { return RequestModel( requestType: json["requestType"], @@ -100,7 +111,7 @@ class RequestModel { year: json["year"], isNew: json["isNew"], description: json["description"], - requestImages: List.from(json["requestImages"].map((x) => x)), + requestImages: List.from(json["requestImages"].map((x) => GenericImageModel.fromJson(x))), cityId: json["cityID"], city: json["city"], price: json["price"], diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index 01e8f9c..5452d36 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -22,6 +22,8 @@ abstract class BranchRepo { required String branchDescription, required int cityId, required String address, + required String openTime, + required String closeTime, required double latitude, required double longitude, required List imagesList, @@ -31,6 +33,8 @@ abstract class BranchRepo { required int branchId, required String branchName, required String branchDescription, + required String openTime, + required String closeTime, required int cityId, required String address, required String latitude, @@ -39,6 +43,8 @@ abstract class BranchRepo { bool isNeedToDelete = true, }); + Future deleteBranch({required int branchId}); + Future fetchAllBranches(); Future fetchBranchCategory(); @@ -114,6 +120,8 @@ class BranchRepoImp implements BranchRepo { required String branchDescription, required int cityId, required String address, + required String openTime, + required String closeTime, required double latitude, required double longitude, required List imagesList, @@ -135,6 +143,8 @@ class BranchRepoImp implements BranchRepo { "branchDescription": branchDescription, "cityID": cityId.toString(), "address": address, + "openTime": openTime, + "closeTime": closeTime, "latitude": latitude, "longitude": longitude, "isActive": true, @@ -219,6 +229,8 @@ class BranchRepoImp implements BranchRepo { required int branchId, required String branchName, required String branchDescription, + required String openTime, + required String closeTime, required int cityId, required String address, required String latitude, @@ -226,6 +238,17 @@ class BranchRepoImp implements BranchRepo { required List imagesList, bool isNeedToDelete = true, }) async { + List serviceProviderBranchImages = []; + for (var element in imagesList) { + var imageMap = { + "id": element.id ?? 0, + "imageName": element.imageName, + "imageUrl": element.imageUrl, + "imageStr": element.imageStr, + }; + serviceProviderBranchImages.add(imageMap); + } + String lat = "0", long = "0"; try { lat = latitude.toString().substring(0, 9); @@ -236,16 +259,29 @@ class BranchRepoImp implements BranchRepo { "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", "branchName": branchName, "branchDescription": branchDescription, + "openTime": openTime, + "closeTime": closeTime, "cityID": cityId, "address": address, "latitude": lat, "longitude": long, + "serviceProviderBranchImages": serviceProviderBranchImages, "isActive": isNeedToDelete }; String t = AppState().getUser.data!.accessToken ?? ""; return await apiClient.postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); } + @override + Future deleteBranch({required int branchId}) async { + var postParams = { + "id": branchId, + "isActive": false, + }; + String t = AppState().getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); + } + @override Future createService(List> map) async { String t = AppState().getUser.data!.accessToken ?? ""; @@ -306,7 +342,6 @@ class BranchRepoImp implements BranchRepo { "ProviderBranchID": branchID, }; String t = AppState().getUser.data!.accessToken ?? ""; - debugPrint("token " + t); return await apiClient.getJsonForObject((json) => Services.fromJson(json), ApiConsts.getProviderServices, queryParameters: postParams, token: t); } @@ -318,7 +353,16 @@ class BranchRepoImp implements BranchRepo { @override Future> getAllNearBranchAndServices() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.getAllNearBranches, token: appState.getUser.data!.accessToken); + var queryParameters = { + "isActive": "true", + "Status": "3", + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getAllNearBranches, + token: appState.getUser.data!.accessToken, + queryParameters: queryParameters, + ); List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); return nearBranches; } @@ -390,6 +434,8 @@ class BranchRepoImp implements BranchRepo { "Rating": "${rating ?? 0}", "Latitude": latitude.toString(), "Longitude": longitude.toString(), + "Status": "3", + }; GenericRespModel adsGenericModel = await apiClient.getJsonForObject( diff --git a/lib/repositories/request_repo.dart b/lib/repositories/request_repo.dart index 18fcd7b..d4e7005 100644 --- a/lib/repositories/request_repo.dart +++ b/lib/repositories/request_repo.dart @@ -10,7 +10,19 @@ import 'package:mc_common_app/models/requests_models/request_model.dart'; import 'package:mc_common_app/utils/enums.dart'; abstract class RequestRepo { - Future createRequest(Map map); + Future createRequest({ + required int requestTypeId, + required int vehicleTypeId, + required String brand, + required String model, + required String year, + required int countryID, + required int cityID, + required String price, + required String description, + required bool isSpecialServiceNeeded, + required List requestImages, + }); Future> getOffersByRequest({required int requestId, int serviceProviderId = 0}); @@ -28,7 +40,34 @@ class RequestRepoImp implements RequestRepo { AppState appState = injector.get(); @override - Future createRequest(Map postParams) async { + Future createRequest({ + required int requestTypeId, + required int vehicleTypeId, + required String brand, + required String model, + required String year, + required int countryID, + required int cityID, + required String price, + required String description, + required bool isSpecialServiceNeeded, + required List requestImages, + }) async { + Map postParams = { + "customerID": AppState().getUser.data!.userInfo!.customerId ?? 0, + "requestType": requestTypeId, + "vehicleTypeID": vehicleTypeId, + "brand": brand, + "model": model, + "year": year, + "isNew": true, + "countryID": countryID, + "cityID": cityID, + "price": price, + "description": description, + "isSpecialServiceNeeded": false, + "requestImages": requestImages, + }; GenericRespModel enumGenericModel = await apiClient.postJsonForObject( (json) => GenericRespModel.fromJson(json), ApiConsts.createRequest, diff --git a/lib/view_models/chat_view_model.dart b/lib/view_models/chat_view_model.dart index 2257e18..7323e48 100644 --- a/lib/view_models/chat_view_model.dart +++ b/lib/view_models/chat_view_model.dart @@ -54,12 +54,13 @@ class ChatVM extends ChangeNotifier { if (!isUserOnChatScreen) { return; } - - scrollController.animateTo( - scrollController.position.maxScrollExtent + 200, // for the text field - duration: const Duration(seconds: 1), - curve: Curves.fastOutSlowIn, - ); + if (scrollController.hasClients) { + scrollController.animateTo( + scrollController.position.maxScrollExtent + 200, // for the text field + duration: const Duration(seconds: 1), + curve: Curves.fastOutSlowIn, + ); + } } List offerRejectModelList = [ diff --git a/lib/view_models/requests_view_model.dart b/lib/view_models/requests_view_model.dart index 94e0479..bb34445 100644 --- a/lib/view_models/requests_view_model.dart +++ b/lib/view_models/requests_view_model.dart @@ -160,7 +160,6 @@ class RequestsVM extends BaseVM { SelectionModel vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); Future getVehicleTypes() async { - resetRequestCreationForm(); isFetchingVehicleType = true; vehicleTypes = await commonRepo.getVehicleTypes(); isFetchingVehicleType = false; @@ -168,12 +167,16 @@ class RequestsVM extends BaseVM { } resetRequestCreationForm() { - vehicleTypeId.selectedId = -1; - vehicleBrandId.selectedId = -1; - vehicleModelId.selectedId = -1; - vehicleModelYearId.selectedId = -1; - vehicleCountryId.selectedId = -1; - vehicleCityId.selectedId = -1; + requestTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + pickedVehicleImages.clear(); + price = ''; + description = ''; } void updateSelectionVehicleTypeId(SelectionModel id) async { @@ -251,7 +254,8 @@ class RequestsVM extends BaseVM { } //Request Management - String price = "", description = ""; + String price = ""; + String description = ""; updatePrice(String v) { price = v; @@ -289,27 +293,26 @@ class RequestsVM extends BaseVM { vehicleImages.forEach((element) { requestImages.add(element.toJson()); }); - Map body = { - "customerID": AppState().getUser.data!.userInfo!.customerId ?? 0, - "requestType": requestTypeId.selectedId, - "vehicleTypeID": vehicleTypeId.selectedId, - "brand": vehicleBrandId.selectedOption, - "model": vehicleModelId.selectedOption, - "year": vehicleModelYearId.selectedOption, - "isNew": true, - "countryID": vehicleCountryId.selectedId, - "cityID": vehicleCityId.selectedId, - "price": price, - "description": description, - "isSpecialServiceNeeded": false, - "requestImages": requestImages, - }; + try { - GenericRespModel respModel = await requestRepo.createRequest(body); + GenericRespModel respModel = await requestRepo.createRequest( + requestTypeId: requestTypeId.selectedId, + vehicleTypeId: vehicleTypeId.selectedId, + brand: vehicleBrandId.selectedOption, + model: vehicleModelId.selectedOption, + year: vehicleModelYearId.selectedOption, + countryID: vehicleCountryId.selectedId, + cityID: vehicleCityId.selectedId, + price: price, + description: description, + isSpecialServiceNeeded: false, + requestImages: requestImages, + ); Utils.hideLoading(context); if (respModel.messageStatus == 1) { Utils.showToast(LocaleKeys.requestSuccessfullyCreated.tr()); Navigator.pop(context); + resetRequestCreationForm(); await getRequests(appType: AppType.customer); } else { Utils.showToast(respModel.message.toString()); @@ -494,6 +497,7 @@ class RequestsVM extends BaseVM { senderId: senderId ?? "", requestIndex: requestIndex, providerIndex: -1, + requestModel: requestModel, ); ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest); diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index 7cbec07..f2d1545 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; 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/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/repositories/branch_repo.dart'; @@ -60,6 +61,17 @@ class ServiceVM extends BaseVM { String address = ""; String branchName = ""; String branchDescription = ""; + String branchErrorScreen = ""; + + void updateSelectionOpenTime(String date) { + openTime = date; + notifyListeners(); + } + + void updateSelectionCloseTime(String date) { + closedTime = date; + notifyListeners(); + } double getDistanceFromMe({ required String destLatitude, @@ -213,6 +225,9 @@ class ServiceVM extends BaseVM { address = ""; branchName = ""; branchDescription = ""; + openTime = ""; + closedTime = ""; + branchErrorScreen = ""; latitude = 0; longitude = 0; role = -1; @@ -225,6 +240,7 @@ class ServiceVM extends BaseVM { categoryDropList = []; servicesDropList = []; services = null; + pickedBranchImages.clear(); } // Create Services @@ -402,7 +418,28 @@ class ServiceVM extends BaseVM { return branchPostingImages; } - Future onCreateBranchPressed({required BuildContext context, required String branchName, required String branchDesc, required int cityID, required String address, required double latitude, required double longitude}) async { + Future onCreateBranchPressed({ + required BuildContext context, + required String branchName, + required String branchDesc, + required int cityID, + required String address, + required String openTime, + required String closeTime, + required double latitude, + required double longitude, + }) async { + if (branchName.isEmpty || branchDesc.isEmpty || address.isEmpty) { + branchErrorScreen = GlobalConsts.fillAllFields; + notifyListeners(); + return; + } + + if (pickedBranchImages.length < 3) { + branchErrorScreen = GlobalConsts.attachImageError; + notifyListeners(); + return; + } try { Utils.showLoading(context); @@ -414,6 +451,8 @@ class ServiceVM extends BaseVM { GenericRespModel res = await branchRepo.createBranch( branchName: branchName, branchDescription: branchDesc, + openTime: branchDesc, + closeTime: branchDesc, cityId: cityID, address: address, latitude: latitude, @@ -440,11 +479,24 @@ class ServiceVM extends BaseVM { required int branchID, required String branchName, required String branchDesc, + required String openTime, + required String closedTime, required int cityID, required String address, required String latitude, required String longitude, }) async { + if (branchName.isEmpty || branchDesc.isEmpty || address.isEmpty) { + branchErrorScreen = GlobalConsts.fillAllFields; + notifyListeners(); + return; + } + + if (pickedBranchImages.length < 3) { + branchErrorScreen = GlobalConsts.attachImageError; + notifyListeners(); + return; + } try { Utils.showLoading(context); @@ -458,6 +510,8 @@ class ServiceVM extends BaseVM { branchId: branchID, branchName: branchName, branchDescription: branchDesc, + openTime: openTime, + closeTime: closedTime, cityId: cityID, address: address, latitude: latitude, @@ -478,4 +532,24 @@ class ServiceVM extends BaseVM { Utils.showToast(e.toString()); } } + + Future onDeleteBranchPressed({required BuildContext context, required int branchID}) async { + try { + Utils.showLoading(context); + + GenericRespModel res = await branchRepo.deleteBranch(branchId: branchID); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast(LocaleKeys.branch_deleted.tr()); + pop(context); + pop(context); + getBranchAndServices(); + } else { + Utils.showToast(res.message ?? ""); + } + } catch (e) { + Utils.hideLoading(context); + Utils.showToast(e.toString()); + } + } } diff --git a/lib/views/advertisement/components/ads_images_corousel_widget.dart b/lib/views/advertisement/components/ads_images_corousel_widget.dart index 80a4b56..252ffbe 100644 --- a/lib/views/advertisement/components/ads_images_corousel_widget.dart +++ b/lib/views/advertisement/components/ads_images_corousel_widget.dart @@ -1,11 +1,15 @@ import 'package:carousel_slider/carousel_slider.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.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/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:sizer/sizer.dart'; class ImagesCorouselWidget extends StatefulWidget { - final List imagesList; + final List imagesList; const ImagesCorouselWidget({super.key, required this.imagesList}); @@ -19,48 +23,65 @@ class _CarouselWithIndicatorState extends State { @override Widget build(BuildContext context) { - return Column(children: [ - CarouselSlider( - items: widget.imagesList - .map((item) => Container( - margin: const EdgeInsets.all(5.0), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(5.0)), - child: item.imageUrl.buildNetworkImage( - height: 80, - width: 80, + if (widget.imagesList.isEmpty) { + return Center( + child: SizedBox( + height: 25.h, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "No Images to Show".toText( + fontSize: 12, + color: MyColors.lightTextColor, + isBold: true, + ), + ], + ), + ), + ); + } + return SizedBox( + height: 25.h, + child: Column(children: [ + CarouselSlider( + items: widget.imagesList + .map((item) => Container( + margin: const EdgeInsets.all(5.0), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + child: item.imageUrl.buildNetworkImage(), ), - ), - )) - .toList(), - carouselController: _controller, - options: CarouselOptions( - autoPlay: false, - enlargeCenterPage: false, - aspectRatio: 1.8, - onPageChanged: (index, reason) { - setState(() { - _current = index; - }); - }), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: widget.imagesList.asMap().entries.map((entry) { - return GestureDetector( - onTap: () => _controller.animateToPage(entry.key), - child: Container( - width: 12.0, - height: 12.0, - margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _current == entry.key ? MyColors.darkPrimaryColor : MyColors.lightTextColor.withOpacity(0.5), + )) + .toList(), + carouselController: _controller, + options: CarouselOptions( + autoPlay: false, + enlargeCenterPage: false, + aspectRatio: 1.8, + onPageChanged: (index, reason) { + setState(() { + _current = index; + }); + }), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: widget.imagesList.asMap().entries.map((entry) { + return GestureDetector( + onTap: () => _controller.animateToPage(entry.key), + child: Container( + width: 12.0, + height: 12.0, + margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _current == entry.key ? MyColors.darkPrimaryColor : MyColors.lightTextColor.withOpacity(0.5), + ), ), - ), - ); - }).toList(), - ), - ]); + ); + }).toList(), + ), + ]), + ); } } diff --git a/lib/views/advertisement/components/ads_list_widget.dart b/lib/views/advertisement/components/ads_list_widget.dart index 0c10f18..5284cf9 100644 --- a/lib/views/advertisement/components/ads_list_widget.dart +++ b/lib/views/advertisement/components/ads_list_widget.dart @@ -70,15 +70,7 @@ class AdCard extends StatelessWidget { children: [ Row( children: [ - Image.network( - adDetails.vehicle!.image == null || adDetails.vehicle!.image!.isEmpty ? "" : adDetails.vehicle!.image!.first.imageUrl!, - errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) { - return const SizedBox( - width: 80, - height: 80, - child: Icon(Icons.error_outline), - ); - }, + adDetails.vehicle!.image!.first.imageUrl.buildNetworkImage( width: 80, height: 80, fit: BoxFit.cover, diff --git a/lib/views/chat/chat_view.dart b/lib/views/chat/chat_view.dart index eb591e8..c32245b 100644 --- a/lib/views/chat/chat_view.dart +++ b/lib/views/chat/chat_view.dart @@ -6,6 +6,7 @@ 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/generated/locale_keys.g.dart'; +import 'package:mc_common_app/main.dart'; import 'package:mc_common_app/models/chat_models/chat_message_model.dart'; import 'package:mc_common_app/models/requests_models/request_model.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -14,6 +15,7 @@ import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart'; import 'package:mc_common_app/view_models/requests_view_model.dart'; +import 'package:mc_common_app/views/requests/request_bottomsheets.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; @@ -63,69 +65,69 @@ class _ChatViewState extends State { super.dispose(); } - Future buildSendOfferBottomSheet(BuildContext context) { - RequestModel requestDetail = chatViewArgumentsForRequest!.requestModel!; - return showModalBottomSheet( - context: context, - isScrollControlled: true, - enableDrag: true, - builder: (BuildContext context) { - return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { - return InfoBottomSheet( - title: LocaleKeys.makeAnOffer.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), - description: Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 12.height, - TxtField( - value: requestsVM.offerPrice, - errorValue: requestsVM.offerPriceError, - keyboardType: TextInputType.number, - hint: LocaleKeys.enterAmount.tr(), - numbersOnly: true, - onChanged: (v) => requestsVM.updateOfferPrice(v), - ), - 12.height, - TxtField( - maxLines: 5, - value: requestsVM.offerDescription, - errorValue: requestsVM.offerDescriptionError, - keyboardType: TextInputType.text, - hint: LocaleKeys.description.tr(), - onChanged: (v) => requestsVM.updateOfferDescription(v), - ), - ], - ), - 25.height, - ShowFillButton( - title: LocaleKeys.submit.tr(), - onPressed: () { - requestsVM.onSendOfferPressed( - context: context, - receiverId: requestDetail.customerID, - message: requestsVM.offerDescription, - requestId: requestDetail.id, - offerPrice: requestsVM.offerPrice, - requestModel: requestDetail, - requestIndex: chatViewArgumentsForRequest!.requestIndex, - isFromChatScreen: true, - ); - }, - maxWidth: double.infinity, - ), - 19.height, - ], - ), - )); - }); - }, - ); - } + // Future buildSendOfferBottomSheet(BuildContext context) { + // RequestModel requestDetail = chatViewArgumentsForRequest!.requestModel!; + // return showModalBottomSheet( + // context: context, + // isScrollControlled: true, + // enableDrag: true, + // builder: (BuildContext context) { + // return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { + // return InfoBottomSheet( + // title: LocaleKeys.makeAnOffer.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), + // description: Padding( + // padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // 12.height, + // TxtField( + // value: requestsVM.offerPrice, + // errorValue: requestsVM.offerPriceError, + // keyboardType: TextInputType.number, + // hint: LocaleKeys.enterAmount.tr(), + // numbersOnly: true, + // onChanged: (v) => requestsVM.updateOfferPrice(v), + // ), + // 12.height, + // TxtField( + // maxLines: 5, + // value: requestsVM.offerDescription, + // errorValue: requestsVM.offerDescriptionError, + // keyboardType: TextInputType.text, + // hint: LocaleKeys.description.tr(), + // onChanged: (v) => requestsVM.updateOfferDescription(v), + // ), + // ], + // ), + // 25.height, + // ShowFillButton( + // title: LocaleKeys.submit.tr(), + // onPressed: () { + // requestsVM.onSendOfferPressed( + // context: context, + // receiverId: requestDetail.customerID, + // message: requestsVM.offerDescription, + // requestId: requestDetail.id, + // offerPrice: requestsVM.offerPrice, + // requestModel: requestDetail, + // requestIndex: chatViewArgumentsForRequest!.requestIndex, + // isFromChatScreen: true, + // ); + // }, + // maxWidth: double.infinity, + // ), + // 19.height, + // ], + // ), + // )); + // }); + // }, + // ); + // } Future onTextMessageSend() async { bool status = false; @@ -202,8 +204,9 @@ class _ChatViewState extends State { color: MyColors.darkPrimaryColor, size: 30, ).onPress( - () async { - buildSendOfferBottomSheet(context); + () { + RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(requestIndex: chatViewArgumentsForRequest!.requestIndex , requestModel: chatViewArgumentsForRequest!.requestModel!); + buildSendOfferBottomSheet(context, requestDetailArguments); }, ), ), diff --git a/lib/views/requests/create_request_page.dart b/lib/views/requests/create_request_page.dart index 2c3f9f7..3b08da8 100644 --- a/lib/views/requests/create_request_page.dart +++ b/lib/views/requests/create_request_page.dart @@ -33,7 +33,7 @@ class CreateRequestPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.vehicleDetails.tr().toText(fontSize: 18, isBold: true), + LocaleKeys.requestType.tr().toText(fontSize: 18, isBold: true), 8.height, if (requestsVM.isFetchingRequestType) ...[ const Center( diff --git a/lib/views/requests/request_bottomsheets.dart b/lib/views/requests/request_bottomsheets.dart new file mode 100644 index 0000000..f6a4276 --- /dev/null +++ b/lib/views/requests/request_bottomsheets.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.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/generated/locale_keys.g.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/view_models/requests_view_model.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; + +Future buildSendOfferBottomSheet(BuildContext context, RequestDetailPageArguments requestDetailPageArguments) { + final requestDetail = requestDetailPageArguments.requestModel; + return showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { + return InfoBottomSheet( + title: LocaleKeys.makeAnOffer.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), + description: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 12.height, + TxtField( + value: requestsVM.offerPrice, + errorValue: requestsVM.offerPriceError, + keyboardType: TextInputType.number, + hint: LocaleKeys.enterAmount.tr(), + numbersOnly: true, + onChanged: (v) => requestsVM.updateOfferPrice(v), + ), + if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeStatusEnum()) ...[ + 12.height, + TxtField( + value: requestsVM.serviceItem, + errorValue: requestsVM.offerPriceError, + keyboardType: TextInputType.number, + hint: "Service Item", + onChanged: (v) => requestsVM.updateServiceItem(v), + ), + 12.height, + TxtField( + value: requestsVM.itemManufacturer, + errorValue: requestsVM.offerPriceError, + keyboardType: TextInputType.number, + hint: "Manufacturer", + onChanged: (v) => requestsVM.updateItemManufacturer(v), + ), + 12.height, + TxtField( + errorValue: "", + hint: "Manufactured On", + value: requestsVM.serviceItemCreatedOn, + isNeedClickAll: true, + postfixData: Icons.calendar_month_rounded, + postFixDataColor: MyColors.darkTextColor, + onTap: () async { + final formattedDate = await Utils.pickDateFromDatePicker(context, firstDate: DateTime(2020), lastDate: DateTime.now()); + requestsVM.updateServiceItemCreatedOn(formattedDate); + }, + ), + ], + 12.height, + TxtField( + maxLines: 5, + value: requestsVM.offerDescription, + errorValue: requestsVM.offerDescriptionError, + keyboardType: TextInputType.text, + hint: LocaleKeys.description.tr(), + onChanged: (v) => requestsVM.updateOfferDescription(v), + ), + ], + ), + 25.height, + ShowFillButton( + title: LocaleKeys.submit.tr(), + maxHeight: 55, + onPressed: () { + requestsVM.onSendOfferPressed( + context: context, + receiverId: requestDetail.customerID, + message: requestsVM.offerDescription, + requestId: requestDetail.id, + offerPrice: requestsVM.offerPrice, + requestModel: requestDetail, + requestIndex: requestDetailPageArguments.requestIndex, + isFromChatScreen: false, + ); + }, + maxWidth: double.infinity, + ), + 19.height, + ], + ), + )); + }); + }, + ); +} diff --git a/lib/views/requests/widget/request_item.dart b/lib/views/requests/widget/request_item.dart index dc2e056..0d7847f 100644 --- a/lib/views/requests/widget/request_item.dart +++ b/lib/views/requests/widget/request_item.dart @@ -2,6 +2,7 @@ import 'dart:developer'; +import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart'; @@ -121,14 +122,11 @@ class RequestItem extends StatelessWidget { Widget showItem(String title, String value) { return Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - title.toText( - color: MyColors.lightTextColor, - ), - 2.width, - value.toText( - isBold: true, - ), + title.toText(color: MyColors.lightTextColor), + 3.width, + Flexible(child: value.toText(isBold: true, overflow: TextOverflow.ellipsis )), ], ); } diff --git a/lib/widgets/extensions/extensions_widget.dart b/lib/widgets/extensions/extensions_widget.dart index afbacea..b511d62 100644 --- a/lib/widgets/extensions/extensions_widget.dart +++ b/lib/widgets/extensions/extensions_widget.dart @@ -359,14 +359,18 @@ extension BuildSVG on String? { errorBuilder: (BuildContext context, Object obj, StackTrace? s) { return SizedBox(height: height, width: width, child: const Icon(Icons.signal_wifi_connected_no_internet_4_outlined)); }, - loadingBuilder: (BuildContext context, Widget? child, ImageChunkEvent? imageChunk) { - return const Center( - child: CircularProgressIndicator( - strokeWidth: 0.5, - color: MyColors.darkPrimaryColor, - ), - ); - }, + // loadingBuilder: (BuildContext context, Widget? child, ImageChunkEvent? imageChunk) { + // return SizedBox( + // height: height, + // width: width, + // child: const Center( + // child: CircularProgressIndicator( + // strokeWidth: 0.7, + // color: MyColors.darkPrimaryColor, + // ), + // ).paddingAll(10), + // ); + // }, fit: fit, color: color, height: height, diff --git a/pubspec.yaml b/pubspec.yaml index 4a5f47b..1d982a6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,7 +59,6 @@ dependencies: # Auth - local_auth: ^2.2.0 huawei_fido: ^6.3.0+305 device_info_plus: ^10.1.0