diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index ed84848..dc88a76 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -84,6 +84,7 @@ class GlobalConsts { static String warrantyError = "Warranty Duration Cannot be Empty"; static String vehicleDescError = "Vehicle Description Cannot be Empty"; static String attachImageError = "You must add at least 3 images"; + static String attachDamagePartImage = "Please add part image"; static String adDurationDateError = "Ad Duration start date cannot be empty"; } diff --git a/lib/models/advertisment_models/special_service_model.dart b/lib/models/advertisment_models/special_service_model.dart index 14660aa..3f5ff63 100644 --- a/lib/models/advertisment_models/special_service_model.dart +++ b/lib/models/advertisment_models/special_service_model.dart @@ -11,20 +11,24 @@ class SpecialServiceModel { List
? details; List? office; bool? isDelivery; + bool? isSelected; + bool? isChecked; SpecialServiceModel( {this.id, - this.name, - this.description, - this.price, - this.specialServiceType, - this.specialServiceTypeName, - this.isActive, - this.startDate, - this.endDate, - this.details, - this.office, - this.isDelivery}); + this.name, + this.description, + this.price, + this.specialServiceType, + this.specialServiceTypeName, + this.isActive, + this.startDate, + this.endDate, + this.details, + this.office, + this.isSelected = false, + this.isChecked = false, + this.isDelivery}); SpecialServiceModel.fromJson(Map json) { id = json['id']; @@ -49,6 +53,8 @@ class SpecialServiceModel { }); } isDelivery = json['isDelivery']; + isSelected = false; + isChecked = false; } Map toJson() { @@ -80,8 +86,7 @@ class Details { int? tocity; int? price; - Details( - {this.id, this.specialServiceID, this.fromcity, this.tocity, this.price}); + Details({this.id, this.specialServiceID, this.fromcity, this.tocity, this.price}); Details.fromJson(Map json) { id = json['id']; @@ -110,13 +115,7 @@ class Office { String? city; int? specialServiceID; - Office( - {this.id, - this.officeAreaName, - this.officeAreaNameN, - this.cityID, - this.city, - this.specialServiceID}); + Office({this.id, this.officeAreaName, this.officeAreaNameN, this.cityID, this.city, this.specialServiceID}); Office.fromJson(Map json) { id = json['id']; diff --git a/lib/models/advertisment_models/vehicle_details_models.dart b/lib/models/advertisment_models/vehicle_details_models.dart index 8c17d96..60ff707 100644 --- a/lib/models/advertisment_models/vehicle_details_models.dart +++ b/lib/models/advertisment_models/vehicle_details_models.dart @@ -406,8 +406,10 @@ class VehiclePartModel { String? partName; String? description; bool? isActive; + bool? isSelected; + bool? isChecked; - VehiclePartModel({this.id, this.partNo, this.partName, this.description, this.isActive}); + VehiclePartModel({this.id, this.partNo, this.partName, this.description, this.isActive, this.isSelected}); VehiclePartModel.fromJson(Map json) { id = json['id']; @@ -415,6 +417,8 @@ class VehiclePartModel { partName = json['partName']; description = json['description']; isActive = json['isActive']; + isSelected = false; + isChecked = false; } Map toJson() { diff --git a/lib/models/widgets_models.dart b/lib/models/widgets_models.dart new file mode 100644 index 0000000..8ad1289 --- /dev/null +++ b/lib/models/widgets_models.dart @@ -0,0 +1,6 @@ +class FilterListModel { + String title; + bool isSelected; + + FilterListModel({required this.isSelected, required this.title}); +} diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index ada3df4..5b83e70 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -1,4 +1,5 @@ import 'package:mc_common_app/api/api_client.dart'; +import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; @@ -9,7 +10,6 @@ import 'package:mc_common_app/models/advertisment_models/vehicle_details_models. import 'package:mc_common_app/models/user/cities.dart'; import 'package:mc_common_app/models/user/country.dart'; import 'package:mc_common_app/models/user/role.dart'; -import 'package:mc_common_app/classes/app_state.dart'; abstract class CommonRepo { Future getAllCountries(); @@ -50,7 +50,7 @@ abstract class CommonRepo { Future createNewAd({required AdsCreationPayloadModel adsCreationPayloadModel}); - Future> getAllAds(); + Future> getAllAds({required bool isMyAds}); Future> getMyAds(); } @@ -332,11 +332,16 @@ class CommonRepoImp implements CommonRepo { } @override - Future> getAllAds() async { + Future> getAllAds({required isMyAds}) async { + var params = { + "userID": appState.getUser.data!.userInfo!.userId ?? "", + }; + AdsGenericModel adsGenericModel = await apiClient.getJsonForObject( token: appState.getUser.data!.accessToken, (json) => AdsGenericModel.fromJson(json), ApiConsts.vehicleAdsGet, + queryParameters: isMyAds ? params : null, ); List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index])); return vehicleAdsDetails; diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index 47f4629..4148bc8 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; + import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; @@ -10,6 +11,7 @@ import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart import 'package:mc_common_app/models/advertisment_models/ads_generic_model.dart'; import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; +import 'package:mc_common_app/models/widgets_models.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/services/services.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -52,8 +54,51 @@ class AdVM extends BaseVM { String adStartDateError = ""; List allAds = []; + List adsFilteredList = []; List myAds = []; + List vehicleDamageCards = []; + + void addNewDamagePartCard({required VehicleDamageCard damageCard}) { + vehicleDamageCards.add(damageCard); + notifyListeners(); + } + + void clearDamageCards() { + vehicleDamageCards.clear(); + } + + List specialServiceCards = []; + + void addNewSpecialServiceCard({required SpecialServiceCard specialServiceCard}) { + int index = vehicleAdsSpecialServices.indexWhere((element) => element.name == specialServiceCard.serviceSelectedId!.selectedOption); + if (index != -1) { + vehicleAdsSpecialServices[index].isSelected = true; + } + specialServiceCards.add(specialServiceCard); + vehicleAdsSpecialServicesId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + adSpecialServiceDate = ""; + notifyListeners(); + } + + void removeSpecialServiceCard(int index) { + String option = specialServiceCards.elementAt(index).serviceSelectedId!.selectedOption; + + for (var value in vehicleAdsSpecialServices) { + if (value.name == option) { + value.isSelected = false; + break; + } + } + specialServiceCards.removeAt(index); + + notifyListeners(); + } + + void clearSpecialServiceCard() { + specialServiceCards.clear(); + } + bool isExploreAdsTapped = true; void updateIsExploreAds(bool value) async { @@ -64,15 +109,41 @@ class AdVM extends BaseVM { notifyListeners(); } + List adsFilterOptions = []; + + populateAdsFilterList() { + adsFilterOptions.clear(); + adsFilterOptions = [ + FilterListModel(title: "All Ads", isSelected: true), + FilterListModel(title: "Customer Ads", isSelected: false), + FilterListModel(title: "Provider Ads", isSelected: false), + FilterListModel(title: "Mowater Ads", isSelected: false), + ]; + notifyListeners(); + } + + applyFilterOnAds({required int index}) { + if (adsFilterOptions.isEmpty) return; + for (var value in adsFilterOptions) { + value.isSelected = false; + } + adsFilterOptions[index].isSelected = true; + // TODO: --> here we will filter the allAds list + // TODO: --> and get the updated list into this new list everytime filter changes + + adsFilteredList = allAds; + notifyListeners(); + } + Future getMyAds() async { isFetchingLists = true; - myAds = await commonRepo.getMyAds(); + myAds = await commonRepo.getAllAds(isMyAds: true); isFetchingLists = true; notifyListeners(); } Future getAllAds() async { - allAds = await commonRepo.getAllAds(); + allAds = await commonRepo.getAllAds(isMyAds: false); notifyListeners(); } @@ -143,6 +214,16 @@ class AdVM extends BaseVM { notifyListeners(); } + String adSpecialServiceDate = ""; + + void updateAdSpecialServiceDate(String date) { + adSpecialServiceDate = date; + if (adSpecialServiceDate.isNotEmpty) { + adStartDateError = ""; + } + notifyListeners(); + } + SelectionModel vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); void updateSelectionVehicleTypeId(SelectionModel id) async { @@ -237,10 +318,14 @@ class AdVM extends BaseVM { notifyListeners(); } - SelectionModel vehicleDamagePartId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + // SelectionModel vehicleDamagePartId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - void updateSelectionVehicleDamagePartId(SelectionModel id) { - vehicleDamagePartId = id; + void updateSelectionVehicleDamagePartId(SelectionModel id, int index) { + vehicleDamageCards[index].partSelectedId = id; + int partIndex = vehicleDamageParts.indexWhere((element) => element.partName == id.selectedOption); + if (partIndex != -1) { + // vehicleDamageParts[partIndex].isSelected = true; + } notifyListeners(); } @@ -399,19 +484,31 @@ class AdVM extends BaseVM { bool isDamagePartsValidated() { bool isValidated = true; - if (vehicleDamagePartId.selectedId == -1) { - vehicleDamagePartId.errorValue = "Please select vehicle part"; - isValidated = false; - } else { - vehicleDamagePartId.errorValue = ""; - } - if (pickedDamageImages.isEmpty || pickedDamageImages.length < 3) { - vehicleDamageImageError = GlobalConsts.attachImageError; - isValidated = false; - } else { - vehicleDamageImageError = ""; - } + vehicleDamageCards.forEach((element) { + if (element.partSelectedId!.selectedId == -1) { + element.partSelectedId!.errorValue = "Please select vehicle part"; + isValidated = false; + } else { + element.partSelectedId!.errorValue = ""; + } + }); + + vehicleDamageCards.forEach((element) { + if (element.partImages == null || element.partImages!.isEmpty) { + element.partImageErrorValue = GlobalConsts.attachDamagePartImage; + isValidated = false; + } else { + element.partImageErrorValue = ""; + } + }); + + // if (pickedDamageImages.isEmpty || pickedDamageImages.length < 3) { + // vehicleDamageImageError = GlobalConsts.attachImageError; + // isValidated = false; + // } else { + // vehicleDamageImageError = ""; + // } notifyListeners(); return isValidated; @@ -492,6 +589,8 @@ class AdVM extends BaseVM { } Utils.hideLoading(context); Utils.showToast("A new ads has been created."); + currentProgressStep = AdCreationStepsEnum.vehicleDetails; + resetValues(); navigateReplaceWithName(context, AppRoutes.dashboard); } catch (e) { Utils.hideLoading(context); @@ -529,11 +628,16 @@ class AdVM extends BaseVM { // sourceFlag for Camera = 0 // sourceFlag for Gallery = 1 - void pickImageFromPhone(int sourceFlag) async { - File? file = await commonServices.pickImageFromPhone(1); - - if (file != null) { - pickedVehicleImages.add(file); + void pickDamagePartImage(int index) async { + List images = await commonServices.pickMultipleImages(); + + if (images.isNotEmpty) { + if (vehicleDamageCards[index].partImages == null) { + vehicleDamageCards[index].partImages = images; + } else { + vehicleDamageCards[index].partImages!.addAll(images); + } + vehicleDamageCards[index].partImageErrorValue = ""; notifyListeners(); } } @@ -549,6 +653,31 @@ class AdVM extends BaseVM { notifyListeners(); } + void removeDamagePartCard(int index) { + String option = vehicleDamageCards.elementAt(index).partSelectedId!.selectedOption; + + for (var value in vehicleDamageParts) { + if (value.partName == option) { + value.isSelected = false; + break; + } + } + vehicleDamageCards.removeAt(index); + + notifyListeners(); + } + + 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); + if (index == -1) { + return; + } + vehicleDamageCards[cardIndex].partImages!.removeAt(index); + notifyListeners(); + } + void pickMultipleDamageImages() async { List Images = await commonServices.pickMultipleImages(); pickedDamageImages.addAll(Images); @@ -559,8 +688,29 @@ class AdVM extends BaseVM { void resetValues() { pickedDamageImages.clear(); pickedVehicleImages.clear(); + vehicleDamageCards.clear(); + specialServiceCards.clear(); currentProgressStep = AdCreationStepsEnum.vehicleDetails; vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleColorId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleConditionId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleMileageId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleTransmissionId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleSellerTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + vehicleDemandAmount = ""; + vehicleVin = ""; + vehicleTitle = ""; + warrantyDuration = ""; + vehicleDescription = ""; + selectionDurationStartDate = ""; + updateFinanceAvailableStatus(false); notifyListeners(); } @@ -573,11 +723,16 @@ class AdVM extends BaseVM { Future createNewAd() async { AppState appState = injector.get(); + List adsSelectedServices = []; + + for (var value in specialServiceCards) { + adsSelectedServices.add(value.serviceSelectedId!.selectedId); + } Ads ads = Ads( adsDurationID: vehicleAdDurationId.selectedId, startDate: selectionDurationStartDate, countryId: vehicleCountryId.selectedId, - specialServiceIDs: [vehicleAdsSpecialServicesId.selectedId], + specialServiceIDs: adsSelectedServices, ); List vehicleImages = []; pickedVehicleImages.forEach((element) async { @@ -585,10 +740,19 @@ class AdVM extends BaseVM { }); List vehicleDamageImages = []; - vehicleDamageImages.add(await convertFileToVehiclePostingDamageParts( - file: pickedDamageImages.first, - damagePartId: vehicleDamagePartId.selectedId, - )); + + for (var card in vehicleDamageCards) { + if (card.partImages != null && card.partImages!.length > 0) { + for (var image in card.partImages!) { + VehiclePostingDamageParts stringImage = await convertFileToVehiclePostingDamageParts( + file: image, + damagePartId: card.partSelectedId!.selectedId, + ); + vehicleDamageImages.add(stringImage); + } + } + } + VehiclePosting vehiclePosting = VehiclePosting( userID: appState.getUser.data!.userInfo!.userId, vehicleType: vehicleTypeId.selectedId, @@ -646,10 +810,41 @@ class SelectionModel { String selectedOption; int selectedId; String errorValue; + String itemPrice; SelectionModel({ this.selectedOption = "", this.errorValue = "", this.selectedId = 0, + this.itemPrice = "", + }); +} + +class VehicleDamageCard { + List? partImages; + SelectionModel? partSelectedId; + String partImageErrorValue; + + VehicleDamageCard({ + this.partImages, + this.partSelectedId, + this.partImageErrorValue = "", }); } + +class SpecialServiceCard { + SelectionModel? serviceSelectedId; + String? serviceDate; + String? serviceDateError; + String? serviceTime; + String? serviceTimeError; + + SpecialServiceCard({ + this.serviceSelectedId, + this.serviceDate = "", + this.serviceDateError = "", + this.serviceTime = "", + this.serviceTimeError = "", + }); +} + diff --git a/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart new file mode 100644 index 0000000..f0a5a6c --- /dev/null +++ b/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/common_widgets/dotted_rect.dart'; + +class DottedRoundedCard extends StatelessWidget { + final Function() onTap; + final String text; + final Widget icon; + + const DottedRoundedCard({Key? key, required this.onTap, required this.text, required this.icon}) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + height: 120, + width: 120, + color: MyColors.white, + child: DashedRect( + color: MyColors.lightIconColor, + strokeWidth: 2.0, + gap: 4.0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon, + SizedBox(width: 8), + text.toText( + fontSize: 15, + isBold: true, + color: MyColors.darkPrimaryColor, + ), + ], + ), + ), + ), + ); + } +} + +class DottedRectContainer extends StatelessWidget { + final Function() onTap; + final String text; + final Widget icon; + + const DottedRectContainer({Key? key, required this.onTap, required this.text, required this.icon}) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + height: 46, + width: double.infinity, + color: MyColors.white, + child: DashedRect( + color: MyColors.lightIconColor, + strokeWidth: 2.0, + gap: 4.0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon, + SizedBox(width: 8), + text.toText( + fontSize: 15, + isBold: true, + color: MyColors.darkPrimaryColor, + ), + ], + ), + ), + ), + ); + } +} +// +// class BuildAdStepContainer extends StatelessWidget { +// final WidgetBuilder onVehicleDetails; +// final WidgetBuilder onDamageParts; +// final WidgetBuilder onAdDuration; +// final WidgetBuilder onReviewAd; +// final AdCreationStepsEnum adCreationStepsEnum; +// +// const BuildAdStepContainer({ +// Key? key, +// required this.onVehicleDetails, +// required this.onDamageParts, +// required this.onAdDuration, +// required this.onReviewAd, +// required this.adCreationStepsEnum, +// }) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// switch (adCreationStepsEnum) { +// case AdCreationStepsEnum.vehicleDetails: +// return onVehicleDetails(context); +// +// case AdCreationStepsEnum.damageParts: +// return onDamageParts(context); +// +// case AdCreationStepsEnum.adDuration: +// return onAdDuration(context); +// +// case AdCreationStepsEnum.reviewAd: +// return onReviewAd(context); +// } +// } +// } diff --git a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart new file mode 100644 index 0000000..cb8f413 --- /dev/null +++ b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart @@ -0,0 +1,141 @@ +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:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; + +class AdDuration extends StatelessWidget { + const AdDuration({Key? key}) : super(key: key); + + void onAddServiceButtonTapped(BuildContext context, AdVM adVM) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return BottomSheetServiceContent(); + }); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Ad Duration".toText(fontSize: 18, isBold: true), + 8.height, + Builder(builder: (context) { + List vehicleAdsDurationsDrop = []; + for (var element in adVM.vehicleAdsDurations) { + vehicleAdsDurationsDrop.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateVehicleAdDurationId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + errorValue: adVM.vehicleAdDurationId.errorValue, + list: vehicleAdsDurationsDrop, + hint: "Select Duration", + dropdownValue: adVM.vehicleAdDurationId.selectedId != -1 ? DropValue(adVM.vehicleAdDurationId.selectedId, adVM.vehicleAdDurationId.selectedOption, "") : null, + ); + }), + 8.height, + TxtField( + errorValue: adVM.adStartDateError, + hint: 'Start Date', + value: adVM.selectionDurationStartDate, + isNeedClickAll: true, + postfixData: Icons.calendar_month_rounded, + postFixDataColor: MyColors.darkTextColor, + onTap: () async { + final formattedDate = await Utils.pickDateFromDatePicker(context); + adVM.updateSelectionDurationStartDate(formattedDate); + }, + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Select Special Services".toText(fontSize: 18, isBold: true), + 8.height, + CustomAddButton( + onTap: () { + onAddServiceButtonTapped(context, adVM); + }, + text: "Add Service", + icon: Container( + height: 24, + width: 24, + decoration: BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), + child: Icon( + Icons.add, + color: MyColors.white, + ), + ), + ), + 20.height, + ListView.builder( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: adVM.specialServiceCards.length, + itemBuilder: (BuildContext context, int index) { + SpecialServiceCard specialServicesCard = adVM.specialServiceCards[index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: specialServicesCard.serviceSelectedId!.selectedOption.toText(fontSize: 18, isBold: true), + ), + InkWell( + onTap: () => adVM.removeSpecialServiceCard(index), + child: Icon(Icons.delete_outline_rounded), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "12 July, 2023 - 09:30AM".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + (specialServicesCard.serviceSelectedId!.itemPrice).toText(fontSize: 20, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 14), + ], + ), + ], + ), + 5.height, + Divider(thickness: 1.5) + ], + ), + 10.height, + ], + ); + }, + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), + ], + ); + }, + ); + } +} diff --git a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart new file mode 100644 index 0000000..f3b3e5d --- /dev/null +++ b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart @@ -0,0 +1,250 @@ +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class ReviewAd extends StatelessWidget { + const ReviewAd({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + VehicleDetailsReview(), + DamagePartsReview(), + AdDurationReview(), + ], + ); + } +} + +class SingleDetailWidget extends StatelessWidget { + final String text; + final String type; + + const SingleDetailWidget({Key? key, required this.text, required this.type}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "$type:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + text.toText(fontSize: 14, color: MyColors.black, isBold: true), + ], + ); + } +} + +class VehicleDetailsReview extends StatelessWidget { + const VehicleDetailsReview({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Vehicle Details".toText(fontSize: 18, isBold: true), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(text: adVM.vehicleTypeId.selectedOption, type: "Vehicle Type"), + 16.height, + SingleDetailWidget(text: adVM.vehicleModelYearId.selectedOption, type: "Vehicle Year"), + 16.height, + SingleDetailWidget(text: adVM.vehicleConditionId.selectedOption, type: "Vehicle Condition"), + 16.height, + SingleDetailWidget(text: adVM.vehicleMileageId.selectedOption, type: "Vehicle Mileage"), + 16.height, + SingleDetailWidget(text: adVM.vehicleSellerTypeId.selectedOption, type: "Seller Type"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: "Vehicle City"), + 16.height, + SingleDetailWidget(text: adVM.vehicleVin, type: "Vehicle VIN"), + 16.height, + ], + ), + ), + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(text: adVM.vehicleModelId.selectedOption, type: "Vehicle Model"), + 16.height, + SingleDetailWidget(text: adVM.vehicleColorId.selectedOption, type: "Vehicle Color"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCategoryId.selectedOption, type: "Vehicle Category"), + 16.height, + SingleDetailWidget(text: adVM.vehicleTransmissionId.selectedOption, type: "Vehicle Transmission"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCountryId.selectedOption, type: "Vehicle Country"), + 16.height, + SingleDetailWidget(text: adVM.vehicleDemandAmount, type: "Vehicle Amount"), + 16.height, + SingleDetailWidget(text: adVM.vehicleTitle, type: "Vehicle Title"), + 16.height, + ], + ), + ), + ], + ), + SingleDetailWidget(text: adVM.warrantyDuration, type: "Warranty Available"), + 8.height, + SingleDetailWidget(text: adVM.vehicleDescription, type: "Description"), + 8.height, + SingleDetailWidget(text: adVM.financeAvailableStatus ? "Yes" : "No", type: "Finance Available"), + 8.height, + "Vehicle Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + if (adVM.pickedVehicleImages.isNotEmpty) ...[ + // 10.height, + PickedImagesContainer( + pickedImages: adVM.pickedVehicleImages, + onCrossPressedPrimary: adVM.removeImageFromList, + isReview: true, + onAddImagePressed: () {}, + ), + ], + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + }, + ); + } +} + +class DamagePartsReview extends StatelessWidget { + const DamagePartsReview({Key? key}) : super(key: key); + + Widget buildDamagePartList(AdVM adVM) { + List list = List.generate( + adVM.vehicleDamageCards.length, + (index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + Row( + children: [ + SingleDetailWidget(type: "Vehicle Part", text: adVM.vehicleDamageCards[index].partSelectedId!.selectedOption), + ], + ), + if (adVM.vehicleDamageCards[index].partImages != null && adVM.vehicleDamageCards[index].partImages!.isNotEmpty) ...[ + "Damage Part Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + PickedImagesContainer( + pickedImages: adVM.vehicleDamageCards[index].partImages!, + onCrossPressedPrimary: adVM.removeImageFromList, + isReview: true, + onAddImagePressed: () {}, + ), + ], + Divider(thickness: 2), + ], + )); + + return Column( + children: list, + ); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Vehicle Damage Part".toText(fontSize: 18, isBold: true), + buildDamagePartList(adVM), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + }, + ); + } +} + +class AdDurationReview extends StatelessWidget { + const AdDurationReview({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Ad Duration".toText(fontSize: 18, isBold: true), + 8.height, + Row( + children: [ + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(type: "Duration", text: adVM.vehicleAdDurationId.selectedOption), + ], + ), + ), + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(type: "Start Date", text: adVM.selectionDurationStartDate), + ], + ), + ), + ], + ), + if (adVM.specialServiceCards.isNotEmpty) ...[ + 15.height, + "Special Services".toText(fontSize: 18, isBold: true), + ListView.separated( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + return Row( + children: [ + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + SingleDetailWidget(type: "Special Service", text: adVM.specialServiceCards[index].serviceSelectedId!.selectedOption), + ], + ), + ), + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(type: "Amount", text: adVM.specialServiceCards[index].serviceSelectedId!.itemPrice), + ], + ), + ), + ], + ); + }, + separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2), + itemCount: adVM.specialServiceCards.length) + ], + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + }, + ); + } +} diff --git a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart new file mode 100644 index 0000000..6f21473 --- /dev/null +++ b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart @@ -0,0 +1,139 @@ +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/picked_images_container.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class DamageParts extends StatelessWidget { + const DamageParts({Key? key}) : super(key: key); + + bool getEnabledStatus(bool? isSelected) { + if (isSelected == null) { + return true; + } + if (isSelected) { + return false; + } + return true; + } + + void onAddButtonTapped(BuildContext context, AdVM adVM) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return BottomSheetListContent(adVM: adVM); + }); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomAddButton( + onTap: () { + onAddButtonTapped(context, adVM); + }, + text: "Add Damage Part", + icon: Container( + height: 24, + width: 24, + decoration: BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), + child: Icon( + Icons.add, + color: MyColors.white, + ), + )).horPaddingMain(), + 9.height, + ListView.builder( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: adVM.vehicleDamageCards.length, + itemBuilder: (BuildContext context, int index) { + VehicleDamageCard vehicleDamageCard = adVM.vehicleDamageCards[index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + vehicleDamageCard.partSelectedId!.selectedOption.toText(fontSize: 18, isBold: true), + InkWell(onTap: () => adVM.removeDamagePartCard(index), child: Icon(Icons.delete_outline_rounded)), + ], + ), + 10.height, + + // Builder(builder: (context) { + // List vehicleDamagePartsDrop = []; + // for (var element in adVM.vehicleDamageParts) { + // vehicleDamagePartsDrop.add(DropValue( + // element.id?.toInt() ?? 0, + // element.partName ?? "", + // "", + // isEnabled: true, + // )); + // } + // return DropdownField((DropValue value) { + // adVM.updateSelectionVehicleDamagePartId(SelectionModel(selectedOption: value.value, selectedId: value.id), index); + // }, + // dropdownValue: adVM.vehicleDamageCards[index].partSelectedId!.selectedId != -1 + // ? DropValue(adVM.vehicleDamageCards[index].partSelectedId!.selectedId, adVM.vehicleDamageCards[index].partSelectedId!.selectedOption, "") + // : null, + // list: vehicleDamagePartsDrop, + // hint: "Vehicle Part", + // errorValue: adVM.vehicleDamageCards[index].partSelectedId!.errorValue); + // }), + // 8.height, + // vehicleDamageCard.partImages != null ? + PickedImagesContainer( + pickedImages: vehicleDamageCard.partImages ?? [], + onCrossPressedSecondary: (imageIndex, filePath) { + adVM.removeDamageImageFromCard(imageIndex, filePath, index); + }, + index: index, + onAddImagePressed: () { + context.read().pickDamagePartImage(index); + }, + ), + // : SizedBox(), + // vehicleDamageCard.partImages == null || vehicleDamageCard.partImages!.length < 10 + // ? DottedRectContainer( + // onTap: () => context.read().pickDamagePartImage(index), + // text: "Add part image", + // icon: MyAssets.attachmentIcon.buildSvg(), + // ) + // : SizedBox(), + vehicleDamageCard.partImages != null ? 0.height : 8.height, + if (vehicleDamageCard.partImageErrorValue != "") ...[ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + vehicleDamageCard.partImageErrorValue.toText(fontSize: 14, color: Colors.red), + ], + ).paddingOnly(right: 10) + ], + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + }, + ), + // DottedRectContainer( + // onTap: () => adVM.addNewDamagePartCard( + // damageCard: VehicleDamageCard(partImageErrorValue: "", partImages: null, partSelectedId: SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""))), + // text: "Add Part", + // icon: MyAssets.attachmentIcon.buildSvg(), + // ).paddingOnly(right: 21, left: 21, top: 10, bottom: 10), + ], + ); + }, + ); + } +} diff --git a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart new file mode 100644 index 0000000..d7f1072 --- /dev/null +++ b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart @@ -0,0 +1,290 @@ +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/picked_images_container.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; + +class VehicleDetails extends StatelessWidget { + const VehicleDetails({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Vehicle Detail".toText(fontSize: 18, isBold: true), + 8.height, + Builder( + builder: (BuildContext context) { + List vehicleTypesDrop = []; + for (var element in adVM.vehicleTypes) { + vehicleTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleTypeName ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value, errorValue: "")), + list: vehicleTypesDrop, + dropdownValue: adVM.vehicleTypeId.selectedId != -1 ? DropValue(adVM.vehicleTypeId.selectedId, adVM.vehicleTypeId.selectedOption, "") : null, + errorValue: adVM.vehicleTypeId.errorValue, + hint: "Vehicle Type", + ); + }, + ), + if (adVM.vehicleTypeId.selectedId != -1) ...[ + if (adVM.isFetchingLists) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ], + ).paddingAll(10), + ] else ...[ + 8.height, + Builder(builder: (context) { + List vehicleModelsDrop = []; + for (var element in adVM.vehicleModels) { + vehicleModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.model ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleModelId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleModelsDrop, + dropdownValue: adVM.vehicleModelId.selectedId != -1 ? DropValue(adVM.vehicleModelId.selectedId, adVM.vehicleModelId.selectedOption, "") : null, + hint: "Vehicle Model", + errorValue: adVM.vehicleModelId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleYearModelsDrop = []; + for (var element in adVM.vehicleModelYears) { + vehicleYearModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.modelYear ?? "", "")); + } + + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleYearModelsDrop, + dropdownValue: adVM.vehicleModelYearId.selectedId != -1 ? DropValue(adVM.vehicleModelYearId.selectedId, adVM.vehicleModelYearId.selectedOption, "") : null, + hint: "Vehicle Model Year", + errorValue: adVM.vehicleModelYearId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleColorsDrop = []; + for (var element in adVM.vehicleColors) { + vehicleColorsDrop.add(DropValue(element.id?.toInt() ?? 0, element.color ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleColorId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleColorsDrop, + hint: "Vehicle Color", + dropdownValue: adVM.vehicleColorId.selectedId != -1 ? DropValue(adVM.vehicleColorId.selectedId, adVM.vehicleColorId.selectedOption, "") : null, + errorValue: adVM.vehicleColorId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleConditionsDrop = []; + for (var element in adVM.vehicleConditions) { + vehicleConditionsDrop.add(DropValue(element.id?.toInt() ?? 0, element.condition ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleConditionsDrop, + dropdownValue: adVM.vehicleConditionId.selectedId != -1 ? DropValue(adVM.vehicleConditionId.selectedId, adVM.vehicleConditionId.selectedOption, "") : null, + hint: "Vehicle Condition", + errorValue: adVM.vehicleConditionId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleCategoriesDrop = []; + for (var element in adVM.vehicleCategories) { + vehicleCategoriesDrop.add(DropValue(element.id?.toInt() ?? 0, element.category ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleCategoriesDrop, + hint: "Vehicle Category", + dropdownValue: adVM.vehicleCategoryId.selectedId != -1 ? DropValue(adVM.vehicleCategoryId.selectedId, adVM.vehicleCategoryId.selectedOption, "") : null, + errorValue: adVM.vehicleCategoryId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleMileageDrop = []; + for (var element in adVM.vehicleMileages) { + vehicleMileageDrop.add(DropValue(element.id?.toInt() ?? 0, "${element.mileageStart ?? ""} - ${element.mileageEnd ?? ""}", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleMileageId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleMileageDrop, + dropdownValue: adVM.vehicleMileageId.selectedId != -1 ? DropValue(adVM.vehicleMileageId.selectedId, adVM.vehicleMileageId.selectedOption, "") : null, + hint: "Vehicle Mileage", + errorValue: adVM.vehicleMileageId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleTransmissionsDrop = []; + for (var element in adVM.vehicleTransmissions) { + vehicleTransmissionsDrop.add(DropValue(element.id?.toInt() ?? 0, element.transmission ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleTransmissionId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleTransmissionsDrop, + hint: "Vehicle Transmission", + errorValue: adVM.vehicleTransmissionId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleSellerTypesDrop = []; + for (var element in adVM.vehicleSellerTypes) { + vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleSellerTypesDrop, + dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null, + hint: "Vehicle Seller Type", + errorValue: adVM.vehicleSellerTypeId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleCountriesDrop = []; + for (var element in adVM.vehicleCountries) { + vehicleCountriesDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleCountryId(SelectionModel(selectedOption: value.value, selectedId: value.id)), + list: vehicleCountriesDrop, + dropdownValue: adVM.vehicleCountryId.selectedId != -1 ? DropValue(adVM.vehicleCountryId.selectedId, adVM.vehicleCountryId.selectedOption, "") : null, + hint: "Vehicle Country", + errorValue: adVM.vehicleCountryId.errorValue, + ); + }), + if (adVM.vehicleCountryId.selectedId != -1) ...[ + if (adVM.isCountryFetching) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [const CircularProgressIndicator().paddingAll(10)], + ), + ] else ...[ + 8.height, + Builder(builder: (context) { + List vehicleCitiesDrop = []; + for (var element in adVM.vehicleCities) { + vehicleCitiesDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleCitiesDrop, + dropdownValue: adVM.vehicleCityId.selectedId != -1 ? DropValue(adVM.vehicleCityId.selectedId, adVM.vehicleCityId.selectedOption, "") : null, + hint: "Vehicle City", + errorValue: adVM.vehicleCityId.errorValue, + ); + }), + ], + ], + 8.height, + TxtField( + value: adVM.vehicleDemandAmount, + errorValue: adVM.demandAmountError, + hint: "Demand Amount", + onChanged: (v) => adVM.updateVehicleDemandAmount(v), + ), + 8.height, + TxtField( + value: adVM.vehicleVin, + errorValue: adVM.vehicleVinError, + hint: "Vehicle VIN", + onChanged: (v) => adVM.updateVehicleVin(v), + ), + 8.height, + TxtField( + value: adVM.vehicleTitle, + errorValue: adVM.vehicleTitleError, + hint: "Vehicle Title", + onChanged: (v) => adVM.updateVehicleTitle(v), + ), + 8.height, + TxtField( + value: adVM.warrantyDuration, + errorValue: adVM.warrantyError, + hint: "Warranty Available (No. of Years)", + onChanged: (v) => adVM.updateVehicleWarrantyDuration(v), + ), + 8.height, + TxtField( + value: adVM.vehicleDescription, + hint: "Vehicle Description", + maxLines: 5, + errorValue: adVM.vehicleDescError, + onChanged: (v) => adVM.updateVehicleDescription(v), + ), + 22.height, + "Finance Available".toText(fontSize: 16), + 8.height, + Container( + width: 65, + height: 37, + decoration: BoxDecoration( + color: adVM.financeAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white, + borderRadius: BorderRadius.circular(25.0), + border: Border.all(color: MyColors.black, width: 1.5), + ), + child: CupertinoSwitch( + activeColor: MyColors.darkPrimaryColor, + trackColor: MyColors.white, + thumbColor: MyColors.grey98Color, + value: adVM.financeAvailableStatus, + onChanged: (value) { + adVM.updateFinanceAvailableStatus(value); + }, + ), + ), + 28.height, + "Vehicle Pictures".toText(fontSize: 18, isBold: true), + 8.height, + DottedRectContainer( + onTap: () => context.read().pickMultipleImages(), + text: "Attach Image", + icon: MyAssets.attachmentIcon.buildSvg(), + ), + if (adVM.vehicleImageError != "") ...[ + 10.height, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + adVM.vehicleImageError.toText(fontSize: 14, color: Colors.red), + ], + ).paddingOnly(right: 10) + ], + if (adVM.pickedVehicleImages.isNotEmpty) ...[ + 16.height, + PickedImagesContainer( + pickedImages: adVM.pickedVehicleImages, + onCrossPressedPrimary: adVM.removeImageFromList, + onAddImagePressed: () { + context.read().pickMultipleImages(); + }, + ), + ], + 15.height, + ], + ] + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + }); + } +} diff --git a/lib/views/advertisement/ad_creation_steps_containers.dart b/lib/views/advertisement/ad_creation_steps_containers.dart deleted file mode 100644 index 624f1d4..0000000 --- a/lib/views/advertisement/ad_creation_steps_containers.dart +++ /dev/null @@ -1,667 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:mc_common_app/classes/consts.dart'; -import 'package:mc_common_app/extensions/int_extensions.dart'; -import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package: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/ad_view_model.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'; -import 'package:mc_common_app/widgets/txt_field.dart'; -import 'package:provider/provider.dart'; -import 'package:mc_common_app/widgets/common_widgets/dotted_rect.dart'; - -class AttachImageContainer extends StatelessWidget { - final Function() onTap; - - const AttachImageContainer({Key? key, required this.onTap}) : super(key: key); - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: onTap, - child: Container( - height: 46, - width: double.infinity, - color: MyColors.white, - child: DashedRect( - color: MyColors.lightIconColor, - strokeWidth: 2.0, - gap: 4.0, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - MyAssets.attachmentIcon.buildSvg(), - "Attach Image".toText( - fontSize: 15, - isBold: true, - color: MyColors.darkPrimaryColor, - ), - ], - ), - ), - ), - ); - } -} - -class BuildAdStepContainer extends StatelessWidget { - final WidgetBuilder onVehicleDetails; - final WidgetBuilder onDamageParts; - final WidgetBuilder onAdDuration; - final WidgetBuilder onReviewAd; - final AdCreationStepsEnum adCreationStepsEnum; - - const BuildAdStepContainer({ - Key? key, - required this.onVehicleDetails, - required this.onDamageParts, - required this.onAdDuration, - required this.onReviewAd, - required this.adCreationStepsEnum, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - switch (adCreationStepsEnum) { - case AdCreationStepsEnum.vehicleDetails: - return onVehicleDetails(context); - - case AdCreationStepsEnum.damageParts: - return onDamageParts(context); - - case AdCreationStepsEnum.adDuration: - return onAdDuration(context); - - case AdCreationStepsEnum.reviewAd: - return onReviewAd(context); - } - } -} - -class VehicleDetails extends StatelessWidget { - const VehicleDetails({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Detail".toText(fontSize: 18, isBold: true), - 8.height, - Builder( - builder: (BuildContext context) { - List vehicleTypesDrop = []; - for (var element in adVM.vehicleTypes) { - vehicleTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleTypeName ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value, errorValue: "")), - list: vehicleTypesDrop, - dropdownValue: adVM.vehicleTypeId.selectedId != -1 ? DropValue(adVM.vehicleTypeId.selectedId, adVM.vehicleTypeId.selectedOption, "") : null, - errorValue: adVM.vehicleTypeId.errorValue, - hint: "Vehicle Type", - ); - }, - ), - if (adVM.vehicleTypeId.selectedId != -1) ...[ - if (adVM.isFetchingLists) ...[ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - CircularProgressIndicator(), - ], - ).paddingAll(10), - ] else ...[ - 8.height, - Builder(builder: (context) { - List vehicleModelsDrop = []; - for (var element in adVM.vehicleModels) { - vehicleModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.model ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleModelId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleModelsDrop, - dropdownValue: adVM.vehicleModelId.selectedId != -1 ? DropValue(adVM.vehicleModelId.selectedId, adVM.vehicleModelId.selectedOption, "") : null, - - hint: "Vehicle Model", - errorValue: adVM.vehicleModelId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleYearModelsDrop = []; - for (var element in adVM.vehicleModelYears) { - vehicleYearModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.modelYear ?? "", "")); - } - - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleYearModelsDrop, - dropdownValue: adVM.vehicleModelYearId.selectedId != -1 ? DropValue(adVM.vehicleModelYearId.selectedId, adVM.vehicleModelYearId.selectedOption, "") : null, - hint: "Vehicle Model Year", - errorValue: adVM.vehicleModelYearId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleColorsDrop = []; - for (var element in adVM.vehicleColors) { - vehicleColorsDrop.add(DropValue(element.id?.toInt() ?? 0, element.color ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleColorId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleColorsDrop, - hint: "Vehicle Color", - dropdownValue: adVM.vehicleColorId.selectedId != -1 ? DropValue(adVM.vehicleColorId.selectedId, adVM.vehicleColorId.selectedOption, "") : null, - - errorValue: adVM.vehicleColorId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleConditionsDrop = []; - for (var element in adVM.vehicleConditions) { - vehicleConditionsDrop.add(DropValue(element.id?.toInt() ?? 0, element.condition ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleConditionsDrop, - dropdownValue: adVM.vehicleConditionId.selectedId != -1 ? DropValue(adVM.vehicleConditionId.selectedId, adVM.vehicleConditionId.selectedOption, "") : null, - - hint: "Vehicle Condition", - errorValue: adVM.vehicleConditionId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleCategoriesDrop = []; - for (var element in adVM.vehicleCategories) { - vehicleCategoriesDrop.add(DropValue(element.id?.toInt() ?? 0, element.category ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleCategoriesDrop, - hint: "Vehicle Category", - dropdownValue: adVM.vehicleCategoryId.selectedId != -1 ? DropValue(adVM.vehicleCategoryId.selectedId, adVM.vehicleCategoryId.selectedOption, "") : null, - - errorValue: adVM.vehicleCategoryId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleMileageDrop = []; - for (var element in adVM.vehicleMileages) { - vehicleMileageDrop.add(DropValue(element.id?.toInt() ?? 0, "${element.mileageStart ?? ""} - ${element.mileageEnd ?? ""}", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleMileageId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleMileageDrop, - dropdownValue: adVM.vehicleMileageId.selectedId != -1 ? DropValue(adVM.vehicleMileageId.selectedId, adVM.vehicleMileageId.selectedOption, "") : null, - hint: "Vehicle Mileage", - errorValue: adVM.vehicleMileageId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleTransmissionsDrop = []; - for (var element in adVM.vehicleTransmissions) { - vehicleTransmissionsDrop.add(DropValue(element.id?.toInt() ?? 0, element.transmission ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleTransmissionId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleTransmissionsDrop, - hint: "Vehicle Transmission", - errorValue: adVM.vehicleTransmissionId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleSellerTypesDrop = []; - for (var element in adVM.vehicleSellerTypes) { - vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleSellerTypesDrop, - dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null, - - hint: "Vehicle Seller Type", - errorValue: adVM.vehicleSellerTypeId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleCountriesDrop = []; - for (var element in adVM.vehicleCountries) { - vehicleCountriesDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleCountryId(SelectionModel(selectedOption: value.value, selectedId: value.id)), - list: vehicleCountriesDrop, - dropdownValue: adVM.vehicleCountryId.selectedId != -1 ? DropValue(adVM.vehicleCountryId.selectedId, adVM.vehicleCountryId.selectedOption, "") : null, - - hint: "Vehicle Country", - errorValue: adVM.vehicleCountryId.errorValue, - ); - }), - if (adVM.vehicleCountryId.selectedId != -1) ...[ - if (adVM.isCountryFetching) ...[ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [const CircularProgressIndicator().paddingAll(10)], - ), - ] else ...[ - 8.height, - Builder(builder: (context) { - List vehicleCitiesDrop = []; - for (var element in adVM.vehicleCities) { - vehicleCitiesDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleCitiesDrop, - dropdownValue: adVM.vehicleCityId.selectedId != -1 ? DropValue(adVM.vehicleCityId.selectedId, adVM.vehicleCityId.selectedOption, "") : null, - hint: "Vehicle City", - errorValue: adVM.vehicleCityId.errorValue, - ); - }), - ], - ], - 8.height, - TxtField( - value: adVM.vehicleDemandAmount, - errorValue: adVM.demandAmountError, - hint: "Demand Amount", - onChanged: (v) => adVM.updateVehicleDemandAmount(v), - ), - 8.height, - TxtField( - value: adVM.vehicleVin, - errorValue: adVM.vehicleVinError, - hint: "Vehicle VIN", - onChanged: (v) => adVM.updateVehicleVin(v), - ), - 8.height, - TxtField( - value: adVM.vehicleTitle, - errorValue: adVM.vehicleTitleError, - hint: "Vehicle Title", - onChanged: (v) => adVM.updateVehicleTitle(v), - ), - 8.height, - TxtField( - value: adVM.warrantyDuration, - errorValue: adVM.warrantyError, - hint: "Warranty Available (No. of Years)", - onChanged: (v) => adVM.updateVehicleWarrantyDuration(v), - ), - 8.height, - TxtField( - value: adVM.vehicleDescription, - hint: "Vehicle Description", - maxLines: 5, - errorValue: adVM.vehicleDescError, - onChanged: (v) => adVM.updateVehicleDescription(v), - ), - 22.height, - "Finance Available".toText(fontSize: 16), - 8.height, - Container( - width: 65, - height: 37, - decoration: BoxDecoration( - color: adVM.financeAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white, - borderRadius: BorderRadius.circular(25.0), - border: Border.all(color: MyColors.black, width: 1.5), - ), - child: CupertinoSwitch( - activeColor: MyColors.darkPrimaryColor, - trackColor: MyColors.white, - thumbColor: MyColors.grey98Color, - value: adVM.financeAvailableStatus, - onChanged: (value) { - adVM.updateFinanceAvailableStatus(value); - }, - ), - ), - 28.height, - "Vehicle Pictures".toText(fontSize: 18, isBold: true), - 8.height, - AttachImageContainer(onTap: () { - context.read().pickMultipleImages(); - }), - if (adVM.vehicleImageError != "") ...[ - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - adVM.vehicleImageError.toText(fontSize: 14, color: Colors.red), - ], - ).paddingOnly(right: 10) - ], - if (adVM.pickedVehicleImages.isNotEmpty) ...[ - 16.height, - PickedImagesContainer( - pickedImages: adVM.pickedVehicleImages, - onCrossPressed: adVM.removeImageFromList, - ), - ], - 15.height, - ], - ] - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }); - } -} - -class DamageParts extends StatelessWidget { - const DamageParts({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Damage Pictures".toText(fontSize: 18, isBold: true), - 8.height, - Builder(builder: (context) { - List vehicleDamagePartsDrop = []; - for (var element in adVM.vehicleDamageParts) { - vehicleDamagePartsDrop.add(DropValue(element.id?.toInt() ?? 0, element.partName ?? "", "")); - } - return DropdownField( - (DropValue value) { - adVM.updateSelectionVehicleDamagePartId(SelectionModel(selectedOption: value.value, selectedId: value.id)); - }, - dropdownValue: adVM.vehicleDamagePartId.selectedId != -1 ? DropValue(adVM.vehicleDamagePartId.selectedId, adVM.vehicleDamagePartId.selectedOption, "") : null, - list: vehicleDamagePartsDrop, - hint: "Vehicle Part", - errorValue: adVM.vehicleDamagePartId.errorValue, - ); - }), - 8.height, - AttachImageContainer(onTap: () { - adVM.pickMultipleDamageImages(); - }), - if (adVM.vehicleDamageImageError != "") ...[ - 10.height, - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - adVM.vehicleDamageImageError.toText(fontSize: 14, color: Colors.red), - ], - ).paddingOnly(right: 10) - ], - if (adVM.pickedDamageImages.isNotEmpty) ...[ - 16.height, - PickedImagesContainer( - pickedImages: adVM.pickedDamageImages, - onCrossPressed: adVM.removeDamageImageFromList, - ), - ], - 20.height, - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, - ); - } -} - -class AdDuration extends StatelessWidget { - const AdDuration({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Ad Duration".toText(fontSize: 18, isBold: true), - 8.height, - Builder(builder: (context) { - List vehicleAdsDurationsDrop = []; - for (var element in adVM.vehicleAdsDurations) { - vehicleAdsDurationsDrop.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateVehicleAdDurationId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - errorValue: adVM.vehicleAdDurationId.errorValue, - list: vehicleAdsDurationsDrop, - hint: "Select Duration", - ); - }), - 8.height, - TxtField( - errorValue: adVM.adStartDateError, - hint: 'Start Date', - value: adVM.selectionDurationStartDate, - isNeedClickAll: true, - postfixData: Icons.calendar_month_rounded, - postFixDataColor: MyColors.lightTextColor, - onTap: () async { - final formattedDate = await Utils.pickDateFromDatePicker(context); - adVM.updateSelectionDurationStartDate(formattedDate); - }, - ), - 28.height, - "Select Special Services".toText(fontSize: 18, isBold: true), - 8.height, - Builder(builder: (context) { - List vehicleAdsSpecialServices = []; - for (var element in adVM.vehicleAdsSpecialServices) { - vehicleAdsSpecialServices.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleAdsSpecialServices, - hint: "Select Service", - ); - }), - 20.height, - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, - ); - } -} - -class SingleDetailWidget extends StatelessWidget { - final String text; - final String type; - - const SingleDetailWidget({Key? key, required this.text, required this.type}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "$type:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - text.toText(fontSize: 14, color: MyColors.black, isBold: true), - ], - ); - } -} - -class ReviewAd extends StatelessWidget { - const ReviewAd({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - VehicleDetailsReview(), - DamagePartsReview(), - AdDurationReview(), - ], - ); - } -} - -class VehicleDetailsReview extends StatelessWidget { - const VehicleDetailsReview({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Details".toText(fontSize: 18, isBold: true), - 8.height, - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(text: adVM.vehicleTypeId.selectedOption, type: "Vehicle Type"), - 16.height, - SingleDetailWidget(text: adVM.vehicleModelYearId.selectedOption, type: "Vehicle Year"), - 16.height, - SingleDetailWidget(text: adVM.vehicleConditionId.selectedOption, type: "Vehicle Condition"), - 16.height, - SingleDetailWidget(text: adVM.vehicleMileageId.selectedOption, type: "Vehicle Mileage"), - 16.height, - SingleDetailWidget(text: adVM.vehicleSellerTypeId.selectedOption, type: "Seller Type"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: "Vehicle City"), - 16.height, - SingleDetailWidget(text: adVM.vehicleVin, type: "Vehicle VIN"), - 16.height, - ], - ), - ), - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(text: adVM.vehicleModelId.selectedOption, type: "Vehicle Model"), - 16.height, - SingleDetailWidget(text: adVM.vehicleColorId.selectedOption, type: "Vehicle Color"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCategoryId.selectedOption, type: "Vehicle Category"), - 16.height, - SingleDetailWidget(text: adVM.vehicleTransmissionId.selectedOption, type: "Vehicle Transmission"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCountryId.selectedOption, type: "Vehicle Country"), - 16.height, - SingleDetailWidget(text: adVM.vehicleDemandAmount, type: "Vehicle Amount"), - 16.height, - SingleDetailWidget(text: adVM.vehicleTitle, type: "Vehicle Title"), - 16.height, - ], - ), - ), - ], - ), - SingleDetailWidget(text: adVM.warrantyDuration, type: "Warranty Available"), - 8.height, - SingleDetailWidget(text: adVM.vehicleDescription, type: "Description"), - 8.height, - SingleDetailWidget(text: adVM.financeAvailableStatus ? "Yes" : "No", type: "Finance Available"), - 8.height, - "Vehicle Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - if (adVM.pickedVehicleImages.isNotEmpty) ...[ - // 10.height, - PickedImagesContainer( - pickedImages: adVM.pickedVehicleImages, - onCrossPressed: adVM.removeImageFromList, - ), - ], - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, - ); - } -} - -class DamagePartsReview extends StatelessWidget { - const DamagePartsReview({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Damage Part".toText(fontSize: 18, isBold: true), - 8.height, - Row( - children: [ - SingleDetailWidget(type: "Vehicle Part", text: adVM.vehicleDamagePartId.selectedOption), - ], - ), - 8.height, - "Damage Part Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - if (adVM.pickedDamageImages.isNotEmpty) ...[ - // 16.height, - PickedImagesContainer( - pickedImages: adVM.pickedDamageImages, - onCrossPressed: adVM.removeDamageImageFromList, - ), - ], - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, - ); - } -} - -class AdDurationReview extends StatelessWidget { - const AdDurationReview({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Damage Part".toText(fontSize: 18, isBold: true), - 8.height, - Row( - children: [ - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(type: "Duration", text: adVM.vehicleAdDurationId.selectedOption), - 8.height, - SingleDetailWidget(type: "Special Service", text: adVM.vehicleAdsSpecialServicesId.selectedOption), - ], - ), - ), - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(type: "Start Date", text: adVM.selectionDurationStartDate), - ], - ), - ), - ], - ), - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, - ); - } -} diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 7e89760..72c901b 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -1,10 +1,10 @@ +import 'package:mc_common_app/views/advertisement/ads_images_slider.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/theme/colors.dart'; -import 'package:mc_common_app/views/advertisement/ads_images_slider.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; @@ -67,7 +67,7 @@ class AdsDetailView extends StatelessWidget { ), ], ), - "${adDetails.createdOn}".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + adDetails.createdOn != null ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor) : SizedBox(), ], ), Row( diff --git a/lib/views/advertisement/ads_images_slider.dart b/lib/views/advertisement/ads_images_slider.dart index 2330c84..d3b8fca 100644 --- a/lib/views/advertisement/ads_images_slider.dart +++ b/lib/views/advertisement/ads_images_slider.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:carousel_slider/carousel_slider.dart'; +import 'package:flutter/material.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/theme/colors.dart'; diff --git a/lib/views/advertisement/ads_list.dart b/lib/views/advertisement/ads_list.dart index 9a40491..a59d86f 100644 --- a/lib/views/advertisement/ads_list.dart +++ b/lib/views/advertisement/ads_list.dart @@ -101,9 +101,11 @@ class AdCard extends StatelessWidget { (adDetails.vehicle!.cityName ?? "").toText( color: MyColors.lightTextColor, ), - "9 Hours Ago".toText( - color: MyColors.lightTextColor, - ), + adDetails.createdOn != null + ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText( + color: MyColors.lightTextColor, + ) + : SizedBox(), ], ), ], diff --git a/lib/views/advertisement/bottom_sheet_content.dart b/lib/views/advertisement/bottom_sheet_content.dart new file mode 100644 index 0000000..350285e --- /dev/null +++ b/lib/views/advertisement/bottom_sheet_content.dart @@ -0,0 +1,262 @@ +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/utils.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/time_slots.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; + +class BottomSheetListContent extends StatefulWidget { + final AdVM adVM; + + const BottomSheetListContent({Key? key, required this.adVM}) : super(key: key); + + @override + State createState() => _BottomSheetListContentState(); +} + +class _BottomSheetListContentState extends State { + bool checkBoxValue = false; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.85, + child: Column( + children: [ + Container( + margin: const EdgeInsets.all(8), + height: 8, + width: 60, + decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))), + ), + 12.height, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + "Damage Part List".toText(fontSize: 24, isBold: true), + ], + ), + 8.height, + TxtField( + value: "", + errorValue: "", + hint: "Search Part", + onChanged: (value) {}, + ), + 8.height, + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: widget.adVM.vehicleDamageParts.length, + itemBuilder: (BuildContext context, int index) { + VehiclePartModel vehiclePart = widget.adVM.vehicleDamageParts[index]; + return Column( + children: [ + // CheckboxListTile( + // value: false, + // visualDensity: VisualDensity.compact, + // contentPadding: EdgeInsets.zero, + // controlAffinity: ListTileControlAffinity.leading, + // title: "Rear Break Light".toText( + // fontSize: 16, + // isBold: true, + // ), + // onChanged: (value) {}, + // ), + InkWell( + onTap: () { + if (vehiclePart.isSelected!) { + return; + } + widget.adVM.vehicleDamageParts[index].isChecked = !(widget.adVM.vehicleDamageParts[index].isChecked!); + setState(() {}); + }, + child: Row( + children: [ + SizedBox( + height: 40.0, + width: 30.0, + child: Transform.scale( + scale: 1.3, + child: Checkbox( + value: vehiclePart.isSelected! ? true : vehiclePart.isChecked, + activeColor: vehiclePart.isSelected! ? MyColors.lightTextColor : MyColors.primaryColor, + onChanged: (value) {}, + ), + ), + ), + const SizedBox(width: 20), + vehiclePart.partName.toString().toText( + fontSize: 16, + isBold: true, + color: vehiclePart.isSelected! ? MyColors.lightTextColor : MyColors.black, + ) + ], + ), + ), + const Divider(thickness: 1), + ], + ); + }, + ), + ), + SizedBox( + width: double.infinity, + child: ShowFillButton( + title: "Add Damage Part", + onPressed: () { + for (var value in widget.adVM.vehicleDamageParts) { + if (value.isChecked! && !value.isSelected!) { + widget.adVM.addNewDamagePartCard( + damageCard: VehicleDamageCard( + partImageErrorValue: "", + partImages: null, + partSelectedId: SelectionModel(selectedOption: value.partName!, selectedId: value.id!, errorValue: ""), + ), + ); + value.isChecked = false; + value.isSelected = true; + } + } + Navigator.pop(context); + }, + ).paddingOnly(bottom: 10), + ), + ], + ), + ).horPaddingMain(); + } +} + +class BottomSheetServiceContent extends StatelessWidget { + const BottomSheetServiceContent({Key? key}) : super(key: key); + + bool isButtonTappable(AdVM adVM) { + bool status = (adVM.vehicleAdsSpecialServicesId.selectedId != -1) && (adVM.vehicleAdsSpecialServicesId.selectedOption != ""); + if (status) { + return true; + } + return false; + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.85, + child: Column( + children: [ + Container( + margin: const EdgeInsets.all(8), + height: 8, + width: 60, + decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))), + ), + 12.height, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Add Special Service".toText(fontSize: 24, isBold: true), + 8.height, + Builder(builder: (context) { + List vehicleAdsSpecialServices = []; + for (var element in adVM.vehicleAdsSpecialServices) { + if (!element.isSelected!) { + vehicleAdsSpecialServices.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", element.price == null ? "" : element.price!.toInt().toString())); + } + } + return DropdownField( + (DropValue value) => adVM.updateVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), + list: vehicleAdsSpecialServices, + hint: "Select Service", + dropdownValue: + adVM.vehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.vehicleAdsSpecialServicesId.selectedId, adVM.vehicleAdsSpecialServicesId.selectedOption, "") : null, + ); + }), + 8.height, + TxtField( + errorValue: adVM.adStartDateError, + hint: 'Date', + value: adVM.adSpecialServiceDate, + isNeedClickAll: true, + postfixData: Icons.calendar_month_rounded, + postFixDataColor: MyColors.lightTextColor, + onTap: () async { + final formattedDate = await Utils.pickDateFromDatePicker(context); + adVM.updateAdSpecialServiceDate(formattedDate); + }, + ), + 22.height, + "Available slots".toText(fontSize: 15, isBold: true), + 8.height, + const BuildTimeSlots(), + 22.height, + "Service Amount".toText(fontSize: 16, isBold: true, color: MyColors.lightTextColor), + if (adVM.vehicleAdsSpecialServicesId.selectedId != -1) ...[ + adVM.vehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true), + "SAR".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + ], + + // 5.height, + // Divider(thickness: 1.2), + // 5.height, + // DottedRectContainer( + // onTap: () => null, + // text: "Add Service", + // icon: MyAssets.attachmentIcon.buildSvg(), + // ), + ], + ), + ), + SizedBox( + width: double.infinity, + child: ShowFillButton( + backgroundColor: !isButtonTappable(adVM) ? MyColors.lightTextColor : MyColors.primaryColor, + title: "Add Service", + onPressed: () { + if (!isButtonTappable(adVM)) { + return; + } + Navigator.pop(context); + + adVM.addNewSpecialServiceCard( + specialServiceCard: SpecialServiceCard( + serviceDate: "", + serviceDateError: "", + serviceSelectedId: adVM.vehicleAdsSpecialServicesId, + serviceTimeError: "", + serviceTime: "", + ), + ); + // for (var value in widget.adVM.vehicleDamageParts) { + // if (value.isChecked! && !value.isSelected!) { + // widget.adVM.addNewDamagePartCard( + // damageCard: VehicleDamageCard( + // partImageErrorValue: "", + // partImages: null, + // partSelectedId: SelectionModel(selectedOption: value.partName!, selectedId: value.id!, errorValue: ""), + // ), + // ); + // value.isChecked = false; + // value.isSelected = true; + // } + // } + }, + ).paddingOnly(bottom: 10), + ), + ], + ).horPaddingMain(), + ); + }, + ); + } +} diff --git a/lib/views/advertisement/create_ad_progress_steps.dart b/lib/views/advertisement/create_ad_progress_steps.dart index a3e4349..54efd31 100644 --- a/lib/views/advertisement/create_ad_progress_steps.dart +++ b/lib/views/advertisement/create_ad_progress_steps.dart @@ -1,10 +1,10 @@ +import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; -import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; @@ -25,7 +25,9 @@ class CreateAdProgressSteps extends StatelessWidget { color: isSelected ? MyColors.darkPrimaryColor : MyColors.lightIconColor, ), ), - child: icon.buildSvg(color: isSelected ? MyColors.white : MyColors.lightIconColor,), + child: icon.buildSvg( + color: isSelected ? MyColors.white : MyColors.lightIconColor, + ), ), 5.height, title.toText( diff --git a/lib/views/advertisement/create_ad_view.dart b/lib/views/advertisement/create_ad_view.dart index 915b8c4..783f0da 100644 --- a/lib/views/advertisement/create_ad_view.dart +++ b/lib/views/advertisement/create_ad_view.dart @@ -1,11 +1,13 @@ - import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; -import 'package:mc_common_app/views/advertisement/ad_creation_steps_containers.dart'; +import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_duration_container.dart'; +import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_review_containers.dart'; +import 'package:mc_common_app/views/advertisement/ad_creation_steps/damage_parts_container.dart'; +import 'package:mc_common_app/views/advertisement/ad_creation_steps/vehicle_details_container.dart'; import 'package:mc_common_app/views/advertisement/create_ad_progress_steps.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; diff --git a/lib/views/advertisement/custom_add_button.dart b/lib/views/advertisement/custom_add_button.dart new file mode 100644 index 0000000..a502777 --- /dev/null +++ b/lib/views/advertisement/custom_add_button.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; + +class CustomAddButton extends StatelessWidget { + final Widget icon; + final String text; + final Function() onTap; + + const CustomAddButton({Key? key, required this.text, required this.onTap, required this.icon}) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + height: 86, + decoration: BoxDecoration(border: Border.all(width: 2, color: MyColors.primaryColor)), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon, + SizedBox(width: 10), + text.toText( + fontSize: 15, + isBold: true, + color: MyColors.lightTextColor, + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/advertisement/picked_images_container.dart b/lib/views/advertisement/picked_images_container.dart index 125d9c1..95b20d1 100644 --- a/lib/views/advertisement/picked_images_container.dart +++ b/lib/views/advertisement/picked_images_container.dart @@ -2,34 +2,94 @@ 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/widgets/extensions/extensions_widget.dart'; class PickedImagesContainer extends StatelessWidget { final List pickedImages; - final Function(String filePath) onCrossPressed; + final Function(String filePath)? onCrossPressedPrimary; + final Function(int index, String filePath)? onCrossPressedSecondary; + final int? index; + final bool isReview; + final Function() onAddImagePressed; const PickedImagesContainer({ Key? key, required this.pickedImages, - required this.onCrossPressed, + this.onCrossPressedPrimary, + this.onCrossPressedSecondary, + this.index, + required this.onAddImagePressed, + this.isReview = false, }) : super(key: key); @override Widget build(BuildContext context) { + return GridView.count( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + crossAxisCount: 4, + crossAxisSpacing: 4.0, + mainAxisSpacing: 8.0, + children: List.generate( + isReview ? pickedImages.length : pickedImages.length + 1, + (index) { + if (index == pickedImages.length && !isReview) { + return Container( + margin: EdgeInsets.all(8), + color: MyColors.lightTextColor.withOpacity(0.4), + alignment: Alignment.center, + child: Container( + height: 24, + width: 24, + decoration: BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), + child: Icon( + Icons.add, + color: MyColors.white, + ), + ), + ).onPress(onAddImagePressed); + } + return Center( + child: BuildImageContainer( + file: pickedImages[index], + onCrossPressedPrimary: onCrossPressedPrimary, + onCrossPressedSecondary: onCrossPressedSecondary, + index: index, + isReview: isReview, + ), + ); + }, + ), + ); return Wrap( - children: pickedImages.map((file) => BuildImageContainer(file: file, onCrossPressed: onCrossPressed,)).toList(), + children: pickedImages + .map((file) => BuildImageContainer( + file: file, + onCrossPressedPrimary: onCrossPressedPrimary, + onCrossPressedSecondary: onCrossPressedSecondary, + index: index, + isReview: isReview, + )) + .toList(), ); } } class BuildImageContainer extends StatelessWidget { final File file; - final Function(String filePath) onCrossPressed; + final Function(String filePath)? onCrossPressedPrimary; + final Function(int index, String filePath)? onCrossPressedSecondary; + final int? index; + final bool isReview; const BuildImageContainer({ Key? key, required this.file, - required this.onCrossPressed, + this.onCrossPressedPrimary, + this.onCrossPressedSecondary, + this.index, + this.isReview = false, }) : super(key: key); @override @@ -37,8 +97,8 @@ class BuildImageContainer extends StatelessWidget { return Stack( children: [ Container( - height: 80, - width: 80, + height: 90, + width: 90, child: Stack( children: [ Image.file( @@ -47,16 +107,22 @@ class BuildImageContainer extends StatelessWidget { height: 72, width: 70, ).paddingAll(8), - Align( - alignment: Alignment.topRight, - child: MyAssets.closeWithOrangeBg.buildSvg( - fit: BoxFit.fill, - height: 25, - width: 25, - ), - ).onPress(() { - onCrossPressed(file.path); - }) + !isReview + ? Align( + alignment: Alignment.topRight, + child: MyAssets.closeWithOrangeBg.buildSvg( + fit: BoxFit.fill, + height: 30, + width: 30, + ), + ).onPress(() { + if (onCrossPressedPrimary == null) { + onCrossPressedSecondary!(index!, file.path); + return; + } + onCrossPressedPrimary!(file.path); + }) + : SizedBox() ], )), ], diff --git a/lib/widgets/common_widgets/categories_list.dart b/lib/widgets/common_widgets/categories_list.dart index 5ddbc0a..47d7fbc 100644 --- a/lib/widgets/common_widgets/categories_list.dart +++ b/lib/widgets/common_widgets/categories_list.dart @@ -1,13 +1,14 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; +class FiltersList extends StatelessWidget { + final List filterList; + final Function(int) onFilterTapped; + final bool needLeftPadding; -class CategoriesList extends StatelessWidget { - // We will pass a list here! - final String name; - final Function() onTapped; - const CategoriesList({Key? key, required this.name, required this.onTapped}) : super(key: key); + const FiltersList({Key? key, required this.filterList, this.needLeftPadding = true, required this.onFilterTapped}) : super(key: key); @override Widget build(BuildContext context) { @@ -15,27 +16,29 @@ class CategoriesList extends StatelessWidget { height: 37, width: double.infinity, child: ListView.builder( - padding: const EdgeInsets.only(left: 12), - itemCount: 20, + padding: EdgeInsets.only(left: needLeftPadding ? 12 : 0), + itemCount: filterList.length, scrollDirection: Axis.horizontal, itemBuilder: (BuildContext context, int index) { return InkWell( - onTap: onTapped, + onTap: () { + onFilterTapped(index); + }, child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 8), margin: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( - color: index < 1 ? MyColors.darkIconColor : null, + color: filterList[index].isSelected ? MyColors.darkIconColor : null, border: Border.all( - color: index < 1 ? MyColors.darkIconColor : MyColors.primaryColor, + color: filterList[index].isSelected ? MyColors.darkIconColor : MyColors.primaryColor, width: 2, ), ), - child: name.toText( - fontSize: 12, - color: index < 1 ? MyColors.white : null, - ), + child: filterList[index].title.toText( + fontSize: 12, + color: filterList[index].isSelected ? MyColors.white : null, + ), ), ); }), diff --git a/lib/widgets/common_widgets/time_slots.dart b/lib/widgets/common_widgets/time_slots.dart new file mode 100644 index 0000000..e9d285c --- /dev/null +++ b/lib/widgets/common_widgets/time_slots.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/theme/colors.dart'; +class BuildTimeSlots extends StatelessWidget { + const BuildTimeSlots({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 37, + width: double.infinity, + child: ListView.builder( + itemCount: 20, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context, int index) { + return InkWell( + onTap: () {}, + child: Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(right: 8), + width: 50, + decoration: BoxDecoration( + color: index < 1 ? MyColors.darkIconColor : null, + border: Border.all( + color: index < 1 ? MyColors.darkIconColor : MyColors.primaryColor, + width: 2, + ), + ), + child: "09:00".toText( + fontSize: 12, + color: index < 1 ? MyColors.white : null, + ), + ), + ); + }), + ); + } +} diff --git a/lib/widgets/common_widgets/view_all_widget.dart b/lib/widgets/common_widgets/view_all_widget.dart index b46d67c..724bfaa 100644 --- a/lib/widgets/common_widgets/view_all_widget.dart +++ b/lib/widgets/common_widgets/view_all_widget.dart @@ -1,13 +1,14 @@ - import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/theme/colors.dart'; class ViewAllWidget extends StatelessWidget { final String title; final String subTitle; + final Function() onSubtitleTapped; - const ViewAllWidget({Key? key, required this.title, required this.subTitle}) : super(key: key); + const ViewAllWidget({Key? key, required this.title, required this.subTitle, required this.onSubtitleTapped}) : super(key: key); @override Widget build(BuildContext context) { @@ -17,11 +18,14 @@ class ViewAllWidget extends StatelessWidget { child: Row( children: [ Expanded(child: title.toText(isBold: true, fontSize: 18)), - subTitle.toText( - fontSize: 11, - isBold: true, - color: MyColors.primaryColor, - textDecoration: TextDecoration.underline, + InkWell( + onTap: onSubtitleTapped, + child: subTitle.toText( + fontSize: 11, + isBold: true, + color: MyColors.primaryColor, + textDecoration: TextDecoration.underline, + ), ) ], ), diff --git a/lib/widgets/dropdown/dropdow_field.dart b/lib/widgets/dropdown/dropdow_field.dart index b80f426..5457372 100644 --- a/lib/widgets/dropdown/dropdow_field.dart +++ b/lib/widgets/dropdown/dropdow_field.dart @@ -8,8 +8,9 @@ class DropValue { int id; String value; String subValue; + bool? isEnabled; - DropValue(this.id, this.value, this.subValue); + DropValue(this.id, this.value, this.subValue, {this.isEnabled = true}); bool operator ==(o) => o is DropValue && o.value == value && o.id == id; } @@ -56,8 +57,8 @@ class _DropdownFieldState extends State { iconEnabledColor: borderColor, iconDisabledColor: borderColor, isExpanded: true, - style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w600), - hint: (widget.hint ?? "").toText(color: borderColor, fontSize: 12), + style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w600, fontSize: 15), + hint: (widget.hint ?? "").toText(color: borderColor, fontSize: 15), underline: Container(height: 0), onChanged: (DropValue? newValue) { setState(() { @@ -69,7 +70,8 @@ class _DropdownFieldState extends State { (DropValue value) { return DropdownMenuItem( value: value, - child: value.value.toText(fontSize: 12), + enabled: value.isEnabled ?? true, + child: value.value.toText(fontSize: 15, color: value.isEnabled == false ? Colors.black38 : null), ); }, ).toList(), diff --git a/lib/widgets/extensions/extensions_widget.dart b/lib/widgets/extensions/extensions_widget.dart index 3c2f3f9..b86c10c 100644 --- a/lib/widgets/extensions/extensions_widget.dart +++ b/lib/widgets/extensions/extensions_widget.dart @@ -354,3 +354,105 @@ extension LocaleSetup on MultiProvider { extension WidgetExtensions on Widget { Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); } + +extension FormatDate on String { + /// get month by + /// [month] convert month number in to month name + /// get month by + /// [month] convert month number in to month name in Arabic + static String getMonthArabic(int month) { + switch (month) { + case 1: + return "يناير"; + case 2: + return " فبراير"; + case 3: + return "مارس"; + case 4: + return "أبريل"; + case 5: + return "مايو"; + case 6: + return "يونيو"; + case 7: + return "يوليو"; + case 8: + return "أغسطس"; + case 9: + return "سبتمبر"; + case 10: + return " اكتوبر"; + case 11: + return " نوفمبر"; + case 12: + return "ديسمبر"; + default: + return ""; + } + } + + static String getMonth(int month) { + switch (month) { + case 1: + return "January"; + case 2: + return "February"; + case 3: + return "March"; + case 4: + return "April"; + case 5: + return "May"; + case 6: + return "June"; + case 7: + return "July"; + case 8: + return "August"; + case 9: + return "September"; + case 10: + return "October"; + case 11: + return "November"; + case 12: + return "December"; + default: + return ""; + } + } + + String getTimeAgo() { + 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))}"; + } +} + +extension DateTimeConversions on DateTime { + String getTimeAgo({bool numericDates = true}) { + final date2 = DateTime.now(); + final difference = date2.difference(this); + + if ((difference.inDays / 7).floor() >= 1) { + return (numericDates) ? '1 week ago' : 'Last week'; + } else if (difference.inDays >= 2) { + return '${difference.inDays} days ago'; + } else if (difference.inDays >= 1) { + return (numericDates) ? '1 day ago' : 'Yesterday'; + } else if (difference.inHours >= 2) { + return '${difference.inHours} hours ago'; + } else if (difference.inHours >= 1) { + return (numericDates) ? '1 hour ago' : 'An hour ago'; + } else if (difference.inMinutes >= 2) { + return '${difference.inMinutes} minutes ago'; + } else if (difference.inMinutes >= 1) { + return (numericDates) ? '1 minute ago' : 'A minute ago'; + } else if (difference.inSeconds >= 3) { + return '${difference.inSeconds} seconds ago'; + } else { + return 'Just now'; + } + } +}