diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index eebb711..ebb9831 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -74,10 +74,7 @@ class ApiClientImp implements ApiClient { if (headers != null && headers.isNotEmpty) { headers0.addAll(headers); } - if (!kReleaseMode) { - logger.i(url); - logger.i(jsonEncode(jsonObject.toString())); - } + var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: headers0, retryTimes: retryTimes); try { if (!kReleaseMode) { @@ -129,14 +126,16 @@ class ApiClientImp implements ApiClient { var queryString = Uri(queryParameters: queryParameters).query; url = '$url?$queryString'; } - Response response; response = await _post(Uri.parse(url), body: requestBody, headers: headers0).timeout(const Duration(seconds: 100)); if (!kReleaseMode) { + logger.d("------URL------"); logger.i(url); - logger.i(requestBody); + logger.d("------Payload------"); + logger.i(jsonDecode(requestBody)); + logger.d("------Response------"); logger.i(jsonDecode(response.body)); } if (response.statusCode >= 200 && response.statusCode < 500) { diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index bbb2e66..b5ea4a0 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -104,6 +104,7 @@ class ApiConsts { static String vehicleAdsDurationGet = "${baseUrlServices}api/Advertisement/AdsDuration_Get"; static String vehicleAdsSpecialServicesGet = "${baseUrlServices}api/Common/SpecialService_Get"; static String vehicleAdsSingleStepCreate = "${baseUrlServices}api/Advertisement/AdsSingleStep_Create"; + static String vehicleAdsSingleStepUpdate = "${baseUrlServices}api/Advertisement/AdsSingleStep_Update"; static String vehicleAdsGet = "${baseUrlServices}api/Advertisement/Ads_Get"; static String myAdsReserveGet = "${baseUrlServices}api/Advertisement/AdsReserve_Get"; static String reserveAdsBankDetailsGet = "${baseUrlServices}api/Advertisement/MCBankAccountAd_Get"; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 2740da4..9d007bd 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -5,18 +5,19 @@ import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; extension EmailValidator on String { - Widget toText({Color? color, - bool isBold = false, - double? fontSize, - bool isUnderLine = false, - bool isItalic = false, - TextDecoration? textDecoration, - double letterSpacing = -0.4, - TextAlign? textAlign, - FontWeight? fontWeight, - double? height, - Color? decorationColor, - int? maxLines}) => + Widget toText( + {Color? color, + bool isBold = false, + double? fontSize, + bool isUnderLine = false, + bool isItalic = false, + TextDecoration? textDecoration, + double letterSpacing = -0.4, + TextAlign? textAlign, + FontWeight? fontWeight, + double? height, + Color? decorationColor, + int? maxLines}) => AutoSizeText( this, textAlign: textAlign, @@ -24,10 +25,8 @@ extension EmailValidator on String { style: TextStyle( fontStyle: isItalic ? FontStyle.italic : null, height: height, - decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? - TextDecoration.none, - decorationColor - : decorationColor, + decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none, + decorationColor: decorationColor, fontSize: fontSize ?? 10, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600, color: color ?? MyColors.darkTextColor, @@ -36,9 +35,7 @@ extension EmailValidator on String { ); bool isValidEmail() { - return RegExp( - r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$') - .hasMatch(this); + return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this); } bool isNum() { @@ -146,9 +143,7 @@ extension FormatDate on String { String date = split("T")[0]; String time = split("T")[1]; var dates = date.split("-"); - return "${dates[2]} ${getMonth( - int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a', "en_US") - .format(DateFormat('hh:mm:ss', "en_US").parse(time))}"; + return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a', "en_US").format(DateFormat('hh:mm:ss', "en_US").parse(time))}"; } String toFormattedDateWithoutTime() { @@ -809,5 +804,3 @@ extension SubscriptionTypeEnumToString on SubscriptionTypeEnum { } } } - - diff --git a/lib/models/advertisment_models/ad_details_model.dart b/lib/models/advertisment_models/ad_details_model.dart index dc0c4d6..322a226 100644 --- a/lib/models/advertisment_models/ad_details_model.dart +++ b/lib/models/advertisment_models/ad_details_model.dart @@ -260,13 +260,15 @@ class Category { class Condition { int? id; + int? vehicleBrandID; String? label; String? labelN; - Condition({this.id, this.label, this.labelN}); + Condition({this.id, this.label, this.labelN, this.vehicleBrandID}); Condition.fromJson(Map json) { id = json['id']; + vehicleBrandID = json['vehicleBrandID']; label = json['label']; labelN = json['labelN']; } diff --git a/lib/models/advertisment_models/vehicle_details_models.dart b/lib/models/advertisment_models/vehicle_details_models.dart index bcbd8ba..5728ae9 100644 --- a/lib/models/advertisment_models/vehicle_details_models.dart +++ b/lib/models/advertisment_models/vehicle_details_models.dart @@ -33,7 +33,6 @@ class VehicleDetailsModel { }); VehicleDetailsModel.fromJson(Map json) { - log("jsonJee: $json"); vehicleBrands = List.generate((json['vehiclebrands']['data']).length, (index) => VehicleBrandsModel.fromJson(json['vehiclebrands']['data'][index])); vehicleCategories = List.generate((json['vehiclecategories']['data']).length, (index) => VehicleCategoryModel.fromJson(json['vehiclecategories']['data'][index])); vehicleColors = List.generate((json['vehiclecolors']['data']).length, (index) => VehicleColorModel.fromJson(json['vehiclecolors']['data'][index])); @@ -69,7 +68,6 @@ class VehicleTypeModel { this.isActive, this.vehicleTypeEnum = VehicleType.car, this.isSelected, - }); VehicleTypeModel.fromJson(Map json) { diff --git a/lib/models/general_models/generic_resp_model.dart b/lib/models/general_models/generic_resp_model.dart index 88b7755..e98c664 100644 --- a/lib/models/general_models/generic_resp_model.dart +++ b/lib/models/general_models/generic_resp_model.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + class GenericRespModel { GenericRespModel({ this.data, @@ -219,16 +221,18 @@ class VehiclePosting { class VehiclePostingImages { int? id; + File? file; String? imageName; String? imageUrl; String? imageStr; int? vehiclePostingID; String? vehiclePosting; - VehiclePostingImages({this.id, this.imageName, this.imageUrl, this.imageStr, this.vehiclePostingID, this.vehiclePosting}); + VehiclePostingImages({this.id, this.file, this.imageName, this.imageUrl, this.imageStr, this.vehiclePostingID, this.vehiclePosting}); VehiclePostingImages.fromJson(Map json) { id = json['id']; + file = null; imageName = json['imageName']; imageUrl = json['imageUrl']; imageStr = json['imageStr']; @@ -249,7 +253,7 @@ class VehiclePostingImages { @override String toString() { - return 'VehiclePostingImages{id: $id, imageName: $imageName, imageUrl: $imageUrl, imageStr: $imageStr, vehiclePostingID: $vehiclePostingID, vehiclePosting: $vehiclePosting}'; + return 'VehiclePostingImages{id: $id, imageName: $imageName, imageUrl: $imageUrl, imageStr: "", vehiclePostingID: $vehiclePostingID, vehiclePosting: $vehiclePosting}'; } } @@ -282,17 +286,21 @@ class RequestPostingImages { class VehiclePostingDamageParts { int? id; + File? file; String? comment; + String? imageUrl; String? vehicleImageBase64; int? vehicleDamagePartID; int? vehiclePostingID; bool? isActive; - VehiclePostingDamageParts({this.id, this.comment, this.vehicleImageBase64, this.vehicleDamagePartID, this.vehiclePostingID, this.isActive}); + VehiclePostingDamageParts({this.id, this.file, this.comment, this.imageUrl, this.vehicleImageBase64, this.vehicleDamagePartID, this.vehiclePostingID, this.isActive}); VehiclePostingDamageParts.fromJson(Map json) { id = json['id']; + file = null; comment = json['comment']; + imageUrl = json['imageUrl']; vehicleImageBase64 = json['vehicleImageBase64']; vehicleDamagePartID = json['vehicleDamagePartID']; vehiclePostingID = json['vehiclePostingID']; @@ -303,6 +311,7 @@ class VehiclePostingDamageParts { final Map data = {}; data['id'] = id; data['comment'] = comment; + data['imageUrl'] = imageUrl; data['vehicleImageBase64'] = vehicleImageBase64; data['vehicleDamagePartID'] = vehicleDamagePartID; data['vehiclePostingID'] = vehiclePostingID; @@ -310,8 +319,8 @@ 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}'; +} } diff --git a/lib/repositories/ads_repo.dart b/lib/repositories/ads_repo.dart index 85b9775..0c8aa8e 100644 --- a/lib/repositories/ads_repo.dart +++ b/lib/repositories/ads_repo.dart @@ -22,7 +22,7 @@ abstract class AdsRepo { Future> getSpecialServices({required int specialServiceId}); - Future createNewAd({required AdsCreationPayloadModel adsCreationPayloadModel}); + Future createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew}); Future> getAllAds({required bool isMyAds}); @@ -72,15 +72,15 @@ class AdsRepoImp implements AdsRepo { } @override - Future createNewAd({required AdsCreationPayloadModel adsCreationPayloadModel}) async { + Future createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew}) async { List vehiclePostingImages = []; adsCreationPayloadModel.vehiclePosting!.vehiclePostingImages?.forEach((element) { var imageMap = { - "id": 0, + "id": element.id ?? 0, "imageName": element.imageName, "imageUrl": element.imageUrl, "imageStr": element.imageStr, - "vehiclePostingID": 0, + "vehiclePostingID": element.vehiclePostingID ?? 0, "vehiclePosting": null, }; vehiclePostingImages.add(imageMap); @@ -89,18 +89,18 @@ class AdsRepoImp implements AdsRepo { List vehiclePostingDamageParts = []; adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts?.forEach((element) { var imageMap = { - "id": 0, + "id": element.id ?? 0, "comment": element.comment, "vehicleImageBase64": element.vehicleImageBase64, "vehicleDamagePartID": element.vehicleDamagePartID, - "vehiclePostingID": 0, + "vehiclePostingID": element.vehiclePostingID ?? 0, "isActive": true }; vehiclePostingDamageParts.add(imageMap); }); var postParams = { "ads": { - "id": 0, + "id": adsCreationPayloadModel.ads!.id ?? 0, "adsDurationID": adsCreationPayloadModel.ads!.adsDurationID, "startDate": adsCreationPayloadModel.ads!.startDate, "countryId": adsCreationPayloadModel.ads!.countryId, @@ -108,7 +108,7 @@ class AdsRepoImp implements AdsRepo { "isMCHandled": false }, "vehiclePosting": { - "id": 0, + "id": adsCreationPayloadModel.vehiclePosting!.id ?? 0, "userID": adsCreationPayloadModel.vehiclePosting!.userID, "vehicleType": adsCreationPayloadModel.vehiclePosting!.vehicleType, "vehicleModelID": adsCreationPayloadModel.vehiclePosting!.vehicleModelID, @@ -134,11 +134,10 @@ class AdsRepoImp implements AdsRepo { } }; - logger.i(jsonEncode(postParams.toString())); String token = appState.getUser.data!.accessToken ?? ""; GenericRespModel adsGenericModel = await apiClient.postJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleAdsSingleStepCreate, + isCreateNew ? ApiConsts.vehicleAdsSingleStepCreate : ApiConsts.vehicleAdsSingleStepUpdate, postParams, token: token, ); diff --git a/lib/repositories/chat_repo.dart b/lib/repositories/chat_repo.dart index 0e7f442..42e64b6 100644 --- a/lib/repositories/chat_repo.dart +++ b/lib/repositories/chat_repo.dart @@ -31,14 +31,11 @@ class ChatRepoImp implements ChatRepo { HubConnection hub; hub = HubConnectionBuilder() .withUrl( - hubUrl, - HttpConnectionOptions( - client: IOClient(HttpClient() - ..badCertificateCallback = (x, y, z) => true), - logging: (level, message) { - log(message); - }, - )) + hubUrl, + HttpConnectionOptions( + client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true), + logging: (level, message) {}, + )) .build(); return hub; } @@ -49,7 +46,7 @@ class ChatRepoImp implements ChatRepo { "id": messageId.toString(), }; await apiClient.postJsonForObject( - (json) => GenericRespModel.fromJson(json), + (json) => GenericRespModel.fromJson(json), ApiConsts.messageIsReadUpdate, queryParameters, token: appState.getUser.data!.accessToken, @@ -68,7 +65,7 @@ class ChatRepoImp implements ChatRepo { "PageIndex": pageIndex.toString(), }; GenericRespModel genericRespModel = await apiClient.getJsonForObject( - (json) => GenericRespModel.fromJson(json), + (json) => GenericRespModel.fromJson(json), ApiConsts.getChatMessages, queryParameters: queryParameters, token: appState.getUser.data!.accessToken, @@ -76,7 +73,7 @@ class ChatRepoImp implements ChatRepo { if (genericRespModel.messageStatus == 1 && genericRespModel.data != null) { List chatMessages = List.generate( genericRespModel.data.length, - (index) => ChatMessageModel.fromJson(genericRespModel.data[index]), + (index) => ChatMessageModel.fromJson(genericRespModel.data[index]), ); return chatMessages; } diff --git a/lib/utils/date_helper.dart b/lib/utils/date_helper.dart index b41653c..e9cd7ab 100644 --- a/lib/utils/date_helper.dart +++ b/lib/utils/date_helper.dart @@ -1,6 +1,10 @@ import 'package:intl/intl.dart'; class DateHelper { + static String formatDateT(String dateString) { + return dateString.split('T')[0]; + } + static DateTime parseStringToDate(String dateString) { final formatter = DateFormat('yyyy-MM-dd'); return formatter.parse(dateString); diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index 7973bad..af8f5ee 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -21,6 +21,7 @@ import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/repositories/ads_repo.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/date_helper.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'; @@ -71,7 +72,8 @@ class AdVM extends BaseVM { String adPhoneNumberError = ""; // Edit Variables Amir - bool isAdEdit = false; + bool isAdEditEnabled = false; + AdDetailsModel? previousAdDetails; List exploreAds = []; List exploreAdsFilteredList = []; @@ -385,18 +387,22 @@ class AdVM extends BaseVM { // notifyListeners(); // } - getVehicleBrandsByVehicleTypeId() async { - if (vehicleTypeId.selectedId == -1 || vehicleBrands.isNotEmpty) { - return; - } - vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: vehicleTypeId.selectedId); + Future getVehicleBrandsByVehicleTypeId({int vehicleIdForEditAd = -1}) async { + // if (vehicleTypeId.selectedId == -1 || vehicleBrands.isNotEmpty) { + // return; + // } + isFetchingLists = true; + notifyListeners(); + + vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: vehicleIdForEditAd != -1 ? vehicleIdForEditAd : vehicleTypeId.selectedId); + isFetchingLists = false; notifyListeners(); } Future getVehicleDetailsByVehicleBrandId() async { - if (vehicleBrandId.selectedId == -1 || vehicleTypeId.selectedId == -1) { - return; - } + // if (vehicleBrandId.selectedId == -1 || vehicleTypeId.selectedId == -1) { + // return; + // } isFetchingLists = true; notifyListeners(); vehicleDetails = await commonRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId, vehicleBrandId: vehicleBrandId.selectedId); @@ -461,13 +467,13 @@ class AdVM extends BaseVM { void updateSelectionVehicleTypeId(SelectionModel id) async { vehicleTypeId = id; - getVehicleBrandsByVehicleTypeId(); + await getVehicleBrandsByVehicleTypeId(); notifyListeners(); } SelectionModel vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - void updateSelectionVehicleBrandId(SelectionModel id, {bool isForSearch = false}) { + Future updateSelectionVehicleBrandId(SelectionModel id, {bool isForSearch = false}) async { if (isForSearch) { VehicleBrandsModel brand = vehicleBrands.firstWhere((element) => element.id == id.selectedId); DropValue brandValue = DropValue(brand.id ?? 0, brand.vehicleBrandDescription ?? "", ""); @@ -478,7 +484,8 @@ class AdVM extends BaseVM { return; } vehicleBrandId = id; - getVehicleDetailsByVehicleBrandId(); + logger.i("message: ${vehicleBrandId.selectedOption}"); + await getVehicleDetailsByVehicleBrandId(); notifyListeners(); } @@ -881,7 +888,7 @@ class AdVM extends BaseVM { } else { vehicleDescError = ""; } - if (pickedVehicleImages.isEmpty || pickedVehicleImages.length < 3) { + if ((pickedPostingImages.isEmpty || pickedPostingImages.length < 3) && !isAdEditEnabled) { vehicleImageError = GlobalConsts.attachImageError; isValidated = false; } else { @@ -1010,8 +1017,14 @@ class AdVM extends BaseVM { case AdCreationSteps.damageParts: if (isDamagePartsValidated()) { currentProgressStep = AdCreationSteps.adDuration; - getVehicleAdsDuration(); - getVehicleAdsSpecialServices(); + if (vehicleAdsDurations.isEmpty) { + getVehicleAdsDuration(); + } + + if (vehicleAdsSpecialServices.isEmpty) { + getVehicleAdsSpecialServices(); + } + notifyListeners(); } break; @@ -1029,6 +1042,7 @@ class AdVM extends BaseVM { Utils.hideLoading(context); return; } + isAdEditEnabled = false; Utils.hideLoading(context); currentProgressStep = AdCreationSteps.vehicleDetails; resetValues(); @@ -1065,30 +1079,35 @@ class AdVM extends BaseVM { notifyListeners(); } - List pickedVehicleImages = []; + List pickedPostingImages = []; void removeImageFromList(String filePath) { - int index = pickedVehicleImages.indexWhere((element) => element.path == filePath); + int index = pickedPostingImages.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } - pickedVehicleImages.removeAt(index); + pickedPostingImages.removeAt(index); notifyListeners(); } void pickMultipleImages() async { + List imageModels = []; List images = await commonServices.pickMultipleImages(); - pickedVehicleImages.addAll(images); - if (pickedVehicleImages.isNotEmpty) vehicleImageError = ""; + + for (var element in images) { + imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); + } + pickedPostingImages.addAll(imageModels); + if (pickedPostingImages.isNotEmpty) vehicleImageError = ""; notifyListeners(); } - List pickedReceiptPdfFiles = []; + List pickedReceiptPdfFiles = []; String receiptPdfFileError = ""; void removePdfFileFromList(String filePath) { - int index = pickedReceiptPdfFiles.indexWhere((element) => element.path == filePath); + int index = pickedReceiptPdfFiles.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } @@ -1097,8 +1116,13 @@ class AdVM extends BaseVM { } void pickPdfReceiptFile(BuildContext context) async { + List imageModels = []; List? files = await commonServices.pickMultipleFiles(context); - pickedReceiptPdfFiles.addAll(files!); + if (files == null) return; + for (var element in files) { + imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); + } + pickedReceiptPdfFiles.addAll(imageModels); if (pickedReceiptPdfFiles.isNotEmpty) receiptPdfFileError = ""; notifyListeners(); } @@ -1106,13 +1130,16 @@ class AdVM extends BaseVM { // sourceFlag for Camera = 0 // sourceFlag for Gallery = 1 void pickDamagePartImage(int index) async { + List imageModels = []; List images = await commonServices.pickMultipleImages(); - + for (var element in images) { + imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); + } if (images.isNotEmpty) { if (vehicleDamageCards[index].partImages == null) { - vehicleDamageCards[index].partImages = images; + vehicleDamageCards[index].partImages = imageModels; } else { - vehicleDamageCards[index].partImages!.addAll(images); + vehicleDamageCards[index].partImages!.addAll(imageModels); } vehicleDamageCards[index].partImageErrorValue = ""; notifyListeners(); @@ -1147,7 +1174,7 @@ class AdVM extends BaseVM { void removeDamageImageFromCard(int imageIndex, String filePath, int cardIndex) { VehicleDamageCard card = vehicleDamageCards.elementAt(cardIndex); if (card.partImages == null) return; - int index = card.partImages!.indexWhere((element) => element.path == filePath); + int index = card.partImages!.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } @@ -1164,9 +1191,10 @@ class AdVM extends BaseVM { void resetValues() { pickedDamageImages.clear(); - pickedVehicleImages.clear(); + pickedPostingImages.clear(); vehicleDamageCards.clear(); specialServiceCards.clear(); + vehicleAdsSpecialServices.clear(); currentProgressStep = AdCreationSteps.vehicleDetails; vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); @@ -1181,14 +1209,13 @@ class AdVM extends BaseVM { vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - vehicleDemandAmount = ""; vehicleVin = ""; vehicleTitle = ""; warrantyDuration = ""; vehicleDescription = ""; selectionDurationStartDate = ""; - + clearSpecialServiceCard(); updateFinanceAvailableStatus(false); notifyListeners(); } @@ -1327,6 +1354,7 @@ class AdVM extends BaseVM { adsSelectedServices.add(value.serviceSelectedId!.selectedId); } Ads ads = Ads( + id: isAdEditEnabled ? previousAdDetails!.id : null, adsDurationID: vehicleAdDurationId.selectedId, startDate: selectionDurationStartDate, countryId: vehicleCountryId.selectedId, @@ -1334,8 +1362,8 @@ class AdVM extends BaseVM { ); List vehicleImages = []; - for (var element in pickedVehicleImages) { - vehicleImages.add(await convertFileToVehiclePostingImages(file: element)); + for (var image in pickedPostingImages) { + vehicleImages.add(await convertFileToVehiclePostingImages(imageModel: image)); } List vehicleDamageImages = []; @@ -1344,7 +1372,7 @@ class AdVM extends BaseVM { if (card.partImages != null && card.partImages!.isNotEmpty) { for (var image in card.partImages!) { VehiclePostingDamageParts stringImage = await convertFileToVehiclePostingDamageParts( - file: image, + imageModel: image, damagePartId: card.partSelectedId!.selectedId, ); vehicleDamageImages.add(stringImage); @@ -1353,6 +1381,7 @@ class AdVM extends BaseVM { } VehiclePosting vehiclePosting = VehiclePosting( + id: isAdEditEnabled ? previousAdDetails!.vehiclePostingID : null, userID: appState.getUser.data!.userInfo!.userId, vehicleType: vehicleTypeId.selectedId, vehicleModelID: vehicleModelId.selectedId, @@ -1379,32 +1408,57 @@ class AdVM extends BaseVM { ); AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting); - GenericRespModel respModel = await adsRepo.createNewAd(adsCreationPayloadModel: adsCreationPayloadModel); + GenericRespModel respModel = await adsRepo.createOrUpdateAd(adsCreationPayloadModel: adsCreationPayloadModel, isCreateNew: !isAdEditEnabled); Utils.showToast(respModel.message.toString()); return Future.value(respModel.messageStatus); } - Future convertFileToVehiclePostingImages({required File file}) async { - List imageBytes = await file.readAsBytes(); - String image = base64Encode(imageBytes); - String fileName = file.path.split('/').last; - VehiclePostingImages vehiclePostingImages = VehiclePostingImages( - imageName: fileName, - imageStr: image, - imageUrl: file.path, - ); + Future convertFileToVehiclePostingImages({required ImageModel imageModel}) async { + VehiclePostingImages vehiclePostingImages; + if (imageModel.isFromNetwork ?? false) { + vehiclePostingImages = VehiclePostingImages( + id: imageModel.id, + imageUrl: imageModel.filePath, + ); + } else { + File file = File(imageModel.filePath!); + List imageBytes = await file.readAsBytes(); + String image = base64Encode(imageBytes); + String fileName = file.path.split('/').last; + vehiclePostingImages = VehiclePostingImages( + imageName: fileName, + imageStr: image, + imageUrl: file.path, + vehiclePostingID: isAdEditEnabled ? previousAdDetails!.vehiclePostingID : null, + ); + } + return vehiclePostingImages; } - Future convertFileToVehiclePostingDamageParts({required File file, required int damagePartId}) async { - List imageBytes = await file.readAsBytes(); - String image = base64Encode(imageBytes); - VehiclePostingDamageParts vehiclePostingDamageParts = VehiclePostingDamageParts( - vehicleImageBase64: image, - vehicleDamagePartID: damagePartId, - ); + Future convertFileToVehiclePostingDamageParts({required ImageModel imageModel, required int damagePartId}) async { + VehiclePostingDamageParts vehiclePostingDamageParts; + + if (imageModel.isFromNetwork ?? false) { + vehiclePostingDamageParts = VehiclePostingDamageParts( + id: imageModel.id, + vehicleDamagePartID: damagePartId, + imageUrl: imageModel.filePath, + vehiclePostingID: isAdEditEnabled ? previousAdDetails!.vehiclePostingID : null, + ); + } else { + File file = File(imageModel.filePath!); + List imageBytes = await file.readAsBytes(); + String image = base64Encode(imageBytes); + vehiclePostingDamageParts = VehiclePostingDamageParts( + vehicleImageBase64: image, + vehicleDamagePartID: damagePartId, + imageUrl: file.path, + ); + } + return vehiclePostingDamageParts; } @@ -1600,25 +1654,21 @@ class AdVM extends BaseVM { ///// Edit Work Amir - void editUpdateAd(BuildContext context, AdDetailsModel previousDetails) { - isAdEdit = true; + void onEditUpdateAdPressed(BuildContext context, AdDetailsModel previousDetails) { + isAdEditEnabled = true; + previousAdDetails = previousDetails; + autoFillSelectedVehicleType(); navigateWithName(context, AppRoutes.selectAdTypeView, arguments: AppState().currentAppType == AppType.provider ? true : false); - checkVehicleStep1(previousDetails); - checkVehicleStep2(previousDetails); - } - void clearEditValues() { - isAdEdit = false; - if (vehicleTypes.isNotEmpty) vehicleTypes.unselectAll(); - if (vehicleAdsDurations.isNotEmpty) vehicleAdsDurations.unselectAll(); - } - - checkVehicleStep1(AdDetailsModel previousDetails) { - logger.d("Step 1"); + autoFillSelectedVehicleType() async { + if (vehicleTypes.isEmpty) { + await getVehicleTypes(); + return; + } if (vehicleTypes.isNotEmpty) { for (var vehicle in vehicleTypes) { - if (vehicle.id == previousDetails.vehicle?.vehicleType) { + if (vehicle.id == previousAdDetails!.vehicle?.vehicleType) { vehicle.isSelected = true; break; } @@ -1627,55 +1677,137 @@ class AdVM extends BaseVM { notifyListeners(); } - checkVehicleStep2(AdDetailsModel previousDetails) { - logger.d("Step 2"); + autoFillSelectedVehicleAdsDuration() async { + if (vehicleAdsDurations.isEmpty) { + await getVehicleAdsDuration(); + } if (vehicleAdsDurations.isNotEmpty) { - for (var adsDuration in vehicleAdsDurations) { - if (adsDuration.price == previousDetails.adsDurationPrice) { - adsDuration.isSelected = true; - break; - } + int index = vehicleAdsDurations.indexWhere((element) => element.price == previousAdDetails!.adsDurationPrice!); + if (index != -1) { + updateVehicleAdDurationId( + SelectionModel( + selectedId: vehicleAdsDurations[index].id ?? 0, + selectedOption: "${vehicleAdsDurations[index].days} Days", + itemPrice: vehicleAdsDurations[index].price!.toInt().toString(), + ), + ); } } notifyListeners(); } - checkVehicleStep3(AdDetailsModel previousDetails) { - logger.d("Step 3"); - if (vehicleBrands.isNotEmpty) { - for (var vBrands in vehicleBrands) { - if (vBrands.id == previousDetails.vehicle.) { - // BrandsId need to be matched here. - vBrands.isSelected = true; - break; - } - } + + List vehicleOldDamageImagesList = []; + + void removeVehicleOldDamageImagesList(String imageUrl) { + int index = vehicleOldDamageImagesList.indexWhere((element) => element.imageUrl == imageUrl); + if (index == -1) { + return; } + vehicleOldDamageImagesList.removeAt(index); notifyListeners(); } - updateValues() { - if (isAdEdit) { - if (vehicleTypes.isNotEmpty) vehicleTypes.unselectAll(); - if (vehicleAdsDurations.isNotEmpty) vehicleAdsDurations.unselectAll(); - notifyListeners(); + autoFillSelectedVehicleAdsDetails() async { + int index = vehicleBrands.indexWhere((element) => element.id == previousAdDetails!.vehicle!.model!.vehicleBrandID); + if (index != -1) { + await updateSelectionVehicleBrandId(SelectionModel(selectedId: vehicleBrands[index].id!, selectedOption: vehicleBrands[index].vehicleBrandDescription ?? "")); + } + + updateSelectionVehicleModelId(SelectionModel(selectedId: previousAdDetails!.vehicle!.model!.id!, selectedOption: previousAdDetails!.vehicle!.model!.label ?? "")); + updateSelectionVehicleModelYearId(SelectionModel(selectedId: previousAdDetails!.vehicle!.modelyear!.id!, selectedOption: previousAdDetails!.vehicle!.modelyear!.label ?? "")); + updateSelectionVehicleColorId(SelectionModel(selectedId: previousAdDetails!.vehicle!.color!.id!, selectedOption: previousAdDetails!.vehicle!.color!.label ?? "")); + updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.label ?? "")); + updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? "")); + updateSelectionVehicleMileageId(SelectionModel( + selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}")); + updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? "")); + updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? "")); + int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID); + if (indexCountry != -1) { + updateSelectionVehicleCountryId(SelectionModel(selectedId: vehicleCountries[index].id!, selectedOption: vehicleCountries[index].countryName ?? "")); + } + + updateSelectionVehicleCityId(SelectionModel(selectedId: previousAdDetails!.vehicle!.cityID!, selectedOption: previousAdDetails!.vehicle!.cityName ?? "")); + vehicleDemandAmount = previousAdDetails!.vehicle!.demandAmount!.toInt().toString(); + vehicleVin = previousAdDetails!.vehicle!.vehicleVIN.toString(); + vehicleTitle = previousAdDetails!.vehicle!.vehicleTitle.toString(); + vehicleDescription = previousAdDetails!.vehicle!.vehicleDescription.toString(); + financeAvailableStatus = previousAdDetails!.vehicle!.isFinanceAvailable ?? false; + + if (previousAdDetails!.vehicle!.image != null && previousAdDetails!.vehicle!.image!.isNotEmpty) { + for (var element in previousAdDetails!.vehicle!.image!) { + if (element.imageUrl != null) { + ImageModel imageModel = ImageModel(id: element.id, filePath: element.imageUrl, isFromNetwork: true); + pickedPostingImages.add(imageModel); + } + } } - } -} -extension ToggleSelected on List { - void unselectAll() { - for (var element in this) { - if (element.isSelected!) { - element.isSelected = false; + if (previousAdDetails!.vehicle!.damagereport != null && previousAdDetails!.vehicle!.damagereport!.isNotEmpty) { + for (var element in previousAdDetails!.vehicle!.damagereport!) { + int index = -1; + if (vehicleDamageCards.isNotEmpty) { + index = ifDamagePartAlreadyThere(element.vehicleDamagePartID!); + ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); + vehicleDamageCards[index].partImages!.add(imageModel); + } else { + ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); + + VehicleDamageCard vehicleDamageCard = VehicleDamageCard( + partSelectedId: SelectionModel( + selectedId: element.vehicleDamagePartID!, + selectedOption: element.partName ?? "", + ), + partImages: [imageModel], + ); + addNewDamagePartCard(damageCard: vehicleDamageCard); + } } } + + if (previousAdDetails!.specialservice != null && previousAdDetails!.specialservice!.isNotEmpty) { + for (var element in previousAdDetails!.specialservice!) { + SelectionModel vehicleAdsSpecialServicesId = SelectionModel(selectedId: element.specialServiceID!, selectedOption: element.name ?? "", itemPrice: element.price.toString()); + SpecialServiceCard specialServiceCard = SpecialServiceCard( + serviceSelectedId: vehicleAdsSpecialServicesId, + description: element.description ?? "", + duration: "", + serviceDate: "", + serviceDateError: "", + serviceTimeError: "", + address: "", + serviceTime: "", + ); + addNewSpecialServiceCard(specialServiceCard: specialServiceCard); + } + } + + selectionDurationStartDate = DateHelper.formatDateT(previousAdDetails!.startdate ?? ""); + isPhoneNumberShown = previousAdDetails!.phoneNo != null; + if (isPhoneNumberShown) { + adPhoneNumber = previousAdDetails!.phoneNo ?? ""; + adPhoneNumberDialCode = "+966"; + } + + isNumberOnWhatsApp = previousAdDetails!.whatsAppNo != null; + logger.i("previousAdDetails!: $previousAdDetails"); + + notifyListeners(); + } + + int ifDamagePartAlreadyThere(int partId) { + return vehicleDamageCards.indexWhere((element) => element.partSelectedId!.selectedId == partId); + } + + int ifSpecialServiceAlreadyThere(int id) { + return specialServiceCards.indexWhere((element) => element.serviceSelectedId!.selectedId == id); } } // Edit Work End Amir class VehicleDamageCard { - List? partImages; + List? partImages; SelectionModel? partSelectedId; String partImageErrorValue; @@ -1684,6 +1816,24 @@ class VehicleDamageCard { this.partSelectedId, this.partImageErrorValue = "", }); + + @override + String toString() { + return 'VehicleDamageCard{partImages: $partImages, partSelectedId: $partSelectedId, partImageErrorValue: $partImageErrorValue}'; + } +} + +class ImageModel { + int? id; + bool? isFromNetwork; + String? filePath; + + ImageModel({this.id, this.filePath, this.isFromNetwork}); + + @override + String toString() { + return 'ImageModel{id: $id, isFromNetwork: $isFromNetwork, filePath: $filePath}'; + } } class SpecialServiceCard { diff --git a/lib/view_models/requests_view_model.dart b/lib/view_models/requests_view_model.dart index 0efe36a..2077713 100644 --- a/lib/view_models/requests_view_model.dart +++ b/lib/view_models/requests_view_model.dart @@ -21,6 +21,7 @@ import 'package:mc_common_app/services/common_services.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/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/base_view_model.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart'; import 'package:provider/provider.dart'; @@ -97,11 +98,11 @@ class RequestsVM extends BaseVM { notifyListeners(); } - List pickedVehicleImages = []; + List pickedVehicleImages = []; String vehicleImageError = ""; void removeImageFromList(String filePath) { - int index = pickedVehicleImages.indexWhere((element) => element.path == filePath); + int index = pickedVehicleImages.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } @@ -110,8 +111,12 @@ class RequestsVM extends BaseVM { } void pickMultipleImages() async { + List imageModels = []; List images = await commonServices.pickMultipleImages(); - pickedVehicleImages.addAll(images); + for (var element in images) { + imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); + } + pickedVehicleImages.addAll(imageModels); if (pickedVehicleImages.isNotEmpty) vehicleImageError = ""; notifyListeners(); } @@ -251,7 +256,7 @@ class RequestsVM extends BaseVM { log("requestImages: ${pickedVehicleImages.length}"); for (var image in pickedVehicleImages) { - var value = await convertFileToRequestPostingImages(file: image); + var value = await convertFileToRequestPostingImages(file: File(image.filePath!)); requestImages.add(value); } diff --git a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart index 9eb84bc..d3f2c84 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart @@ -110,10 +110,10 @@ class VehicleDetailsReview extends StatelessWidget { SingleDetailWidget(text: adVM.vehicleDescription, type: "Description"), 8.height, "Vehicle Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - if (adVM.pickedVehicleImages.isNotEmpty) ...[ + if (adVM.pickedPostingImages.isNotEmpty) ...[ // 10.height, PickedFilesContainer( - pickedFiles: adVM.pickedVehicleImages, + pickedFiles: adVM.pickedPostingImages, onCrossPressedPrimary: adVM.removeImageFromList, isReview: true, onAddFilePressed: () {}, diff --git a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart index a71a318..b9b3ea3 100644 --- a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart +++ b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart @@ -6,6 +6,7 @@ import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/views/advertisement/bottom_sheet_content.dart'; import 'package:mc_common_app/views/advertisement/custom_add_button.dart'; +import 'package:mc_common_app/views/advertisement/network_images_container.dart'; import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; @@ -128,6 +129,7 @@ class DamageParts extends StatelessWidget { ], ).paddingOnly(right: 10) ], + ], ).toWhiteContainer( width: double.infinity, diff --git a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart index e8c4a33..e462ecb 100644 --- a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart +++ b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart @@ -7,6 +7,7 @@ import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart'; +import 'package:mc_common_app/views/advertisement/network_images_container.dart'; import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; @@ -276,16 +277,27 @@ class VehicleDetails extends StatelessWidget { ], ).paddingOnly(right: 10) ], - if (adVM.pickedVehicleImages.isNotEmpty) ...[ + if (adVM.pickedPostingImages.isNotEmpty) ...[ 16.height, PickedFilesContainer( - pickedFiles: adVM.pickedVehicleImages, + pickedFiles: adVM.pickedPostingImages, onCrossPressedPrimary: adVM.removeImageFromList, onAddFilePressed: () { context.read().pickMultipleImages(); }, ), ], + // if (adVM.isAdEditEnabled) ...[ + // if (adVM.previousAdDetails!.vehicle!.image!.isNotEmpty) ...[ + // 16.height, + // "Old Images".toText(fontSize: 16), + // NetworkFilesContainerForVehiclePosting( + // networkFilesForVehiclePosting: adVM.vehicleOldImagesList, + // onCrossPressedPrimary: adVM.removeVehicleOldImagesList, + // onAddFilePressed: () => context.read().pickMultipleImages(), + // ), + // ], + // ], 15.height, ], ] diff --git a/lib/views/advertisement/ad_duration_selection_sheet_content.dart b/lib/views/advertisement/ad_duration_selection_sheet_content.dart index 01af7e8..8904245 100644 --- a/lib/views/advertisement/ad_duration_selection_sheet_content.dart +++ b/lib/views/advertisement/ad_duration_selection_sheet_content.dart @@ -2,6 +2,7 @@ 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/main.dart'; import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -71,13 +72,10 @@ class AdDurationSelectionSheetContent extends StatelessWidget { ), ], ).toWhiteContainer( - width: double.infinity, - allPading: 12, - isBorderRequired: adDuration.isSelected! - ? true - : adDuration.id == adVM.vehicleAdDurationId.selectedId - ? true - : false), + width: double.infinity, + allPading: 12, + isBorderRequired: adDuration.id == adVM.vehicleAdDurationId.selectedId, + ), ).onPress(() { if (isFromExtendAd) { adVM.updateVehicleExtendAdDurationId( @@ -96,7 +94,6 @@ class AdDurationSelectionSheetContent extends StatelessWidget { itemPrice: adDuration.price!.toInt().toString(), ), ); - adVM.updateValues(); }); }, separatorBuilder: (BuildContext context, int index) { @@ -106,15 +103,27 @@ class AdDurationSelectionSheetContent extends StatelessWidget { ), ), ShowFillButton( - title: "Select", + iconWidget: adVM.isFetchingLists ? const Padding( + padding: EdgeInsets.all(8.0), + child: SizedBox( + height: 30, + width: 30, + child: CircularProgressIndicator(color: Colors.white), + ), + ) : null, + title: adVM.isFetchingLists ? "" : "Select", maxWidth: double.infinity, margin: const EdgeInsets.all(21), onPressed: () { - if (isFromExtendAd && !isUpdateAdSelected) { - navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.extendAds); + if (adVM.isFetchingLists) { return; + } else { + if (isFromExtendAd && !isUpdateAdSelected) { + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.extendAds); + return; + } + navigateReplaceWithName(context, AppRoutes.createAdView); } - navigateReplaceWithName(context, AppRoutes.createAdView); }, ).toContainer(paddingAll: 0, backgroundColor: Colors.white), ], diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index b5e1b71..ca6f78b 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -21,7 +21,6 @@ import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/payment_view_model.dart'; import 'package:mc_common_app/views/advertisement/ad_duration_selection_sheet_content.dart'; import 'package:mc_common_app/views/advertisement/ads_images_slider.dart'; -import 'package:mc_common_app/views/advertisement/custom_add_button.dart'; import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; import 'package:mc_common_app/views/appointments/widgets/custom_calender_widget.dart'; import 'package:mc_common_app/widgets/bottom_sheet.dart'; @@ -33,7 +32,6 @@ 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/txt_field.dart'; import 'package:provider/provider.dart'; -import 'package:sizer/sizer.dart'; class AdsDetailView extends StatefulWidget { final AdDetailsModel adDetails; @@ -93,14 +91,8 @@ class _AdsDetailViewState extends State { ); } - void editAd() { - AdVM adVM = context.read(); - adVM.editUpdateAd(context, widget.adDetails); - } - @override Widget build(BuildContext context) { - log("ad: ${widget.adDetails.vehicle!.image!.first.imageUrl}"); return Scaffold( appBar: CustomAppBar( title: "Ads", @@ -109,16 +101,16 @@ class _AdsDetailViewState extends State { isDrawerEnabled: false, actions: [ ((widget.adDetails.isMyAd ?? false) && (widget.adDetails.adPostStatus != AdPostStatus.reserved) - ? IconButton( - icon: const Icon(Icons.delete_outline, color: MyColors.redColor), - onPressed: () { - return deleteAdBottomSheet(context); - }, - ) - : IconButton( - icon: const Icon(Icons.chat_outlined, color: Colors.black), - onPressed: () {}, - )) + ? IconButton( + icon: const Icon(Icons.delete_outline, color: MyColors.redColor), + onPressed: () { + return deleteAdBottomSheet(context); + }, + ) + : IconButton( + icon: const Icon(Icons.chat_outlined, color: Colors.black), + onPressed: () {}, + )) .toContainer( margin: const EdgeInsets.fromLTRB(0, 8, 21, 8), paddingAll: 0, @@ -149,7 +141,7 @@ class _AdsDetailViewState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( - child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label} | AdID: ${widget.adDetails.id}".toText( + child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label} | ${widget.adDetails.id}".toText( fontSize: 18, isBold: true, maxLines: 2, @@ -278,29 +270,31 @@ class _AdsDetailViewState extends State { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Rejection Comments".toText(fontSize: 18, isBold: true, color: MyColors.lightTextColor), + "Rejection Comments".toText(fontSize: 13, isBold: true, color: MyColors.lightTextColor), Row( children: [ - Icon( - Icons.edit, - size: 15, - ), + "Edit Ad".toText(fontSize: 10, isBold: true), 2.width, - "Edit Add".toText(fontSize: 10, isBold: true), + const Icon(Icons.edit, size: 15), ], - ).onPress(() { - logger.i(widget.adDetails); - editAd(); + ).onPress(() async { + Utils.showLoading(context); + await context.read().getVehicleTypes(); + await context.read().getVehicleBrandsByVehicleTypeId(vehicleIdForEditAd: widget.adDetails.vehicle!.vehicleType ?? -1); + Utils.hideLoading(context); + context.read().onEditUpdateAdPressed(context, widget.adDetails); }), ], ).paddingOnly(bottom: 5), Row( children: [ - (widget.adDetails.comment ?? "").toText( - color: MyColors.redColor, - fontSize: 12, - isItalic: true, - ), + Flexible( + child: (widget.adDetails.comment ?? "").toText( + color: MyColors.redColor, + fontSize: 12, + isItalic: true, + ), + ) ], ), ], @@ -525,36 +519,36 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { Widget defaultActionForProviderAndCustomer(BuildContext context, AdDetailsModel adDetailsModel) { return (adDetailsModel.phoneNo == null) ? Row( - children: [ - Expanded( - child: ShowFillButton( - maxHeight: 55, - title: "Contact", - fontSize: 18, - isBold: false, - iconWidget: const Padding( - padding: EdgeInsets.only(right: 10), - child: Icon(Icons.phone, color: MyColors.white, size: 24), - ), - onPressed: () { - Utils.openNumberViaCaller(phoneNumber: adDetailsModel.phoneNo ?? ""); - }, - ), - ), - if (adDetailsModel.whatsAppNo == null) ...[ - 8.width, - Container( - height: 55, - width: 55, - alignment: Alignment.center, - decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), - child: MyAssets.whatsAppIcon.buildSvg(height: 33, width: 35)) - .onPress(() { - Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? ""); - }), - ], - ], - ) + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Contact", + fontSize: 18, + isBold: false, + iconWidget: const Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.phone, color: MyColors.white, size: 24), + ), + onPressed: () { + Utils.openNumberViaCaller(phoneNumber: adDetailsModel.phoneNo ?? ""); + }, + ), + ), + if (adDetailsModel.whatsAppNo == null) ...[ + 8.width, + Container( + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + child: MyAssets.whatsAppIcon.buildSvg(height: 33, width: 35)) + .onPress(() { + Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? ""); + }), + ], + ], + ) : const SizedBox.shrink(); } @@ -598,23 +592,23 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { adVM.state == ViewState.busy ? const Center(child: CircularProgressIndicator()) : Builder( - builder: (context) { - List vehicleCitiesDrop = []; - for (int i = 0; i < adVM.photoSSSchedulesByOffices.length; i++) { - var element = adVM.photoSSSchedulesByOffices[i]; - vehicleCitiesDrop.add(DropValue(element.photoOfficeID?.toInt() ?? 0, element.photoOfficeName ?? "", i.toString())); - } + builder: (context) { + List vehicleCitiesDrop = []; + for (int i = 0; i < adVM.photoSSSchedulesByOffices.length; i++) { + var element = adVM.photoSSSchedulesByOffices[i]; + vehicleCitiesDrop.add(DropValue(element.photoOfficeID?.toInt() ?? 0, element.photoOfficeName ?? "", i.toString())); + } - return DropdownField( - (DropValue value) => adVM.updatePhotoOfficeSelectedId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), - // here the item price is the index of the selected option - list: vehicleCitiesDrop, - dropdownValue: adVM.photoOfficeSelectedId.selectedId != -1 ? DropValue(adVM.photoOfficeSelectedId.selectedId, adVM.photoOfficeSelectedId.selectedOption, "") : null, - hint: "Select Office", - errorValue: adVM.photoOfficeSelectedId.errorValue, - ); - }, - ), + return DropdownField( + (DropValue value) => adVM.updatePhotoOfficeSelectedId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), + // here the item price is the index of the selected option + list: vehicleCitiesDrop, + dropdownValue: adVM.photoOfficeSelectedId.selectedId != -1 ? DropValue(adVM.photoOfficeSelectedId.selectedId, adVM.photoOfficeSelectedId.selectedOption, "") : null, + hint: "Select Office", + errorValue: adVM.photoOfficeSelectedId.errorValue, + ); + }, + ), if (adVM.photoOfficeSelectedId.selectedId != -1) ...[ 9.height, CustomCalenderAppointmentWidget( @@ -959,7 +953,10 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { return InfoBottomSheet( title: "Cancel Reservation".toText(fontSize: 28, isBold: true, letterSpacing: -1.44), description: Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: EdgeInsets.only(bottom: MediaQuery + .of(context) + .viewInsets + .bottom), child: Consumer( builder: (BuildContext context, AdVM adVM, Widget? child) { return Column( @@ -1075,7 +1072,10 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { return InfoBottomSheet( title: "Upload Bank Receipt".toText(fontSize: 26, isBold: true, letterSpacing: -1.44), description: Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: EdgeInsets.only(bottom: MediaQuery + .of(context) + .viewInsets + .bottom), child: Consumer( builder: (BuildContext context, AdVM adVM, Widget? child) { return Column( @@ -1107,27 +1107,28 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { }, isPdf: true, ), - ] else ...[ - Row( - children: [ - Container( - height: 90, - width: 90, - decoration: BoxDecoration(color: MyColors.greyButtonColor, border: Border.all(width: 2, color: MyColors.greyAddBorderColor)), - margin: const EdgeInsets.all(8), - alignment: Alignment.center, - child: Container( - height: 24, - width: 24, - decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), - child: const Icon(Icons.add, color: MyColors.white), - ), - ).onPress(() { - context.read().pickPdfReceiptFile(context); - }), - ], - ), - ], + ] else + ...[ + Row( + children: [ + Container( + height: 90, + width: 90, + decoration: BoxDecoration(color: MyColors.greyButtonColor, border: Border.all(width: 2, color: MyColors.greyAddBorderColor)), + margin: const EdgeInsets.all(8), + alignment: Alignment.center, + child: Container( + height: 24, + width: 24, + decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), + child: const Icon(Icons.add, color: MyColors.white), + ), + ).onPress(() { + context.read().pickPdfReceiptFile(context); + }), + ], + ), + ], 15.height, ShowFillButton( title: "Submit", @@ -1256,6 +1257,8 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { return pendingForReviewAction(pendingText: "Waiting for Admins Approval"); case AdPostStatus.sold: + return pendingForReviewAction(pendingText: "Sold"); + case AdPostStatus.expired: return expiredAdAction(context); case AdPostStatus.allAds: diff --git a/lib/views/advertisement/ads_images_slider.dart b/lib/views/advertisement/ads_images_slider.dart index d3b8fca..cdae3b0 100644 --- a/lib/views/advertisement/ads_images_slider.dart +++ b/lib/views/advertisement/ads_images_slider.dart @@ -6,7 +6,7 @@ import 'package:mc_common_app/theme/colors.dart'; class CarouselWithIndicatorDemo extends StatefulWidget { final List vehicleImages; - const CarouselWithIndicatorDemo({key, required this.vehicleImages}); + const CarouselWithIndicatorDemo({super.key, required this.vehicleImages}); @override State createState() => _CarouselWithIndicatorState(); @@ -16,21 +16,15 @@ class _CarouselWithIndicatorState extends State { int _current = 0; final CarouselController _controller = CarouselController(); - // final imgList = [ - // MyAssets.bnCar, - // MyAssets.bnCar, - // MyAssets.bnCar, - // ]; - @override Widget build(BuildContext context) { return Column(children: [ CarouselSlider( items: widget.vehicleImages .map((item) => Container( - margin: EdgeInsets.all(5.0), + margin: const EdgeInsets.all(5.0), child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5.0)), + borderRadius: const BorderRadius.all(Radius.circular(5.0)), child: Image.network( item.imageUrl!, fit: BoxFit.cover, @@ -64,7 +58,7 @@ class _CarouselWithIndicatorState extends State { child: Container( width: 12.0, height: 12.0, - margin: EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.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), diff --git a/lib/views/advertisement/create_ad_view.dart b/lib/views/advertisement/create_ad_view.dart index d0ca883..3a6619f 100644 --- a/lib/views/advertisement/create_ad_view.dart +++ b/lib/views/advertisement/create_ad_view.dart @@ -34,7 +34,7 @@ class _CreateAdViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: adVM.isAdEdit ? "Update Ad": "Create Ad", + title: adVM.isAdEditEnabled ? "Update Ad": "Create Ad", isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => adVM.onBackButtonPressed(context), diff --git a/lib/views/advertisement/network_images_container.dart b/lib/views/advertisement/network_images_container.dart new file mode 100644 index 0000000..3d49de6 --- /dev/null +++ b/lib/views/advertisement/network_images_container.dart @@ -0,0 +1,159 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; + +class NetworkFilesContainerForVehiclePosting extends StatelessWidget { + final List networkFilesForVehiclePosting; + final Function(String filePath)? onCrossPressedPrimary; + final Function(int index, String filePath)? onCrossPressedSecondary; + final int? index; + final bool isReview; + final Function() onAddFilePressed; + + const NetworkFilesContainerForVehiclePosting({ + Key? key, + required this.networkFilesForVehiclePosting, + this.onCrossPressedPrimary, + this.onCrossPressedSecondary, + this.index, + required this.onAddFilePressed, + this.isReview = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return GridView.count( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 4.0, + mainAxisSpacing: 8.0, + children: List.generate( + networkFilesForVehiclePosting.length, + (index) { + return Center( + child: BuildNetworkContainer( + fileUrl: networkFilesForVehiclePosting[index].imageUrl ?? "", + onCrossPressedPrimary: onCrossPressedPrimary, + onCrossPressedSecondary: onCrossPressedSecondary, + index: index, + isReview: isReview, + )); + }, + ), + ); + } +} + +class NetworkFilesContainerForDamagedParts extends StatelessWidget { + final List networkFilesForDamagedParts; + final Function(String filePath)? onCrossPressedPrimary; + final Function(int index, String filePath)? onCrossPressedSecondary; + final int? index; + final bool isReview; + final Function() onAddFilePressed; + + const NetworkFilesContainerForDamagedParts({ + Key? key, + required this.networkFilesForDamagedParts, + this.onCrossPressedPrimary, + this.onCrossPressedSecondary, + this.index, + required this.onAddFilePressed, + this.isReview = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return GridView.count( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 4.0, + mainAxisSpacing: 8.0, + children: List.generate( + networkFilesForDamagedParts.length, + (index) { + return Center( + child: BuildNetworkContainer( + fileUrl: networkFilesForDamagedParts[index].imageUrl ?? "", + onCrossPressedPrimary: onCrossPressedPrimary, + onCrossPressedSecondary: onCrossPressedSecondary, + index: index, + isReview: isReview, + )); + }, + ), + ); + } +} + +class BuildNetworkContainer extends StatelessWidget { + final String fileUrl; + final Function(String filePath)? onCrossPressedPrimary; + final Function(int index, String filePath)? onCrossPressedSecondary; + final int? index; + final bool isReview; + final bool isPdf; + + const BuildNetworkContainer({ + Key? key, + required this.fileUrl, + this.onCrossPressedPrimary, + this.onCrossPressedSecondary, + this.index, + this.isReview = false, + this.isPdf = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + SizedBox( + height: 90, + width: 90, + child: Stack( + children: [ + isPdf + ? Container( + height: 72, + width: 70, + margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all( + width: 2, + color: MyColors.darkPrimaryColor, + )), + child: const Icon(Icons.picture_as_pdf).paddingAll(8), + ) + : Image.network( + fileUrl, + fit: BoxFit.fill, + height: 72, + width: 70, + ).paddingAll(8), + !isReview + ? Align( + alignment: Alignment.topRight, + child: MyAssets.closeWithOrangeBg.buildSvg( + fit: BoxFit.fill, + height: 30, + width: 30, + ), + ).onPress(() { + if (onCrossPressedPrimary == null) { + onCrossPressedSecondary!(index!, fileUrl); + return; + } + onCrossPressedPrimary!(fileUrl); + }) + : const SizedBox() + ], + )), + ], + ); + } +} diff --git a/lib/views/advertisement/picked_images_container.dart b/lib/views/advertisement/picked_images_container.dart index 3971938..2762d80 100644 --- a/lib/views/advertisement/picked_images_container.dart +++ b/lib/views/advertisement/picked_images_container.dart @@ -3,15 +3,17 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; class PickedFilesContainer extends StatelessWidget { - final List pickedFiles; + final List pickedFiles; final Function(String filePath)? onCrossPressedPrimary; final Function(int index, String filePath)? onCrossPressedSecondary; final int? index; final bool isReview; final bool isPdf; + final bool isFromNetwork; final Function() onAddFilePressed; const PickedFilesContainer({ @@ -23,6 +25,7 @@ class PickedFilesContainer extends StatelessWidget { required this.onAddFilePressed, this.isReview = false, this.isPdf = false, + this.isFromNetwork = false, }) : super(key: key); @override @@ -51,7 +54,7 @@ class PickedFilesContainer extends StatelessWidget { } return Center( child: BuildFilesContainer( - file: pickedFiles[index], + image: pickedFiles[index], onCrossPressedPrimary: onCrossPressedPrimary, onCrossPressedSecondary: onCrossPressedSecondary, index: index, @@ -76,7 +79,7 @@ class PickedFilesContainer extends StatelessWidget { } class BuildFilesContainer extends StatelessWidget { - final File file; + final ImageModel image; final Function(String filePath)? onCrossPressedPrimary; final Function(int index, String filePath)? onCrossPressedSecondary; final int? index; @@ -85,7 +88,7 @@ class BuildFilesContainer extends StatelessWidget { const BuildFilesContainer({ Key? key, - required this.file, + required this.image, this.onCrossPressedPrimary, this.onCrossPressedSecondary, this.index, @@ -114,12 +117,19 @@ class BuildFilesContainer extends StatelessWidget { )), child: const Icon(Icons.picture_as_pdf).paddingAll(8), ) - : Image.file( - file, - fit: BoxFit.fill, - height: 72, - width: 70, - ).paddingAll(8), + : image.isFromNetwork! + ? Image.network( + image.filePath!, + fit: BoxFit.fill, + height: 72, + width: 70, + ).paddingAll(8) + : Image.file( + File(image.filePath!), + fit: BoxFit.fill, + height: 72, + width: 70, + ).paddingAll(8), !isReview ? Align( alignment: Alignment.topRight, @@ -130,10 +140,10 @@ class BuildFilesContainer extends StatelessWidget { ), ).onPress(() { if (onCrossPressedPrimary == null) { - onCrossPressedSecondary!(index!, file.path); + onCrossPressedSecondary!(index!, image.filePath!); return; } - onCrossPressedPrimary!(file.path); + onCrossPressedPrimary!(image.filePath!); }) : const SizedBox() ], diff --git a/lib/views/advertisement/select_ad_type_view.dart b/lib/views/advertisement/select_ad_type_view.dart index 651f19d..f6f04a6 100644 --- a/lib/views/advertisement/select_ad_type_view.dart +++ b/lib/views/advertisement/select_ad_type_view.dart @@ -59,134 +59,129 @@ class SelectAdTypeView extends StatelessWidget { @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - logger.d("Clead All Values"); - // clearAll(context); - AdVM adVM = context.read(); - adVM.clearEditValues(); - return true; - }, - child: Scaffold( - appBar: CustomAppBar( - title: "Select Ad Type", - profileImageUrl: MyAssets.bnCar, - isRemoveBackButton: false, - isDrawerEnabled: false, - ), - body: Column( - children: [ - Expanded( - child: Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { - return ListView.separated( - itemCount: adVM.vehicleTypes.length, - itemBuilder: (BuildContext context, int index) { - VehicleTypeModel vehicleTypeModel = adVM.vehicleTypes[index]; - return InkWell( - onTap: () { - adVM.updateSelectionVehicleTypeId( - SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""), - ); - showMyBottomSheet(context, child: const AdDurationSelectionSheetContent(isUpdateAdSelected: false, isFromExtendAd: false)); - }, - child: SizedBox( - width: double.infinity, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ + return Scaffold( + appBar: CustomAppBar( + title: "Select Ad Type", + profileImageUrl: MyAssets.bnCar, + isRemoveBackButton: false, + isDrawerEnabled: false, + ), + body: Column( + children: [ + Expanded( + child: Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { + return ListView.separated( + itemCount: adVM.vehicleTypes.length, + itemBuilder: (BuildContext context, int index) { + VehicleTypeModel vehicleTypeModel = adVM.vehicleTypes[index]; + return InkWell( + onTap: () { + adVM.updateSelectionVehicleTypeId( + SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""), + ); + if (adVM.isAdEditEnabled) { + adVM.autoFillSelectedVehicleAdsDuration(); + adVM.autoFillSelectedVehicleAdsDetails(); + } + showMyBottomSheet(context, child: const AdDurationSelectionSheetContent(isUpdateAdSelected: false, isFromExtendAd: false)); + }, + child: SizedBox( + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + vehicleTypeModel.vehicleTypeName.toString().toText(fontSize: 18, isBold: true), + getVehicleAdTypeIcon(vehicleTypeModel.vehicleTypeEnum!), + ], + ), + if (isProvider) ...[ + Row( + children: [ + "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + "Valid Until Subscription Expiration".toText(fontSize: 13, isBold: true), + ], + ).paddingOnly(top: 5, bottom: 5), + ] else ...[ + Row( + children: [ + "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + adVM.vehicleAdDurationId.selectedOption.toText(fontSize: 13, isBold: true), + const Icon(Icons.keyboard_arrow_down_sharp, color: MyColors.darkPrimaryColor, size: 20), + ], + ).paddingOnly(top: 5, bottom: 5), + ], + if (!isProvider) ...[ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, children: [ - vehicleTypeModel.vehicleTypeName.toString().toText(fontSize: 18, isBold: true), - getVehicleAdTypeIcon(vehicleTypeModel.vehicleTypeEnum!), + adVM.vehicleAdDurationId.itemPrice.toText(fontSize: 22, isBold: true), + 2.width, + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ), ], ), - if (isProvider) ...[ - Row( - children: [ - "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - "Valid Until Subscription Expiration".toText(fontSize: 13, isBold: true), - ], - ).paddingOnly(top: 5, bottom: 5), - ] else ...[ - Row( - children: [ - "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - adVM.vehicleAdDurationId.selectedOption.toText(fontSize: 13, isBold: true), - const Icon(Icons.keyboard_arrow_down_sharp, color: MyColors.darkPrimaryColor, size: 20), - ], - ).paddingOnly(top: 5, bottom: 5), - ], - if (!isProvider) ...[ - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - adVM.vehicleAdDurationId.itemPrice.toText(fontSize: 22, isBold: true), - 2.width, - Padding( - padding: const EdgeInsets.only(bottom: 4), - child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - ), - ], - ), - ], ], - ), + ], ), - ], - ), + ), + ], + ), ).toWhiteContainer(width: double.infinity, isBorderRequired: vehicleTypeModel.isSelected! ? true : false, pading: const EdgeInsets.symmetric(horizontal: 20, vertical: 10)), - ); - }, - separatorBuilder: (BuildContext context, int index) { - return 9.height; - }, - padding: const EdgeInsets.all(20), - ); - }), - ), - if (isProvider) ...[ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + ); + }, + separatorBuilder: (BuildContext context, int index) { + return 9.height; + }, + padding: const EdgeInsets.all(20), + ); + }), + ), + if (isProvider) ...[ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + "5 of 10 ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1), + "Ads Remaining ".toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true), + ], + ), + const Text.rich( + TextSpan( children: [ - "5 of 10 ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1), - "Ads Remaining ".toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true), + TextSpan( + text: "You have left with 05 out of 50 ads given in the subscription. ", + style: TextStyle( + fontSize: 14, + color: MyColors.lightTextColor, + )), + TextSpan( + text: "Update Subscription", + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: 14, + fontWeight: FontWeight.w600, + color: MyColors.darkPrimaryColor, + )) ], ), - const Text.rich( - TextSpan( - children: [ - TextSpan( - text: "You have left with 05 out of 50 ads given in the subscription. ", - style: TextStyle( - fontSize: 14, - color: MyColors.lightTextColor, - )), - TextSpan( - text: "Update Subscription", - style: TextStyle( - decoration: TextDecoration.underline, - fontSize: 14, - fontWeight: FontWeight.w600, - color: MyColors.darkPrimaryColor, - )) - ], - ), - ), - 10.height, - ], - ).toContainer(paddingAll: 20, backgroundColor: Colors.white), - ] - ], - ), + ), + 10.height, + ], + ).toContainer(paddingAll: 20, backgroundColor: Colors.white), + ] + ], ), ); }