From dfa57dbe55c404c196dd1e1c2ed0d4c0071fbc55 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Wed, 21 Aug 2024 18:19:06 +0300 Subject: [PATCH] Added Damage Pictures in ad_detail_view and extend edit ad --- assets/langs/ar-SA.json | 4 +- assets/langs/en-US.json | 4 +- lib/classes/consts.dart | 4 + lib/config/routes.dart | 10 +- lib/extensions/string_extensions.dart | 2 +- lib/generated/codegen_loader.g.dart | 8 +- lib/generated/locale_keys.g.dart | 2 + lib/main.dart | 167 ++----- .../advertisment_models/ad_details_model.dart | 10 +- lib/models/general_models/widgets_models.dart | 5 + .../branch_detail_model.dart | 37 +- .../branch_review_model.dart | 36 ++ .../profile/branch.dart | 48 +- .../provider_model.dart | 19 - .../provider_profile_model.dart | 22 +- lib/models/requests_models/request_model.dart | 2 +- lib/repositories/appointment_repo.dart | 15 + lib/repositories/branch_repo.dart | 41 ++ lib/repositories/request_repo.dart | 38 +- lib/theme/colors.dart | 2 + lib/view_models/ad_view_model.dart | 29 +- lib/view_models/appointments_view_model.dart | 90 ++-- lib/view_models/chat_view_model.dart | 4 +- lib/view_models/requests_view_model.dart | 29 +- .../ad_duration_container.dart | 9 +- .../ad_review_containers.dart | 8 +- .../damage_parts_container.dart | 10 +- .../vehicle_details_container.dart | 4 +- .../ads_buyer_chats_list_view.dart | 95 ---- .../advertisement/ads_buyer_chats_view.dart | 118 +++++ lib/views/advertisement/ads_detail_view.dart | 414 ++++++++++-------- .../ad_damage_parts_selection_sheet.dart | 143 ++++++ .../ad_duration_selection_sheet.dart} | 47 +- .../ad_special_service_sheet.dart} | 14 +- .../ads_damage_part_pictures_sheet.dart | 91 ++++ .../ads_images_corousel_widget.dart} | 6 +- .../ads_list_widget.dart} | 4 +- .../create_ad_progress_steps_widget.dart} | 8 +- .../damage_pictures_bottom_sheet.dart | 110 +++++ .../network_images_container_widget.dart} | 0 .../picked_images_container_widget.dart} | 19 +- lib/views/advertisement/create_ad_view.dart | 5 +- .../advertisement/select_ad_type_view.dart | 48 +- .../book_appointment_schedules_view.dart | 12 +- .../book_appointment_services_view.dart | 83 +--- .../common_appointment_slider_widget.dart | 5 +- lib/views/common_fragments/ads_fragment.dart | 14 +- .../my_requests_fragment.dart | 2 +- lib/views/requests/create_request_page.dart | 2 +- lib/views/requests/widget/request_item.dart | 18 +- lib/widgets/common_widgets/app_bar.dart | 133 +++--- .../custom_add_button_widget.dart} | 0 52 files changed, 1183 insertions(+), 867 deletions(-) create mode 100644 lib/models/provider_branches_models/branch_review_model.dart delete mode 100644 lib/views/advertisement/ads_buyer_chats_list_view.dart create mode 100644 lib/views/advertisement/ads_buyer_chats_view.dart create mode 100644 lib/views/advertisement/bottom_sheets/ad_damage_parts_selection_sheet.dart rename lib/views/advertisement/{ad_duration_selection_sheet_content.dart => bottom_sheets/ad_duration_selection_sheet.dart} (77%) rename lib/views/advertisement/{bottom_sheet_content.dart => bottom_sheets/ad_special_service_sheet.dart} (95%) create mode 100644 lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart rename lib/views/advertisement/{ads_images_slider.dart => components/ads_images_corousel_widget.dart} (91%) rename lib/views/advertisement/{ads_list.dart => components/ads_list_widget.dart} (99%) rename lib/views/advertisement/{create_ad_progress_steps.dart => components/create_ad_progress_steps_widget.dart} (82%) create mode 100644 lib/views/advertisement/components/damage_pictures_bottom_sheet.dart rename lib/views/advertisement/{network_images_container.dart => components/network_images_container_widget.dart} (100%) rename lib/views/advertisement/{picked_images_container.dart => components/picked_images_container_widget.dart} (89%) rename lib/{views/advertisement/custom_add_button.dart => widgets/common_widgets/custom_add_button_widget.dart} (100%) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 5aeb8dc..32b9472 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -580,5 +580,7 @@ "acceptOfferConfirmation": "هل تريد قبول هذا العرض؟", "acceptOfferConfirmationMessage": "سيتم قبول هذا العرض وستدفع المبلغ المطلوب للمشتري في وقت معين وإلا سيتم إلغاء هذا العرض.", "noUpcomingAppointments": "لا يوجد موعد قادم متاح", - "addNewAppointment": "إضافة موعد جديد" + "addNewAppointment": "إضافة موعد جديد", + "myNearbyBranches": "فروعي القريبة", + "myRecentBranches": "فروعي الأخيرة" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 2b85fb4..5698e44 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -581,5 +581,7 @@ "whendoyouWanttoRenew": "When do you want to renew", "renewVar": "Renew", "noUpcomingAppointments": "No Upcoming Appointment Available.", - "addNewAppointment": "Add New Appointment" + "addNewAppointment": "Add New Appointment", + "myNearbyBranches": "My Nearby Branches", + "myRecentBranches": "My Recent Branches" } \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 500f758..41577b2 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -55,6 +55,9 @@ class ApiConsts { static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get"; static String serviceProviderDDLGet = "${baseUrlServices}api/ServiceProviders/ServiceProviderDDL_Get"; static String GetAllNearBranches = "${baseUrlServices}api/ServiceProviders/ServiceProviderBranchDetail_Get"; + static String getMyRecentBranches = "${baseUrlServices}api/ServiceProviders/ServiceProviderBranchRecent_Get"; + static String getBranchRatings = "${baseUrlServices}api/ServiceProviders/BranchRating_Get"; + static String createBranchRatings = "${baseUrlServices}api/ServiceProviders/BranchRating_Create"; //Appointment APIs static String serviceProvidersAppointmentGet = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointment_Get"; @@ -153,6 +156,7 @@ class ApiConsts { static String getRequestOffers = "${baseUrlServices}api/RequestManagement/ReqOffer_Get"; static String updateRequestOffer = "${baseUrlServices}api/RequestManagement/RequestOffer_UpdateStatus"; static String requestOffersSpsGet = "${baseUrlServices}api/RequestManagement/Request_OfferSPs_Get"; + static String getServiceRequestsForProvider = "${baseUrlServices}api/RequestManagement/Request_ServiceProvider"; //Chat static String chatHubUrl = "$baseUrlServices/McHub"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 8ef24cb..9192a9c 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -4,7 +4,7 @@ import 'package:mc_common_app/models/requests_models/provider_offers_model.dart' import 'package:mc_common_app/models/requests_models/request_model.dart'; import 'package:mc_common_app/models/user_models/register_user.dart'; import 'package:mc_common_app/utils/enums.dart'; -import 'package:mc_common_app/views/advertisement/ads_buyer_chats_list_view.dart'; +import 'package:mc_common_app/views/advertisement/ads_buyer_chats_view.dart'; import 'package:mc_common_app/views/advertisement/ads_detail_view.dart'; import 'package:mc_common_app/views/advertisement/ads_filter_view.dart'; import 'package:mc_common_app/views/advertisement/create_ad_view.dart'; @@ -83,9 +83,9 @@ class AppRoutes { static const String paymentMethodsView = "/paymentMethodsView"; //Customer APP: Provider & Services - static const String branchDetailPage = "/branchDetailPage"; + static const String branchDetailView = "/branchDetailPage"; static const String branchSearchFilterPage = "/branchSearchFilterPage"; - static const String providerProfilePage = "/providerProfilePage"; + static const String providerProfileView = "/providerProfilePage"; // Subscriptions static const String mySubscriptionsPage = "/mySubscriptionsPage"; @@ -145,10 +145,10 @@ class AppRoutes { AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel), AppRoutes.createAdView: (context) => const CreateAdView(), AppRoutes.adsFilterView: (context) => const AdsFilterView(), - AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(isProvider: ModalRoute.of(context)!.settings.arguments as bool), + AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(arguments: ModalRoute.of(context)!.settings.arguments as List), AppRoutes.chatView: (context) => ChatView(chatViewArguments: ModalRoute.of(context)!.settings.arguments as ChatViewArguments), AppRoutes.offersListPage: (context) => OfferListPage(offerListPageArguments: ModalRoute.of(context)!.settings.arguments as OfferListPageArguments), - AppRoutes.adsBuyerChatsListView: (context) => AdsBuyerChatsListView(buyersListViewArguments: ModalRoute.of(context)!.settings.arguments as List), + AppRoutes.adsBuyerChatsListView: (context) => AdsBuyerChatsView(buyersListViewArguments: ModalRoute.of(context)!.settings.arguments as List), AppRoutes.createRequestPage: (context) => const CreateRequestPage(), AppRoutes.settingOptionsFaqs: (context) => const SettingOptionsFAQs(), AppRoutes.settingOptionsInviteFriends: (context) => const SettingOptionsInviteFriends(), diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 8913904..bacf8a1 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -12,7 +12,7 @@ extension EmailValidator on String { bool isUnderLine = false, bool isItalic = false, TextDecoration? textDecoration, - double letterSpacing = -0.4, + double letterSpacing = 0, TextAlign? textAlign, FontWeight? fontWeight, double? height, diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index d52c675..9f71ab2 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -596,7 +596,9 @@ class CodegenLoader extends AssetLoader{ "acceptOfferConfirmation": "هل تريد قبول هذا العرض؟", "acceptOfferConfirmationMessage": "سيتم قبول هذا العرض وستدفع المبلغ المطلوب للمشتري في وقت معين وإلا سيتم إلغاء هذا العرض.", "noUpcomingAppointments": "لا يوجد موعد قادم متاح", - "addNewAppointment": "إضافة موعد جديد" + "addNewAppointment": "إضافة موعد جديد", + "myNearbyBranches": "فروعي القريبة", + "myRecentBranches": "فروعي الأخيرة" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1181,7 +1183,9 @@ static const Map en_US = { "whendoyouWanttoRenew": "When do you want to renew", "renewVar": "Renew", "noUpcomingAppointments": "No Upcoming Appointment Available.", - "addNewAppointment": "Add New Appointment" + "addNewAppointment": "Add New Appointment", + "myNearbyBranches": "My Nearby Branches", + "myRecentBranches": "My Recent Branches" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 883de6a..4c9ac7e 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -560,5 +560,7 @@ abstract class LocaleKeys { static const acceptOfferConfirmationMessage = 'acceptOfferConfirmationMessage'; static const noUpcomingAppointments = 'noUpcomingAppointments'; static const addNewAppointment = 'addNewAppointment'; + static const myNearbyBranches = 'myNearbyBranches'; + static const myRecentBranches = 'myRecentBranches'; } diff --git a/lib/main.dart b/lib/main.dart index 1eae988..c7e6f71 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,95 +1,34 @@ import 'dart:io'; - -import 'package:easy_localization/easy_localization.dart'; - -import 'package:flutter/material.dart'; -import 'package:mc_common_app/theme/app_theme.dart'; import 'package:logger/logger.dart'; -import 'package:provider/provider.dart'; -import 'package:provider/single_child_widget.dart'; -import 'package:sizer/sizer.dart'; - -//testing push -final navigatorKey = GlobalKey(); - -Logger logger = Logger( - printer: PrettyPrinter(printEmojis: false, colors: true,printTime: false), -); - -class MyHttpOverrides extends HttpOverrides { - @override - HttpClient createHttpClient(SecurityContext? context) { - return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true; - } -} - -Future main() async { - WidgetsFlutterBinding.ensureInitialized(); - - await EasyLocalization.ensureInitialized(); - // AppState().setPostParamsInitConfig(); - HttpOverrides.global = MyHttpOverrides(); - runApp( - EasyLocalization( - supportedLocales: const [ - Locale('en', 'US'), - Locale('ar', 'SA'), - ], - path: 'resources', - // assetLoader: const CodegenLoader(), - child: MultiProvider( - providers: const [ - // ChangeNotifierProvider( - // create: (_) => LoginProviderModel(), - // ), - ], - child: const MyApp(), - ), - ), - ); -} - -// todo terminal command to genertate translation files -// flutter pub run easy_localization:generate --source-dir ./assets/langs -// todo terminal command to genertate translation keys -// flutter pub run easy_localization:generate --source-dir ./assets/langs -f keys -o locale_keys.g.dart -// command to generate languages data from json +Logger logger = Logger(printer: PrettyPrinter(printEmojis: false, colors: true, printTime: false)); -class MyApp extends StatelessWidget { - const MyApp({super.key}); +// class MyHttpOverrides extends HttpOverrides { +// @override +// HttpClient createHttpClient(SecurityContext? context) { +// return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true; +// } +// } - @override - Widget build(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - return Sizer( - builder: ( - BuildContext context, - Orientation orientation, - DeviceType deviceType, - ) { - List> delegates = context.localizationDelegates; - // AppState().setPostParamsModel( - // PostParamsModel( - // languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, - // ), - // ); - return MaterialApp( - // key: navigatorKey, - navigatorKey: navigatorKey, - theme: AppTheme.getTheme( - isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar", - ), - debugShowCheckedModeBanner: false, - localizationsDelegates: delegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - ); - }, - ); - }); - } -} +// Future main() async { +// WidgetsFlutterBinding.ensureInitialized(); +// +// await EasyLocalization.ensureInitialized(); +// // AppState().setPostParamsInitConfig(); +// HttpOverrides.global = MyHttpOverrides(); +// +// runApp( +// EasyLocalization( +// supportedLocales: const [ +// Locale('en', 'US'), +// Locale('ar', 'SA'), +// ], +// path: 'resources', +// // assetLoader: const CodegenLoader(), +// child: const MyApp(), +// ), +// ); +// } // class MyApp extends StatelessWidget { // const MyApp({super.key}); @@ -104,13 +43,9 @@ class MyApp extends StatelessWidget { // DeviceType deviceType, // ) { // List> delegates = context.localizationDelegates; -// // AppState().setPostParamsModel( -// // PostParamsModel( -// // languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, -// // ), -// // ); // return MaterialApp( // // key: navigatorKey, +// navigatorKey: navigatorKey, // theme: AppTheme.getTheme( // isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar", // ), @@ -124,45 +59,9 @@ class MyApp extends StatelessWidget { // }); // } // } -// -// // class MyApp extends StatelessWidget { -// // MyApp({super.key}) { -// // AppDependencies.addDependencies(); -// // AppState = Injector.appInstance.get(); -// // // AppState.setPostParamsInitConfig(); -// // } -// // -// // @override -// // Widget build(BuildContext context) { -// // return LayoutBuilder(builder: (context, constraints) { -// // return Sizer( -// // builder: ( -// // BuildContext context, -// // Orientation orientation, -// // DeviceType deviceType, -// // ) { -// // SizeConfig().init(constraints, orientation); -// // List> delegates = context.localizationDelegates; -// // // AppState().setPostParamsModel( -// // // PostParamsModel( -// // // languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, -// // // ), -// // // ); -// // return MaterialApp( -// // // key: navigatorKey, -// // navigatorKey: navigatorKey, -// // theme: AppTheme.getTheme( -// // EasyLocalization.of(context)?.locale.languageCode == "ar", -// // ), -// // debugShowCheckedModeBanner: false, -// // localizationsDelegates: delegates, -// // supportedLocales: context.supportedLocales, -// // locale: context.locale, -// // initialRoute: AppRoutes.initialPage, -// // routes: AppRoutes.routes, -// // ); -// // }, -// // ); -// // }); -// // } -// // } + +// todo terminal command to genertate translation files +// flutter pub run easy_localization:generate --source-dir ./assets/langs +// todo terminal command to genertate translation keys +// flutter pub run easy_localization:generate --source-dir ./assets/langs -f keys -o locale_keys.g.dart +// command to generate languages data from json diff --git a/lib/models/advertisment_models/ad_details_model.dart b/lib/models/advertisment_models/ad_details_model.dart index 0b1b304..c9f785e 100644 --- a/lib/models/advertisment_models/ad_details_model.dart +++ b/lib/models/advertisment_models/ad_details_model.dart @@ -44,6 +44,7 @@ class AdDetailsModel { bool? isReservedByMe; String? phoneNo; String? whatsAppNo; + String? adOwnerName; CreatedByRoleEnum? createdByRoleEnum; List? adMessages; @@ -84,6 +85,7 @@ class AdDetailsModel { this.isReservedByMe, this.phoneNo, this.whatsAppNo, + this.adOwnerName, this.createdByRoleEnum, this.modifiedOn, this.adMessages, @@ -131,13 +133,11 @@ class AdDetailsModel { reservePrice = json['reservePrice']; isMCHandled = json['isMCHandled']; modifiedOn = json['modifiedOn']; - whatsAppNo = json['phoneNo']; - modifiedOn = json['whatsAppNo']; - // adPostStatus = AdPostStatus.expired; + phoneNo = json['phoneNo']; + whatsAppNo = json['whatsAppNo']; + adOwnerName = json['adOwnerName'] ?? ""; adPostStatus = (json['statusID'] as int).toAdPostEnum(); - //TODO: THIS ID SHOULD BE UPDATED! adReserveStatus = AdReserveStatus.defaultStatus; - // createdByRoleEnum = CreatedByRoleEnum.admin; createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum(); isMyAd = isMyAds; isReservedByMe = false; diff --git a/lib/models/general_models/widgets_models.dart b/lib/models/general_models/widgets_models.dart index 52ef1fb..9972299 100644 --- a/lib/models/general_models/widgets_models.dart +++ b/lib/models/general_models/widgets_models.dart @@ -18,6 +18,11 @@ class SelectionModel { this.selectedId = 0, this.itemPrice = "", }); + + @override + String toString() { + return 'SelectionModel{selectedOption: $selectedOption, selectedId: $selectedId, errorValue: $errorValue, itemPrice: $itemPrice}'; + } } class TimeSlotModel { diff --git a/lib/models/provider_branches_models/branch_detail_model.dart b/lib/models/provider_branches_models/branch_detail_model.dart index 7748a81..ba0d747 100644 --- a/lib/models/provider_branches_models/branch_detail_model.dart +++ b/lib/models/provider_branches_models/branch_detail_model.dart @@ -19,12 +19,14 @@ class BranchDetailModel { final String? closeTime; final BranchStatusEnum? branchStatus; final int? statusId; - final dynamic statusText; + final String? statusText; + final double? branchRateAvg; final List? branchServices; List? categories; int? countryID; String? countryName; bool isExpanded; + bool? isFavorite; BranchDetailModel({ this.id, @@ -41,17 +43,18 @@ class BranchDetailModel { this.openTime, this.closeTime, this.branchStatus, + this.branchRateAvg, this.statusId, this.statusText, this.branchServices, this.categories, this.countryID, this.countryName, + this.isFavorite, required this.isExpanded, }); - factory BranchDetailModel.fromJson(Map json) => - BranchDetailModel( + factory BranchDetailModel.fromJson(Map json) => BranchDetailModel( id: json["id"], serviceProviderId: json["serviceProviderID"], serviceProviderName: json["serviceProviderName"], @@ -65,33 +68,13 @@ class BranchDetailModel { distanceKm: json["distanceKM"]?.toDouble(), openTime: json["openTime"], closeTime: json["closeTime"], - branchStatus: json.containsKey("branchStatus")?(json['branchStatus'] as int).toBranchStatusEnum():null, + branchStatus: json.containsKey("branchStatus") ? (json['branchStatus'] as int).toBranchStatusEnum() : null, statusId: json["branchStatus"], statusText: json["statusText"], - branchServices: json["serviceProviderServices"] == null ? [] : List< - ServiceModel>.from(json["serviceProviderServices"]!.map((x) => - ServiceModel.fromJson(x))), + branchRateAvg: json["branchRateAvg"], + branchServices: json["serviceProviderServices"] == null ? [] : List.from(json["serviceProviderServices"]!.map((x) => ServiceModel.fromJson(x))), categories: [], isExpanded: false, + isFavorite: false, ); - - Map toJson() => - { - "id": id, - "serviceProviderID": serviceProviderId, - "serviceProviderName": serviceProviderName, - "branchName": branchName, - "branchDescription": branchDescription, - "cityID": cityId, - "address": address, - "latitude": latitude, - "longitude": longitude, - "distanceKM": distanceKm, - "openTime": openTime, - "closeTime": closeTime, - "status": statusId, - "statusText": statusText, - "serviceProviderServices": branchServices == null ? [] : List< - dynamic>.from(branchServices!.map((x) => x.toJson())), - }; } diff --git a/lib/models/provider_branches_models/branch_review_model.dart b/lib/models/provider_branches_models/branch_review_model.dart new file mode 100644 index 0000000..b9f7589 --- /dev/null +++ b/lib/models/provider_branches_models/branch_review_model.dart @@ -0,0 +1,36 @@ +class BranchRatingModel { + int? id; + String? title; + String? review; + int? ratNo; + int? serviceProviderBranchID; + String? serviceProviderBranchName; + int? customerID; + String? customerName; + + BranchRatingModel({this.id, this.title, this.review, this.ratNo, this.serviceProviderBranchID, this.serviceProviderBranchName, this.customerID, this.customerName}); + + BranchRatingModel.fromJson(Map json) { + id = json['id']; + title = json['title']; + review = json['review']; + ratNo = json['ratNo']; + serviceProviderBranchID = json['serviceProviderBranchID']; + serviceProviderBranchName = json['serviceProviderBranchName']; + customerID = json['customerID']; + customerName = json['customerName']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['title'] = title; + data['review'] = review; + data['ratNo'] = ratNo; + data['serviceProviderBranchID'] = serviceProviderBranchID; + data['serviceProviderBranchName'] = serviceProviderBranchName; + data['customerID'] = customerID; + data['customerName'] = customerName; + return data; + } +} diff --git a/lib/models/provider_branches_models/profile/branch.dart b/lib/models/provider_branches_models/profile/branch.dart index cc7d68a..8c0cac4 100644 --- a/lib/models/provider_branches_models/profile/branch.dart +++ b/lib/models/provider_branches_models/profile/branch.dart @@ -22,17 +22,17 @@ class Branch { String? message; factory Branch.fromJson(Map json) => Branch( - totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : List.from(json["data"].map((x) => BranchData.fromJson(x))), - messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], - message: json["message"] == null ? null : json["message"], + messageStatus: json["messageStatus"], + message: json["message"], ); Map toJson() => { - "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "totalItemsCount": totalItemsCount, "data": data == null ? null : List.from(data!.map((x) => x.toJson())), - "messageStatus": messageStatus == null ? null : messageStatus, - "message": message == null ? null : message, + "messageStatus": messageStatus, + "message": message, }; } @@ -60,26 +60,26 @@ class BranchData { int? status; factory BranchData.fromJson(Map json) => BranchData( - id: json["id"] == null ? null : json["id"], - serviceProviderId: json["serviceProviderID"] == null ? null : json["serviceProviderID"], - branchName: json["branchName"] == null ? null : json["branchName"], - branchDescription: json["branchDescription"] == null ? null : json["branchDescription"], - cityId: json["cityID"] == null ? null : json["cityID"], - address: json["address"] == null ? null : json["address"], - latitude: json["latitude"] == null ? null : json["latitude"], - longitude: json["longitude"] == null ? null : json["longitude"], - status: json["status"] == null ? null : json["status"], + id: json["id"], + serviceProviderId: json["serviceProviderID"], + branchName: json["branchName"], + branchDescription: json["branchDescription"], + cityId: json["cityID"], + address: json["address"], + latitude: json["latitude"], + longitude: json["longitude"], + status: json["status"], ); Map toJson() => { - "id": id == null ? null : id, - "serviceProviderID": serviceProviderId == null ? null : serviceProviderId, - "branchName": branchName == null ? null : branchName, - "branchDescription": branchDescription == null ? null : branchDescription, - "cityID": cityId == null ? null : cityId, - "address": address == null ? null : address, - "latitude": latitude == null ? null : latitude, - "longitude": longitude == null ? null : longitude, - "status": status == null ? null : status, + "id": id, + "serviceProviderID": serviceProviderId, + "branchName": branchName, + "branchDescription": branchDescription, + "cityID": cityId, + "address": address, + "latitude": latitude, + "longitude": longitude, + "status": status, }; } diff --git a/lib/models/provider_branches_models/provider_model.dart b/lib/models/provider_branches_models/provider_model.dart index f7a8c96..0ec0ee2 100644 --- a/lib/models/provider_branches_models/provider_model.dart +++ b/lib/models/provider_branches_models/provider_model.dart @@ -8,8 +8,6 @@ import 'package:mc_common_app/models/provider_branches_models/branch_detail_mode ProviderModel branch2FromJson(String str) => ProviderModel.fromJson(json.decode(str)); -String branch2ToJson(ProviderModel data) => json.encode(data.toJson()); - class ProviderModel { ProviderModel({ this.messageStatus, @@ -29,13 +27,6 @@ class ProviderModel { data: json["data"] == null ? null : ProviderModelData.fromJson(json["data"]), message: json["message"], ); - - Map toJson() => { - "messageStatus": messageStatus, - "totalItemsCount": totalItemsCount, - "data": data == null ? null : data!.toJson(), - "message": message, - }; } class ProviderModelData { @@ -72,16 +63,6 @@ class ProviderModelData { userId: json["userID"], serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchDetailModel.fromJson(x))), ); - - Map toJson() => { - "id": id, - "companyName": companyName, - "companyDescription": companyDescription, - "allDocStatus": allDocStatus, - "isValidSubscription": isValidSubscription, - "userID": userId, - "serviceProviderBranch": serviceProviderBranch == null ? null : List.from(serviceProviderBranch!.map((x) => x.toJson())), - }; } class ProviderBasicDataModel { diff --git a/lib/models/provider_branches_models/provider_profile_model.dart b/lib/models/provider_branches_models/provider_profile_model.dart index 10a845f..f32879d 100644 --- a/lib/models/provider_branches_models/provider_profile_model.dart +++ b/lib/models/provider_branches_models/provider_profile_model.dart @@ -1,10 +1,5 @@ -// To parse this JSON data, do -// -// final branch2 = branch2FromJson(jsonString); - import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; - class ProviderProfileModel { ProviderProfileModel({ this.id, @@ -16,6 +11,7 @@ class ProviderProfileModel { this.userId, this.serviceProviderBranch, this.countryID, + this.isFavorite, }); final int? id; @@ -25,10 +21,12 @@ class ProviderProfileModel { final String? companyDescription; final int? allDocStatus; final bool? isValidSubscription; + final bool? isFavorite; final String? userId; final List? serviceProviderBranch; - factory ProviderProfileModel.fromJson(Map json) => ProviderProfileModel( + factory ProviderProfileModel.fromJson(Map json) => + ProviderProfileModel( id: json["id"], companyName: json["companyName"], countryName: json["countryName"], @@ -37,17 +35,7 @@ class ProviderProfileModel { allDocStatus: json["allDocStatus"], isValidSubscription: json["isValidSubscription"], userId: json["userID"], + isFavorite: json["isFavorite"] ?? false, serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchDetailModel.fromJson(x))), ); - - Map toJson() => { - "id": id, - "companyName": companyName, - "companyDescription": companyDescription, - "allDocStatus": allDocStatus, - "isValidSubscription": isValidSubscription, - "userID": userId, - "serviceProviderBranch": serviceProviderBranch == null ? null : List.from(serviceProviderBranch!.map((x) => x.toJson())), - }; } - diff --git a/lib/models/requests_models/request_model.dart b/lib/models/requests_models/request_model.dart index ed1d4cc..3a0d5c9 100644 --- a/lib/models/requests_models/request_model.dart +++ b/lib/models/requests_models/request_model.dart @@ -86,7 +86,7 @@ class RequestModel { cityName: json["cityName"], vehicleTypeName: json["vehicleTypeName"], countryName: json["countryName"], - customerName: json["customerName"], + customerName: json["customerName"] ?? "", customerID: json["customerUserID"], serviceProviders: json["serviceProviders"], offerCount: json["offerCount"], diff --git a/lib/repositories/appointment_repo.dart b/lib/repositories/appointment_repo.dart index 1991fef..bbc36f2 100644 --- a/lib/repositories/appointment_repo.dart +++ b/lib/repositories/appointment_repo.dart @@ -49,6 +49,8 @@ abstract class AppointmentRepo { Future createServiceAppointment({required List schedules, required int serviceProviderID}); Future cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction}); + + Future addProviderToFavourite({required int providerID}); } class AppointmentRepoImp implements AppointmentRepo { @@ -250,4 +252,17 @@ class AppointmentRepoImp implements AppointmentRepo { String t = appState.getUser.data!.accessToken ?? ""; return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createMergeAppointment, map, token: t); } + + @override + Future addProviderToFavourite({required int providerID}) async { + final customerID = appState.getUser.data!.userInfo!.customerId; + final parameters = {"providerID": providerID, "customerID": customerID}; + GenericRespModel adsGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.createBranchRatings, + parameters, + token: appState.getUser.data!.accessToken, + ); + return adsGenericModel; + } } diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index 566de9c..01f5862 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -9,6 +9,7 @@ import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/branch_review_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/branch.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/document.dart'; @@ -73,6 +74,12 @@ abstract class BranchRepo { double? latitude, double? longitude, }); + + Future> getMyRecentBranchesWithServices(); + + Future> getBranchRatings({required int serviceProviderBranchID}); + + Future submitBranchRatings({required int serviceProviderBranchID, required String title, required String review, required double ratingNo}); } class BranchRepoImp implements BranchRepo { @@ -273,6 +280,13 @@ class BranchRepoImp implements BranchRepo { return nearBranches; } + @override + Future> getMyRecentBranchesWithServices() async { + GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.getMyRecentBranches, token: appState.getUser.data!.accessToken); + List recentBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); + return recentBranches; + } + @override Future> getServiceItems(int serviceId) async { var queryParameters = { @@ -345,4 +359,31 @@ class BranchRepoImp implements BranchRepo { List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); return nearBranches; } + + @override + Future> getBranchRatings({required int serviceProviderBranchID}) async { + var postParams = {"ServiceProviderBranchID": serviceProviderBranchID.toString()}; + + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getBranchRatings, + token: appState.getUser.data!.accessToken, + queryParameters: postParams, + ); + List branchRatings = List.generate(adsGenericModel.data.length, (index) => BranchRatingModel.fromJson(adsGenericModel.data[index])); + return branchRatings; + } + + @override + Future submitBranchRatings({required int serviceProviderBranchID, required String title, required String review, required double ratingNo}) async { + final customerID = appState.getUser.data!.userInfo!.customerId; + final parameters = {"title": title, "review": review, "ratNo": ratingNo, "serviceProviderBranchID": serviceProviderBranchID, "customerID": "$customerID"}; + GenericRespModel adsGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.createBranchRatings, + parameters, + token: appState.getUser.data!.accessToken, + ); + return adsGenericModel; + } } diff --git a/lib/repositories/request_repo.dart b/lib/repositories/request_repo.dart index 16d7a93..36f4f08 100644 --- a/lib/repositories/request_repo.dart +++ b/lib/repositories/request_repo.dart @@ -16,7 +16,9 @@ abstract class RequestRepo { Future getOffersFromProvidersByRequest({required int requestId}); - Future> getRequests(Map postParams); + Future> getRequests({required int providerOrCustomerID}); + + Future> getServiceRequestsForProviders({required int serviceProviderID}); Future updateOfferRequestStatus({required RequestOfferStatusEnum requestOfferStatusEnum, required int requestOfferId, required String comments}); } @@ -37,11 +39,21 @@ class RequestRepoImp implements RequestRepo { } @override - Future> getRequests(Map postParams) async { + Future> getRequests({required int providerOrCustomerID}) async { + final paramsForGetRequests = { + "pageSize": 100, + "pageIndex": 0, + }; + + if (AppState().currentAppType == AppType.provider) { + paramsForGetRequests.addEntries([MapEntry("providerID", providerOrCustomerID)]); + } else { + paramsForGetRequests.addEntries([MapEntry("customerID", providerOrCustomerID)]); + } GenericRespModel enumGenericModel = await apiClient.postJsonForObject( (json) => GenericRespModel.fromJson(json), ApiConsts.getRequest, - postParams, + paramsForGetRequests, token: appState.getUser.data!.accessToken, ); List requests = List.generate( @@ -53,6 +65,26 @@ class RequestRepoImp implements RequestRepo { return requests; } + @override + Future> getServiceRequestsForProviders({required int serviceProviderID}) async { + final parameters = { + "ServiceProviderId": serviceProviderID.toString(), + }; + GenericRespModel genericRespModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getServiceRequestsForProvider, + queryParameters: parameters, + token: appState.getUser.data!.accessToken, + ); + List requests = List.generate( + genericRespModel.data.length, + (index) => RequestModel.fromJson( + genericRespModel.data[index], + ), + ); + return requests; + } + @override Future> getOffersByRequest({required int requestId, int serviceProviderId = 0}) async { var queryParameters = { diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index af4dd81..df56c72 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; class MyColors { static const Color darkPrimaryColor = Color(0xffF47F20); static const Color primaryColor = Color(0xffF69521); + static const Color lightPrimaryColor = Color(0xffFFD077); static const Color accentColor = Colors.blue; static const Color lightTextColor = Color(0xff969696); static const Color textColor = Color(0xff777777); @@ -38,6 +39,7 @@ class MyColors { static const Color borderColor = Color(0xffE8E8E8); static const Color greyAddBorderColor = Color(0xffEEEEEE); static const Color lightGreyBgColor = Color(0xffFDFDFD); + static const Color lightGreyDDColor = Color(0xffDDDDDD); //AdStatusColors: static const Color adActiveStatusColor = Color(0xff5FC16A); diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index d18836f..9e0ae74 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -175,8 +175,7 @@ class AdVM extends BaseVM { if (myAdsFilterOptions.isNotEmpty && exploreAdsFilterOptions.isNotEmpty) { return; } - log("myAdsEnums: ${myAdsEnums.length}"); - log("exploreAdsEnums: ${exploreAdsEnums.length}"); + if (myAdsEnums.isEmpty) { myAdsEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.myAdsFilterEnumId); } @@ -196,8 +195,6 @@ class AdVM extends BaseVM { } exploreAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0)); - logger.i("myAdsEnums: ${myAdsEnums.length}"); - logger.i("exploreAdsEnums: ${exploreAdsEnums.length}"); notifyListeners(); } @@ -409,6 +406,7 @@ class AdVM extends BaseVM { vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: vehicleIdForEditAd != -1 ? vehicleIdForEditAd : vehicleTypeId.selectedId); isFetchingLists = false; + notifyListeners(); } @@ -497,7 +495,6 @@ class AdVM extends BaseVM { return; } vehicleBrandId = id; - logger.i("message: ${vehicleBrandId.selectedOption}"); await getVehicleDetailsByVehicleBrandId(); notifyListeners(); @@ -1210,7 +1207,7 @@ class AdVM extends BaseVM { vehicleAdsSpecialServices.clear(); currentProgressStep = AdCreationSteps.vehicleDetails; vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + // vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleColorId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); @@ -1221,7 +1218,6 @@ class AdVM extends BaseVM { 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 = ""; @@ -1679,11 +1675,13 @@ class AdVM extends BaseVM { ///// Edit Work Amir - void onEditUpdateAdPressed(BuildContext context, AdDetailsModel previousDetails) { + void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd}) { isAdEditEnabled = true; previousAdDetails = previousDetails; autoFillSelectedVehicleType(); - navigateWithName(context, AppRoutes.selectAdTypeView, arguments: AppState().currentAppType == AppType.provider ? true : false); + autoFillSelectedVehicleAdsDuration(); + + navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [AppState().currentAppType == AppType.provider, isFromExtendAd]); } autoFillSelectedVehicleType() async { @@ -1707,6 +1705,7 @@ class AdVM extends BaseVM { await getVehicleAdsDuration(); } if (vehicleAdsDurations.isNotEmpty) { + // TODO: FOR THE PROVIDER, THIS CHECK WILL NOT WORK. BECAUSE IN CASE OF PROVIDER,THE PRICE WILL ALWAYS BE 0.0. Have to get ads duration ID from API in previousAd Details int index = vehicleAdsDurations.indexWhere((element) => element.price == previousAdDetails!.adsDurationPrice!); if (index != -1) { updateVehicleAdDurationId( @@ -1743,13 +1742,12 @@ class AdVM extends BaseVM { updateSelectionVehicleColorId(SelectionModel(selectedId: previousAdDetails!.vehicle!.color!.id!, selectedOption: previousAdDetails!.vehicle!.color!.label ?? "")); updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.label ?? "")); updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? "")); - updateSelectionVehicleMileageId(SelectionModel( - selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}")); + updateSelectionVehicleMileageId(SelectionModel(selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}")); updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? "")); updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? "")); int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID); if (indexCountry != -1) { - updateSelectionVehicleCountryId(SelectionModel(selectedId: vehicleCountries[index].id!, selectedOption: vehicleCountries[index].countryName ?? "")); + updateSelectionVehicleCountryId(SelectionModel(selectedId: vehicleCountries[indexCountry].id!, selectedOption: vehicleCountries[indexCountry].countryName ?? "")); } updateSelectionVehicleCityId(SelectionModel(selectedId: previousAdDetails!.vehicle!.cityID!, selectedOption: previousAdDetails!.vehicle!.cityName ?? "")); @@ -1759,6 +1757,7 @@ class AdVM extends BaseVM { vehicleDescription = previousAdDetails!.vehicle!.vehicleDescription.toString(); financeAvailableStatus = previousAdDetails!.vehicle!.isFinanceAvailable ?? false; + pickedPostingImages.clear(); if (previousAdDetails!.vehicle!.image != null && previousAdDetails!.vehicle!.image!.isNotEmpty) { for (var element in previousAdDetails!.vehicle!.image!) { if (element.imageUrl != null) { @@ -1815,7 +1814,6 @@ class AdVM extends BaseVM { } isNumberOnWhatsApp = previousAdDetails!.whatsAppNo != null; - logger.i("previousAdDetails!: $previousAdDetails"); notifyListeners(); } @@ -1846,10 +1844,9 @@ class AdVM extends BaseVM { adsChatBuyerId: 1, adID: adDetailsModel.id, userID: myUserID, + senderName: adDetailsModel.adOwnerName, ) - .whenComplete( - () => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments), - ); + .whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments)); } } diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index 72948eb..ea8166b 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -15,6 +15,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/branch_review_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_model.dart'; @@ -161,7 +162,7 @@ class AppointmentsVM extends BaseVM { } } } catch (e) { - Utils.showToast("${e.toString()}"); + Utils.showToast(e.toString()); } } @@ -238,7 +239,9 @@ class AppointmentsVM extends BaseVM { } void removeServiceInCurrentAppointment(int index) { - int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1; + int serviceId = servicesInCurrentAppointment + .elementAt(index) + .serviceProviderServiceId ?? -1; allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId); servicesInCurrentAppointment.removeAt(index); notifyListeners(); @@ -382,9 +385,7 @@ class AppointmentsVM extends BaseVM { } } - Future getMyAppointmentsForProvider( - Map map, - ) async { + Future getMyAppointmentsForProvider(Map map) async { setState(ViewState.busy); myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map); myFilteredAppointments = myAppointments; @@ -434,7 +435,7 @@ class AppointmentsVM extends BaseVM { updateCheckBoxInMergeRequest(int currentIndex) { myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = - !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); + !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []); if (count > 1) @@ -445,7 +446,10 @@ class AppointmentsVM extends BaseVM { } int countSelected(List appointments) { - return appointments.where((appointment) => appointment.isSelected == true).toList().length; + return appointments + .where((appointment) => appointment.isSelected == true) + .toList() + .length; } updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) { @@ -531,6 +535,7 @@ class AppointmentsVM extends BaseVM { } Future> getServiceItems(int serviceId) async { + setState(ViewState.busy); serviceItemsFromApi.clear(); serviceItemsFromApi = await branchRepo.getServiceItems(serviceId); for (var item in serviceItemsFromApi) { @@ -612,13 +617,14 @@ class AppointmentsVM extends BaseVM { Column( children: List.generate( selectedService.serviceItems!.length, - (index) => Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - "${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - "${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true), - ], - ), + (index) => + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + "${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true), + ], + ), ), ), Row( @@ -654,8 +660,8 @@ class AppointmentsVM extends BaseVM { crossAxisAlignment: CrossAxisAlignment.end, children: [ (selectedService.isHomeSelected - ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" - : "${selectedService.currentTotalServicePrice}") + ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" + : "${selectedService.currentTotalServicePrice}") .toText(fontSize: 29, isBold: true), 2.width, LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), @@ -810,19 +816,6 @@ class AppointmentsVM extends BaseVM { List branchServices = []; - // populateBranchesFilterList() { - // branchesFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API - // branchesFilterOptions = [ - // FilterListModel(title: "All Branches", isSelected: true, id: 0), - // FilterListModel(title: "Maintenance", isSelected: false, id: 1), - // FilterListModel(title: "Oil Service", isSelected: false, id: 2), - // FilterListModel(title: "Accessories", isSelected: false, id: 3), - // FilterListModel(title: "Tire Service", isSelected: false, id: 4), - // FilterListModel(title: "Dent and Paint", isSelected: false, id: 5), - // ]; - // notifyListeners(); - // } - Future populateBranchesFilterList() async { if (branchesFilterOptions.isNotEmpty) return; branchesFilterOptions.clear(); @@ -853,7 +846,7 @@ class AppointmentsVM extends BaseVM { Future getMyRecentBranches({bool isNeedToRebuild = false}) async { myRecentBranches.clear(); if (isNeedToRebuild) setState(ViewState.busy); - myRecentBranches = await branchRepo.getAllNearBranchAndServices(); + myRecentBranches = await branchRepo.getMyRecentBranchesWithServices(); setState(ViewState.idle); } @@ -1086,10 +1079,10 @@ class AppointmentsVM extends BaseVM { DropValue( element.id ?? 0, ((element.categoryName!.isEmpty - ? "N/A" - : countryCode == "SA" - ? element.categoryNameN - : element.categoryName) ?? + ? "N/A" + : countryCode == "SA" + ? element.categoryNameN + : element.categoryName) ?? "N/A"), ""), ); @@ -1433,4 +1426,33 @@ class AppointmentsVM extends BaseVM { applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); setState(ViewState.idle); } + + Future addProviderToFavorite({required String serviceProviderID}) async { + setState(ViewState.busy); + } + + List currentBranchReviews = []; + bool isReadMoreEnabled = false; + + void resetCurrentBranchRatings() { + currentBranchReviews.clear(); + isReadMoreEnabled = false; + } + + updateIsReadMoreEnabled(var value) { + isReadMoreEnabled = value; + notifyListeners(); + } + + Future getReviewsByBranchId({required int serviceProviderBranchID}) async { + setState(ViewState.busy); + try { + currentBranchReviews = await branchRepo.getBranchRatings(serviceProviderBranchID: serviceProviderBranchID); + } catch (e, s) { + logger.e(s); + setState(ViewState.idle); + Utils.showToast(e.toString()); + } + setState(ViewState.idle); + } } diff --git a/lib/view_models/chat_view_model.dart b/lib/view_models/chat_view_model.dart index 4a88a55..2257e18 100644 --- a/lib/view_models/chat_view_model.dart +++ b/lib/view_models/chat_view_model.dart @@ -446,7 +446,6 @@ class ChatVM extends ChangeNotifier { return false; }); } - return true; } @@ -454,7 +453,7 @@ class ChatVM extends ChangeNotifier { List currentMessagesForAds = []; - Future getUsersChatMessagesForAd({required BuildContext context, int? adID, int? adsChatBuyerId, String? userID, required bool isForBuyer}) async { + Future getUsersChatMessagesForAd({required BuildContext context, int? adID, int? adsChatBuyerId, String? userID, String? senderName, required bool isForBuyer}) async { try { Utils.showLoading(context); currentMessagesForAds = await chatRepo.getUsersChatMessagesForAds(userID: userID, adID: adID, isForBuyer: isForBuyer, adsChatBuyerId: adsChatBuyerId); @@ -463,6 +462,7 @@ class ChatVM extends ChangeNotifier { List unreadMessageIds = []; for (var msg in currentMessagesForAds) { + msg.senderName = senderName ?? ""; if (!msg.isRead!) { unreadMessageIds.add(msg.id!); } diff --git a/lib/view_models/requests_view_model.dart b/lib/view_models/requests_view_model.dart index c4b303e..e1111ae 100644 --- a/lib/view_models/requests_view_model.dart +++ b/lib/view_models/requests_view_model.dart @@ -64,27 +64,26 @@ class RequestsVM extends BaseVM { Future getRequests({bool isNeedToRebuild = false, required AppType appType}) async { if (isNeedToRebuild) setState(ViewState.busy); - var paramsForGetRequests = {}; - - paramsForGetRequests = { - "pageSize": 100, - "pageIndex": 0, - // "requestType": 0, - }; + int providerOrCustomerID = 0; if (appType == AppType.provider) { - paramsForGetRequests.addEntries([MapEntry("providerID", AppState().getUser.data!.userInfo!.providerId)]); + providerOrCustomerID = AppState().getUser.data!.userInfo!.providerId ?? 0; } else { - paramsForGetRequests.addEntries([MapEntry("customerID", AppState().getUser.data!.userInfo!.customerId)]); + providerOrCustomerID = AppState().getUser.data!.userInfo!.customerId ?? 0; } - myRequests = await requestRepo.getRequests(paramsForGetRequests); + myRequests = await requestRepo.getRequests(providerOrCustomerID: providerOrCustomerID); applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest); setState(ViewState.idle); notifyListeners(); } + Future> getServiceRequestsForProviders() async { + setState(ViewState.busy); + List serviceRequestsForProviders = await requestRepo.getServiceRequestsForProviders(serviceProviderID: AppState().getUser.data!.userInfo!.providerId); + setState(ViewState.idle); + return serviceRequestsForProviders; + } + addChatMessagesInRequestsModel({required ChatMessageModel msg, required int index}) { - log("msg: $msg"); - log("index: $index"); myFilteredRequests[index].chatMessages.add(msg); notifyListeners(); } @@ -102,12 +101,16 @@ class RequestsVM extends BaseVM { notifyListeners(); } - applyFilterOnRequestsVM({required RequestsTypeEnum requestsTypeEnum}) { + applyFilterOnRequestsVM({required RequestsTypeEnum requestsTypeEnum}) async { if (requestsTypeFilterOptions.isEmpty) return; for (var value in requestsTypeFilterOptions) { value.isSelected = false; } requestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeStatusEnum() - 1].isSelected = true; // -1 to match with the index + if (AppState().currentAppType == AppType.provider && requestsTypeEnum == RequestsTypeEnum.serviceRequest) { + myFilteredRequests = await getServiceRequestsForProviders(); + return; + } myFilteredRequests = myRequests.where((element) => element.requestType == requestsTypeEnum.getIdFromRequestTypeStatusEnum()).toList(); notifyListeners(); } diff --git a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart index 619d3b7..5487cdc 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart @@ -5,12 +5,11 @@ import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; -import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.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/bottom_sheet_content.dart'; -import 'package:mc_common_app/views/advertisement/custom_add_button.dart'; +import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_special_service_sheet.dart'; +import 'package:mc_common_app/widgets/common_widgets/custom_add_button_widget.dart'; import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; @@ -20,7 +19,7 @@ import 'package:easy_localization/easy_localization.dart'; class AdDuration extends StatelessWidget { const AdDuration({Key? key}) : super(key: key); - void onAddServiceButtonTapped(BuildContext context, AdVM adVM) { + void onAddSpecialServiceButtonTapped(BuildContext context, AdVM adVM) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -228,7 +227,7 @@ class AdDuration extends StatelessWidget { needsBorder: true, bgColor: MyColors.white, onTap: () { - onAddServiceButtonTapped(context, adVM); + onAddSpecialServiceButtonTapped(context, adVM); }, text: LocaleKeys.addService.tr(), icon: Container( diff --git a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart index 0926a29..96b3840 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart @@ -4,7 +4,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; -import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; +import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -78,7 +78,7 @@ class VehicleDetailsReview extends StatelessWidget { 16.height, SingleDetailWidget(text: adVM.vehicleVin, type: LocaleKeys.vehicleVIN.tr()), 16.height, - SingleDetailWidget(text: ("${adVM.warrantyDuration} "+ LocaleKeys.years.tr()), type: LocaleKeys.warrantyAvailable.tr()), + SingleDetailWidget(text: ("${adVM.warrantyDuration} ${LocaleKeys.years.tr()}"), type: LocaleKeys.warrantyAvailable.tr()), 16.height, ], ), @@ -111,7 +111,7 @@ class VehicleDetailsReview extends StatelessWidget { ), SingleDetailWidget(text: adVM.vehicleDescription, type: LocaleKeys.description.tr()), 8.height, - (LocaleKeys.vehiclePictures.tr() + ":").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ("${LocaleKeys.vehiclePictures.tr()}:").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), if (adVM.pickedPostingImages.isNotEmpty) ...[ // 10.height, PickedFilesContainer( @@ -142,7 +142,7 @@ class DamagePartsReview extends StatelessWidget { ], ), if (adVM.vehicleDamageCards[index].partImages != null && adVM.vehicleDamageCards[index].partImages!.isNotEmpty) ...[ - (LocaleKeys.damagePartPictures.tr() + ":").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ("${LocaleKeys.damagePartPictures.tr()}:").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), PickedFilesContainer( pickedFiles: adVM.vehicleDamageCards[index].partImages!, onCrossPressedPrimary: adVM.removeImageFromList, diff --git a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart index dbd070a..be1b994 100644 --- a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart +++ b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart @@ -5,10 +5,9 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; -import 'package:mc_common_app/views/advertisement/bottom_sheet_content.dart'; -import 'package:mc_common_app/views/advertisement/custom_add_button.dart'; -import 'package:mc_common_app/views/advertisement/network_images_container.dart'; -import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; +import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_damage_parts_selection_sheet.dart'; +import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; +import 'package:mc_common_app/widgets/common_widgets/custom_add_button_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -32,7 +31,7 @@ class DamageParts extends StatelessWidget { isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - return const BottomSheetListContent(); + return const AdDamagePartsSelectionSheet(); }); } @@ -131,7 +130,6 @@ class DamageParts extends StatelessWidget { ], ).paddingOnly(right: 10) ], - ], ).toWhiteContainer( width: double.infinity, diff --git a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart index 1f4cc29..0e98a69 100644 --- a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart +++ b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart @@ -8,8 +8,8 @@ import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart'; -import 'package:mc_common_app/views/advertisement/network_images_container.dart'; -import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; +import 'package:mc_common_app/views/advertisement/components/network_images_container_widget.dart'; +import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.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'; diff --git a/lib/views/advertisement/ads_buyer_chats_list_view.dart b/lib/views/advertisement/ads_buyer_chats_list_view.dart deleted file mode 100644 index 339a745..0000000 --- a/lib/views/advertisement/ads_buyer_chats_list_view.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mc_common_app/config/routes.dart'; -import 'package:mc_common_app/extensions/int_extensions.dart'; -import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package:mc_common_app/generated/locale_keys.g.dart'; -import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; -import 'package:mc_common_app/models/chat_models/buyers_chat_for_ads_model.dart'; -import 'package:mc_common_app/theme/colors.dart'; -import 'package:mc_common_app/utils/enums.dart'; -import 'package:mc_common_app/utils/navigator.dart'; -import 'package:mc_common_app/view_models/ad_view_model.dart'; -import 'package:mc_common_app/view_models/chat_view_model.dart'; -import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; -import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:provider/provider.dart'; - -class AdsBuyerChatsListView extends StatelessWidget { - final List buyersListViewArguments; - - const AdsBuyerChatsListView({super.key, required this.buyersListViewArguments}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(title: LocaleKeys.chat.tr()), - body: buyersListViewArguments.isEmpty - ? Center(child: LocaleKeys.noOffersShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor)) - : ListView.separated( - itemCount: buyersListViewArguments.length, - padding: const EdgeInsets.all(16), - itemBuilder: (context, index) { - BuyersChatForAdsModel chatForAdsModel = buyersListViewArguments[index]; - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (chatForAdsModel.buyerName ?? "").toText(fontSize: 16, isBold: true), - if (chatForAdsModel.unReadMessagesCount != null && chatForAdsModel.unReadMessagesCount! > 0) ...[ - Center( - child: "${chatForAdsModel.unReadMessagesCount ?? "1"}".toText( - color: Colors.white, - isBold: true, - fontSize: 10, - ), - ).toContainer( - backgroundColor: MyColors.redColor, - borderRadius: 100, - paddingAll: 1, - width: 22, - height: 22, - ), - ] - ], - ), - 8.height, - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - (chatForAdsModel.lastMessage ?? "").toText(color: MyColors.lightTextColor, fontSize: 12), - ], - ), - - if (chatForAdsModel.lastMessageDateTime != null) ...[ - DateTime.parse(chatForAdsModel.lastMessageDateTime!).getTimeAgo().toText(color: MyColors.lightTextColor), - ], - // const Icon( - // Icons.arrow_forward, - // color: MyColors.darkIconColor, - // size: 18, - // ), - ], - ), - ], - ).onPress(() async { - ChatViewArgumentsForAd chatViewArgumentsForAd = ChatViewArgumentsForAd(receiverUserID: chatForAdsModel.buyerUserID, adsID: chatForAdsModel.adsID); - - ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.ads, chatViewArgumentsForAd: chatViewArgumentsForAd); - - final chatVM = context.read(); - await chatVM.getUsersChatMessagesForAd(context: context, isForBuyer: false, adsChatBuyerId: chatForAdsModel.id).whenComplete( - () => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments), - ); - }).toContainer(isShadowEnabled: true); - }, - separatorBuilder: (context, index) => 16.height, - ), - ); - } -} diff --git a/lib/views/advertisement/ads_buyer_chats_view.dart b/lib/views/advertisement/ads_buyer_chats_view.dart new file mode 100644 index 0000000..37eba85 --- /dev/null +++ b/lib/views/advertisement/ads_buyer_chats_view.dart @@ -0,0 +1,118 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/config/routes.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; +import 'package:mc_common_app/models/chat_models/buyers_chat_for_ads_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/view_models/chat_view_model.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; + +class AdsBuyerChatsView extends StatelessWidget { + final List buyersListViewArguments; + + const AdsBuyerChatsView({super.key, required this.buyersListViewArguments}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar(title: LocaleKeys.chat.tr()), + body: buyersListViewArguments.isEmpty + ? Center(child: LocaleKeys.noOffersShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor)) + : ListView.separated( + itemCount: buyersListViewArguments.length, + padding: const EdgeInsets.all(16), + itemBuilder: (context, index) { + BuyersChatForAdsModel chatForAdsModel = buyersListViewArguments[index]; + return Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + MyAssets.bnCar, + width: 34, + height: 34, + fit: BoxFit.fill, + ).toCircle(borderRadius: 100), + SizedBox(width: 2.w), + Expanded( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (chatForAdsModel.buyerName ?? "").toText(fontSize: 16, isBold: true), + if (chatForAdsModel.unReadMessagesCount != null && chatForAdsModel.unReadMessagesCount! > 0) ...[ + Center( + child: "${chatForAdsModel.unReadMessagesCount ?? "1"}".toText( + color: Colors.white, + isBold: true, + fontSize: 10, + ), + ).toContainer( + backgroundColor: MyColors.redColor, + borderRadius: 100, + paddingAll: 1, + width: 22, + height: 22, + ), + ] + ], + ), + 8.height, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: ("${chatForAdsModel.lastMessage}").toText(color: MyColors.lightTextColor, fontSize: 12)), + SizedBox(width: 5.w), + if (chatForAdsModel.lastMessageDateTime != null) ...[ + DateTime.parse(chatForAdsModel.lastMessageDateTime!).getTimeAgo().toText(color: MyColors.lightTextColor), + ], + ], + ), + 2.height, + const Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + Icons.arrow_forward, + color: MyColors.darkIconColor, + size: 18, + ), + ], + ) + ], + ), + ), + ], + ), + ], + ).onPress(() async { + ChatViewArgumentsForAd chatViewArgumentsForAd = ChatViewArgumentsForAd(receiverUserID: chatForAdsModel.buyerUserID, adsID: chatForAdsModel.adsID); + + ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.ads, chatViewArgumentsForAd: chatViewArgumentsForAd); + + final chatVM = context.read(); + await chatVM + .getUsersChatMessagesForAd(context: context, isForBuyer: false, adsChatBuyerId: chatForAdsModel.id, senderName: chatForAdsModel.buyerName) + .whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments)); + }).toContainer(isShadowEnabled: true); + }, + separatorBuilder: (context, index) => 16.height, + ), + ); + } +} diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 93a7a73..4313fcd 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; @@ -15,9 +16,10 @@ import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/payment_view_model.dart'; -import 'package:mc_common_app/views/advertisement/ad_duration_selection_sheet_content.dart'; -import 'package:mc_common_app/views/advertisement/ads_images_slider.dart'; -import 'package:mc_common_app/views/advertisement/picked_images_container.dart'; +import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart'; +import 'package:mc_common_app/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart'; +import 'package:mc_common_app/views/advertisement/components/ads_images_corousel_widget.dart'; +import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; import 'package:mc_common_app/views/appointments/widgets/custom_calender_widget.dart'; import 'package:mc_common_app/widgets/bottom_sheet.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; @@ -41,12 +43,15 @@ class AdsDetailView extends StatefulWidget { class _AdsDetailViewState extends State { late AdVM adVM; + late List damagePartsPictures; @override void initState() { adVM = context.read(); + damagePartsPictures = []; scheduleMicrotask(() { onAdDetailsLoaded(); + populateDamagePartPictures(); }); super.initState(); } @@ -58,6 +63,24 @@ class _AdsDetailViewState extends State { } } + void populateDamagePartPictures() { + if (widget.adDetails.vehicle!.damagereport != null && widget.adDetails.vehicle!.damagereport!.isNotEmpty) { + for (var element in widget.adDetails.vehicle!.damagereport!) { + int index = -1; + ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); + + VehicleDamageCard vehicleDamageCard = VehicleDamageCard( + partSelectedId: SelectionModel( + selectedId: element.vehicleDamagePartID!, + selectedOption: element.partName ?? "", + ), + partImages: [imageModel], + ); + damagePartsPictures.add(vehicleDamageCard); + } + } + } + void deleteAdBottomSheet(BuildContext context) { return actionConfirmationBottomSheet( context: context, @@ -90,6 +113,196 @@ class _AdsDetailViewState extends State { ); } + Widget buildVehicleDetailsWidget() { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AdImagesCorouselWidget(vehicleImages: widget.adDetails.vehicle!.image!), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label} | ${widget.adDetails.id}".toText( + fontSize: 18, + isBold: true, + maxLines: 2, + ), + ), + (widget.adDetails.vehicle!.cityName ?? "").toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + ("${LocaleKeys.model.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "${widget.adDetails.vehicle!.modelyear!.label}".toText( + fontSize: 14, + isBold: true, + ), + ], + ), + "${widget.adDetails.vehicle!.countryID}".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + ("${LocaleKeys.mileage.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "${widget.adDetails.vehicle!.mileage!.mileageEnd}Km".toText( + fontSize: 14, + isBold: true, + ), + ], + ), + widget.adDetails.createdOn != null ? DateTime.parse(widget.adDetails.createdOn!).getTimeAgo().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor) : const SizedBox(), + ], + ), + Row( + children: [ + ("${LocaleKeys.transmission.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "${widget.adDetails.vehicle!.transmission!.label}".toText( + fontSize: 14, + isBold: true, + ), + ], + ), + 8.height, + ("${LocaleKeys.description.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "${widget.adDetails.vehicle!.vehicleDescription}".toText( + fontSize: 14, + isBold: true, + ), + if (widget.adDetails.isMyAd ?? false) ...[ + 8.height, + ("${LocaleKeys.demand.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + widget.adDetails.vehicle!.demandAmount!.toInt().toString().toText(fontSize: 30, height: 1.2, isBold: true), + LocaleKeys.sar.tr().toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5), + ], + ), + if (widget.adDetails.adPostStatus == AdPostStatus.expired) ...[ + 8.height, + const Divider(thickness: 1, height: 1), + 8.height, + LocaleKeys.adDurationExpired.tr().toText( + color: MyColors.redColor, + fontSize: 12, + isItalic: true, + ), + ], + ] + ], + ).toWhiteContainer(width: double.infinity, allPading: 12); + } + + Widget buildBankDetailsIfAvailable() { + return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { + if (adVM.adsBankDetailsModel != null) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.bankDetails.tr().toText(fontSize: 18, isBold: true), + // Row( + // children: [ + // "Full Name: ".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + // "${widget.adDetails.vehicle!.vehicleDescription}".toText( + // fontSize: 14, + // isBold: true, + // ), + // ], + // ), + Row( + children: [ + ("${LocaleKeys.bankName.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + (adVM.adsBankDetailsModel!.bankName ?? "").toText( + fontSize: 14, + isBold: true, + ), + ], + ), + Row( + children: [ + ("${LocaleKeys.iban.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + (adVM.adsBankDetailsModel!.iban ?? "").toText( + fontSize: 14, + isBold: true, + ), + ], + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12); + } + return const SizedBox.shrink(); + }); + } + + Widget buildAdRejectionDetails() { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.rejectionComments.tr().toText(fontSize: 13, isBold: true, color: MyColors.lightTextColor), + Row( + children: [ + LocaleKeys.editAd.tr().toText(fontSize: 10, isBold: true), + 2.width, + const Icon(Icons.edit, size: 15), + ], + ).onPress(() async { + Utils.showLoading(context); + await adVM.getVehicleTypes(); + await adVM.getVehicleBrandsByVehicleTypeId(vehicleIdForEditAd: widget.adDetails.vehicle!.vehicleType ?? -1); + Utils.hideLoading(context); + adVM.onEditUpdateAdPressed(context: context, previousDetails: widget.adDetails, isFromExtendAd: false); + }), + ], + ).paddingOnly(bottom: 5), + Row( + children: [ + Flexible( + child: (widget.adDetails.comment ?? "").toText( + color: MyColors.redColor, + fontSize: 12, + isItalic: true, + ), + ) + ], + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12); + } + + Widget buildDamagePartDetails() { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + MyAssets.carHitIcon.buildSvg(color: MyColors.darkTextColor), + 10.width, + LocaleKeys.damagePartPictures.tr().toText(fontSize: 16), + ], + ), + const Icon(Icons.arrow_forward_ios_rounded, size: 20) + ], + ).paddingOnly(top: 5, bottom: 5).onPress(() { + showMyBottomSheet(context, child: AdDamagePartPicturesSheet(adDamageReportList: widget.adDetails.vehicle!.damagereport ?? [])); + }).toWhiteContainer(width: double.infinity, allPading: 12); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -128,173 +341,16 @@ class _AdsDetailViewState extends State { child: ListView( shrinkWrap: true, children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CarouselWithIndicatorDemo(vehicleImages: widget.adDetails.vehicle!.image!), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label} | ${widget.adDetails.id}".toText( - fontSize: 18, - isBold: true, - maxLines: 2, - ), - ), - (widget.adDetails.vehicle!.cityName ?? "").toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - ("${LocaleKeys.model.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - "${widget.adDetails.vehicle!.modelyear!.label}".toText( - fontSize: 14, - isBold: true, - ), - ], - ), - "${widget.adDetails.vehicle!.countryID}".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - ("${LocaleKeys.mileage.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - "${widget.adDetails.vehicle!.mileage!.mileageEnd}Km".toText( - fontSize: 14, - isBold: true, - ), - ], - ), - widget.adDetails.createdOn != null - ? DateTime.parse(widget.adDetails.createdOn!).getTimeAgo().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor) - : const SizedBox(), - ], - ), - Row( - children: [ - ("${LocaleKeys.transmission.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - "${widget.adDetails.vehicle!.transmission!.label}".toText( - fontSize: 14, - isBold: true, - ), - ], - ), - 8.height, - ("${LocaleKeys.description.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - "${widget.adDetails.vehicle!.vehicleDescription}".toText( - fontSize: 14, - isBold: true, - ), - if (widget.adDetails.isMyAd ?? false) ...[ - 8.height, - ("${LocaleKeys.demand.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - widget.adDetails.vehicle!.demandAmount!.toInt().toString().toText(fontSize: 30, height: 1.2, isBold: true), - LocaleKeys.sar.tr().toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5), - ], - ), - if (widget.adDetails.adPostStatus == AdPostStatus.expired) ...[ - 8.height, - const Divider(thickness: 1, height: 1), - 8.height, - LocaleKeys.adDurationExpired.tr().toText( - color: MyColors.redColor, - fontSize: 12, - isItalic: true, - ), - ], - ] - ], - ).toWhiteContainer(width: double.infinity, allPading: 12), + buildVehicleDetailsWidget(), 12.height, - Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { - if (adVM.adsBankDetailsModel != null) { - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.bankDetails.tr().toText(fontSize: 18, isBold: true), - // Row( - // children: [ - // "Full Name: ".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - // "${widget.adDetails.vehicle!.vehicleDescription}".toText( - // fontSize: 14, - // isBold: true, - // ), - // ], - // ), - Row( - children: [ - ("${LocaleKeys.bankName.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - (adVM.adsBankDetailsModel!.bankName ?? "").toText( - fontSize: 14, - isBold: true, - ), - ], - ), - Row( - children: [ - ("${LocaleKeys.iban.tr()}: ").toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - (adVM.adsBankDetailsModel!.iban ?? "").toText( - fontSize: 14, - isBold: true, - ), - ], - ), - ], - ).toWhiteContainer(width: double.infinity, allPading: 12); - } - return const SizedBox.shrink(); - }), + buildBankDetailsIfAvailable(), + if (widget.adDetails.vehicle!.damagereport != null && widget.adDetails.vehicle!.damagereport!.isNotEmpty) ...[ + buildDamagePartDetails(), + ], 12.height, - if (widget.adDetails.adPostStatus == AdPostStatus.rejected) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocaleKeys.rejectionComments.tr().toText(fontSize: 13, isBold: true, color: MyColors.lightTextColor), - Row( - children: [ - LocaleKeys.editAd.tr().toText(fontSize: 10, isBold: true), - 2.width, - const Icon(Icons.edit, size: 15), - ], - ).onPress(() async { - Utils.showLoading(context); - await adVM.getVehicleTypes(); - await adVM.getVehicleBrandsByVehicleTypeId(vehicleIdForEditAd: widget.adDetails.vehicle!.vehicleType ?? -1); - Utils.hideLoading(context); - adVM.onEditUpdateAdPressed(context, widget.adDetails); - }), - ], - ).paddingOnly(bottom: 5), - Row( - children: [ - Flexible( - child: (widget.adDetails.comment ?? "").toText( - color: MyColors.redColor, - fontSize: 12, - isItalic: true, - ), - ) - ], - ), - ], - ).toWhiteContainer(width: double.infinity, allPading: 12), + if (widget.adDetails.adPostStatus == AdPostStatus.rejected) ...[ + buildAdRejectionDetails(), + ], ], ), ), @@ -533,13 +589,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { ), if (adDetailsModel.whatsAppNo == null) ...[ 8.width, - Container( - height: 55, - width: 55, - alignment: Alignment.center, - decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), - child: MyAssets.whatsAppIcon.buildSvg(height: 33, width: 35)) - .onPress(() { + Container(height: 55, width: 55, alignment: Alignment.center, decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), child: MyAssets.whatsAppIcon.buildSvg(height: 33, width: 35)).onPress(() { Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? ""); }), ], @@ -1155,12 +1205,12 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { maxHeight: 55, title: LocaleKeys.yes.tr(), fontSize: 15, - onPressed: () { - Navigator.pop(context); - adVM.updateSelectionVehicleTypeId( - SelectionModel(selectedId: adDetailsModel.vehicle!.vehicleType!, selectedOption: (adDetailsModel.vehicle!.vehicleType!).toVehicleTypeString(), errorValue: ""), - ); - showMyBottomSheet(context, child: const AdDurationSelectionSheetContent(isFromExtendAd: true, isUpdateAdSelected: true)); + onPressed: () async { + Utils.showLoading(context); + await adVM.getVehicleTypes(); + await adVM.getVehicleBrandsByVehicleTypeId(vehicleIdForEditAd: adDetailsModel.vehicle!.vehicleType ?? -1); + Utils.hideLoading(context); + adVM.onEditUpdateAdPressed(context: context, previousDetails: adDetailsModel, isFromExtendAd: true); }, ), ), @@ -1177,7 +1227,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { SelectionModel(selectedId: adDetailsModel.vehicle!.vehicleType!, selectedOption: (adDetailsModel.vehicle!.vehicleType!).toVehicleTypeString(), errorValue: ""), ); - showMyBottomSheet(context, child: const AdDurationSelectionSheetContent(isFromExtendAd: true, isUpdateAdSelected: false)); + showMyBottomSheet(context, child: const AdDurationSelectionSheet(isFromExtendAd: true, isUpdateAdSelected: false)); }, ), ), diff --git a/lib/views/advertisement/bottom_sheets/ad_damage_parts_selection_sheet.dart b/lib/views/advertisement/bottom_sheets/ad_damage_parts_selection_sheet.dart new file mode 100644 index 0000000..6703a47 --- /dev/null +++ b/lib/views/advertisement/bottom_sheets/ad_damage_parts_selection_sheet.dart @@ -0,0 +1,143 @@ +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/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; +import 'package:mc_common_app/models/general_models/widgets_models.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; +import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; + +class AdDamagePartsSelectionSheet extends StatefulWidget { + const AdDamagePartsSelectionSheet({Key? key}) : super(key: key); + + @override + State createState() => _AdDamagePartsSelectionSheetState(); +} + +class _AdDamagePartsSelectionSheetState extends State { + bool checkBoxValue = false; + + @override + Widget build(BuildContext context) { + AdVM adVM = context.watch(); + 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: [ + LocaleKeys.damagePartList.tr().toText(fontSize: 24, isBold: true), + ], + ), + 8.height, + TxtField( + value: adVM.damagePartSearchValue, + errorValue: "", + hint: LocaleKeys.searchPart.tr(), + onChanged: (value) { + adVM.onSearchChangedForDamagePart(value); + }, + ), + 8.height, + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: adVM.vehiclePartsSearchResults.isEmpty ? adVM.vehicleDamageParts.length : adVM.vehiclePartsSearchResults.length, + itemBuilder: (BuildContext context, int index) { + VehiclePartModel vehiclePart = adVM.vehiclePartsSearchResults.isEmpty ? adVM.vehicleDamageParts[index] : adVM.vehiclePartsSearchResults[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; + } + adVM.vehicleDamageParts[index].isChecked = !(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) { + if (vehiclePart.isSelected!) { + return; + } + adVM.vehicleDamageParts[index].isChecked = !(adVM.vehicleDamageParts[index].isChecked!); + setState(() {}); + }, + ), + ), + ), + const SizedBox(width: 20), + vehiclePart.partName.toString().toText( + fontSize: 16, + color: vehiclePart.isSelected! ? MyColors.lightTextColor : MyColors.black, + ) + ], + ), + ), + const Divider(thickness: 1), + ], + ); + }, + ), + ), + SizedBox( + width: double.infinity, + child: ShowFillButton( + title: LocaleKeys.addDamagePart.tr(), + onPressed: () { + for (var value in adVM.vehicleDamageParts) { + if (value.isChecked! && !value.isSelected!) { + 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(); + } +} diff --git a/lib/views/advertisement/ad_duration_selection_sheet_content.dart b/lib/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart similarity index 77% rename from lib/views/advertisement/ad_duration_selection_sheet_content.dart rename to lib/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart index 2f41365..3841c55 100644 --- a/lib/views/advertisement/ad_duration_selection_sheet_content.dart +++ b/lib/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart @@ -15,14 +15,11 @@ import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; -class AdDurationSelectionSheetContent extends StatelessWidget { +class AdDurationSelectionSheet extends StatelessWidget { final bool isFromExtendAd; final bool isUpdateAdSelected; - const AdDurationSelectionSheetContent( - {super.key, - required this.isFromExtendAd, - required this.isUpdateAdSelected}); + const AdDurationSelectionSheet({super.key, required this.isFromExtendAd, required this.isUpdateAdSelected}); @override Widget build(BuildContext context) { @@ -33,10 +30,7 @@ class AdDurationSelectionSheetContent extends StatelessWidget { children: [ Row( children: [ - LocaleKeys.selectDuration - .tr() - .toText(fontSize: 22, isBold: true) - .paddingOnly(top: 10, left: 21, right: 21), + LocaleKeys.selectDuration.tr().toText(fontSize: 22, isBold: true).paddingOnly(top: 10, left: 21, right: 21), ], ), Expanded( @@ -56,32 +50,22 @@ class AdDurationSelectionSheetContent extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - ("${adDuration.days}${LocaleKeys.daysVar.tr()}") - .toString() - .toText(fontSize: 16, isBold: true), + ("${adDuration.days}${LocaleKeys.daysVar.tr()}").toString().toText(fontSize: 16, isBold: true), 4.height, - "Your Ad will be active for ${adDuration.days} Days and then you will need to extend it to keep it active. " - .toText( + "Your Ad will be active for ${adDuration.days} Days and then you will need to extend it to keep it active. ".toText( fontSize: 14, color: MyColors.lightTextColor, ), 12.height, - LocaleKeys.adCharges.tr().toText( - fontSize: 14, - color: MyColors.lightTextColor, - isBold: true), + LocaleKeys.adCharges.tr().toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - "${adDuration.price}" - .toText(fontSize: 22, isBold: true), + "${adDuration.price}".toText(fontSize: 22, isBold: true), 2.width, Padding( padding: const EdgeInsets.only(bottom: 4), - child: LocaleKeys.sar.tr().toText( - fontSize: 12, - color: MyColors.lightTextColor, - isBold: true), + child: LocaleKeys.sar.tr().toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), ), ], ), @@ -92,16 +76,14 @@ class AdDurationSelectionSheetContent extends StatelessWidget { ).toWhiteContainer( width: double.infinity, allPading: 12, - isBorderRequired: - adDuration.id == adVM.vehicleAdDurationId.selectedId, + isBorderRequired: adDuration.id == adVM.vehicleAdDurationId.selectedId, ), ).onPress(() { if (isFromExtendAd) { adVM.updateVehicleExtendAdDurationId( SelectionModel( selectedId: adDuration.id ?? 0, - selectedOption: - ("${adDuration.days} ${LocaleKeys.daysVar.tr()}"), + selectedOption: ("${adDuration.days} ${LocaleKeys.daysVar.tr()}"), itemPrice: adDuration.price!.toInt().toString(), ), ); @@ -110,8 +92,7 @@ class AdDurationSelectionSheetContent extends StatelessWidget { adVM.updateVehicleAdDurationId( SelectionModel( selectedId: adDuration.id ?? 0, - selectedOption: - ("${adDuration.days} ${LocaleKeys.daysVar.tr()}"), + selectedOption: ("${adDuration.days} ${LocaleKeys.daysVar.tr()}"), itemPrice: adDuration.price!.toInt().toString(), ), ); @@ -142,8 +123,7 @@ class AdDurationSelectionSheetContent extends StatelessWidget { return; } else { if (isFromExtendAd && !isUpdateAdSelected) { - navigateWithName(context, AppRoutes.paymentMethodsView, - arguments: PaymentTypes.extendAds); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.extendAds); return; } navigateReplaceWithName(context, AppRoutes.createAdView); @@ -155,8 +135,7 @@ class AdDurationSelectionSheetContent extends StatelessWidget { ); } - Widget showItem(String item, String value, - {Color valueColor = Colors.black}) { + Widget showItem(String item, String value, {Color valueColor = Colors.black}) { return Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, diff --git a/lib/views/advertisement/bottom_sheet_content.dart b/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart similarity index 95% rename from lib/views/advertisement/bottom_sheet_content.dart rename to lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart index 33b8fca..2db3127 100644 --- a/lib/views/advertisement/bottom_sheet_content.dart +++ b/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart @@ -15,14 +15,14 @@ import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; import 'package:easy_localization/easy_localization.dart'; -class BottomSheetListContent extends StatefulWidget { - const BottomSheetListContent({Key? key}) : super(key: key); +class BottomSheetAdDamagePartsContent extends StatefulWidget { + const BottomSheetAdDamagePartsContent({Key? key}) : super(key: key); @override - State createState() => _BottomSheetListContentState(); + State createState() => _BottomSheetAdDamagePartsContentState(); } -class _BottomSheetListContentState extends State { +class _BottomSheetAdDamagePartsContentState extends State { bool checkBoxValue = false; @override @@ -207,8 +207,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { (DropValue value) => adVM.updateVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), list: vehicleAdsSpecialServices, hint: LocaleKeys.selectService.tr(), - dropdownValue: - adVM.vehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.vehicleAdsSpecialServicesId.selectedId, adVM.vehicleAdsSpecialServicesId.selectedOption, "") : null, + dropdownValue: adVM.vehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.vehicleAdsSpecialServicesId.selectedId, adVM.vehicleAdsSpecialServicesId.selectedOption, "") : null, ); }, ), @@ -266,8 +265,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { ], if (adVM.vehicleAdsSpecialServicesId.selectedId != 3 && adVM.vehicleAdsSpecialServicesId.selectedId != 1) ...[ descriptionCard( - description: - adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "Some Dummy Service Description!!", + description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "Some Dummy Service Description!!", ), ], if (adVM.adSSTimeSlots.isNotEmpty) ...[ diff --git a/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart b/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart new file mode 100644 index 0000000..44aaca8 --- /dev/null +++ b/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart @@ -0,0 +1,91 @@ +import 'dart:async'; +import 'dart:developer'; + +import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; +import 'package:mc_common_app/models/general_models/widgets_models.dart'; +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/theme/colors.dart'; +import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; + +class AdDamagePartPicturesSheet extends StatefulWidget { + final List adDamageReportList; + + const AdDamagePartPicturesSheet({super.key, required this.adDamageReportList}); + + @override + State createState() => _AdDamagePartPicturesSheetState(); +} + +class _AdDamagePartPicturesSheetState extends State { + List vehicleDamageCards = []; + + @override + void initState() { + scheduleMicrotask(() => populateDamagePartPictures()); + super.initState(); + } + + void populateDamagePartPictures() { + for (var element in widget.adDamageReportList) { + ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); + + VehicleDamageCard vehicleDamageCard = VehicleDamageCard( + partSelectedId: SelectionModel( + selectedId: element.vehicleDamagePartID!, + selectedOption: element.partName ?? "", + ), + partImages: [imageModel], + ); + vehicleDamageCards.add(vehicleDamageCard); + } + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height / 1.2, + child: ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: vehicleDamageCards.length, + itemBuilder: (BuildContext context, int index) { + VehicleDamageCard vehicleDamageCard = vehicleDamageCards[index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + vehicleDamageCard.partSelectedId!.selectedOption.toText(fontSize: 18, color: MyColors.darkTextColor), + PickedFilesContainer( + pickedFiles: vehicleDamageCard.partImages ?? [], + isReview: true, + onCrossPressedSecondary: (imageIndex, filePath) {}, + index: index, + onAddFilePressed: () {}, + ), + ], + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4), + ); + }, + ).paddingOnly(top: 10), + ); + } + + Widget showItem(String item, String value, {Color valueColor = Colors.black}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + item.toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + 4.width, + value.toText(fontSize: 12, color: valueColor, isBold: true), + ], + ); + } +} diff --git a/lib/views/advertisement/ads_images_slider.dart b/lib/views/advertisement/components/ads_images_corousel_widget.dart similarity index 91% rename from lib/views/advertisement/ads_images_slider.dart rename to lib/views/advertisement/components/ads_images_corousel_widget.dart index cdae3b0..61f5ee0 100644 --- a/lib/views/advertisement/ads_images_slider.dart +++ b/lib/views/advertisement/components/ads_images_corousel_widget.dart @@ -3,16 +3,16 @@ 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'; -class CarouselWithIndicatorDemo extends StatefulWidget { +class AdImagesCorouselWidget extends StatefulWidget { final List vehicleImages; - const CarouselWithIndicatorDemo({super.key, required this.vehicleImages}); + const AdImagesCorouselWidget({super.key, required this.vehicleImages}); @override State createState() => _CarouselWithIndicatorState(); } -class _CarouselWithIndicatorState extends State { +class _CarouselWithIndicatorState extends State { int _current = 0; final CarouselController _controller = CarouselController(); diff --git a/lib/views/advertisement/ads_list.dart b/lib/views/advertisement/components/ads_list_widget.dart similarity index 99% rename from lib/views/advertisement/ads_list.dart rename to lib/views/advertisement/components/ads_list_widget.dart index 0dd45c1..25c751d 100644 --- a/lib/views/advertisement/ads_list.dart +++ b/lib/views/advertisement/components/ads_list_widget.dart @@ -14,13 +14,13 @@ import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; -class BuildAdsList extends StatelessWidget { +class AdsListWidget extends StatelessWidget { final List adsList; final ScrollPhysics? scrollPhysics; final bool isAdsFragment; final bool shouldShowAdStatus; - const BuildAdsList({ + const AdsListWidget({ Key? key, required this.adsList, this.scrollPhysics, diff --git a/lib/views/advertisement/create_ad_progress_steps.dart b/lib/views/advertisement/components/create_ad_progress_steps_widget.dart similarity index 82% rename from lib/views/advertisement/create_ad_progress_steps.dart rename to lib/views/advertisement/components/create_ad_progress_steps_widget.dart index fee89ac..926ce6d 100644 --- a/lib/views/advertisement/create_ad_progress_steps.dart +++ b/lib/views/advertisement/components/create_ad_progress_steps_widget.dart @@ -68,10 +68,10 @@ class CreateAdProgressSteps extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - buildStep(MyAssets.carIcon, (LocaleKeys.vehicleVar.tr() + " \n" + LocaleKeys.detailsVar.tr()), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 1), - buildStep(MyAssets.carHitIcon, (LocaleKeys.damageVar.tr() + " \n" + LocaleKeys.partsVar.tr()), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 2), - buildStep(MyAssets.clockIcon, (LocaleKeys.additional.tr() + " \n" + LocaleKeys.detailsVar.tr()), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 3), - buildStep(MyAssets.reviewIcon, (LocaleKeys.review.tr() + " \n"+ LocaleKeys.adVar.tr()), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 4), + buildStep(MyAssets.carIcon, ("${LocaleKeys.vehicleVar.tr()} \n${LocaleKeys.detailsVar.tr()}"), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 1), + buildStep(MyAssets.carHitIcon, ("${LocaleKeys.damageVar.tr()} \n${LocaleKeys.partsVar.tr()}"), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 2), + buildStep(MyAssets.clockIcon, ("${LocaleKeys.additional.tr()} \n${LocaleKeys.detailsVar.tr()}"), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 3), + buildStep(MyAssets.reviewIcon, ("${LocaleKeys.review.tr()} \n${LocaleKeys.adVar.tr()}"), getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 4), ], ), ], diff --git a/lib/views/advertisement/components/damage_pictures_bottom_sheet.dart b/lib/views/advertisement/components/damage_pictures_bottom_sheet.dart new file mode 100644 index 0000000..1eb22c2 --- /dev/null +++ b/lib/views/advertisement/components/damage_pictures_bottom_sheet.dart @@ -0,0 +1,110 @@ +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/services_models/item_model.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/view_models/appointments_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/theme/colors.dart'; +import 'package:mc_common_app/widgets/empty_widget.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; + +class DamagePicturesList extends StatefulWidget { + final int serviceId; + + const DamagePicturesList(this.serviceId, {super.key}); + + @override + State createState() => _DamagePicturesListState(); +} + +class _DamagePicturesListState extends State { + @override + void initState() { + super.initState(); + context.read().getServiceItems(widget.serviceId); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height / 1.2, + child: Consumer( + builder: (context, appointmentsVM, _) { + if (appointmentsVM.state == ViewState.busy) { + return Center(child: CircularProgressIndicator()); + } + return appointmentsVM.serviceItemsFromApi.isEmpty + ? const EmptyWidget() + : ListView.separated( + itemCount: appointmentsVM.serviceItemsFromApi.length, + itemBuilder: (BuildContext context, int index) { + ItemData serviceItemModel = appointmentsVM.serviceItemsFromApi[index]; + return SizedBox( + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + serviceItemModel.name.toString().toText(fontSize: 16, isBold: true), + 4.height, + showItem(LocaleKeys.availableforAppointment.tr() + ":", (serviceItemModel.isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green), + showItem(LocaleKeys.allowingWorkshopService.tr() + ":", (serviceItemModel.isAppointmentCompanyLoc ?? false) ? "Yes" : "No", valueColor: Colors.green), + showItem(LocaleKeys.allowingHomeService.tr() + ":", (serviceItemModel.isAppointmentCustomerLoc ?? false) ? "Yes" : "No", valueColor: Colors.green), + 12.height, + LocaleKeys.serviceAmount.tr().toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + serviceItemModel.price!.toText(fontSize: 22, isBold: true), + 2.width, + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: LocaleKeys.sar.tr().toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ), + ], + ), + ], + ), + ), + // Padding( + // padding: const EdgeInsets.all(4.0), + // child: SvgPicture.asset( + // MyAssets.icEdit, + // width: 16, + // height: 16, + // ), + // ) + ], + ), + ).toWhiteContainer(width: double.infinity, allPading: 12); + }, + separatorBuilder: (BuildContext context, int index) { + return 12.height; + }, + padding: const EdgeInsets.all(20), + ); + }, + ), + ); + } + + Widget showItem(String item, String value, {Color valueColor = Colors.black}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + item.toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + 4.width, + value.toText(fontSize: 12, color: valueColor, isBold: true), + ], + ); + } +} diff --git a/lib/views/advertisement/network_images_container.dart b/lib/views/advertisement/components/network_images_container_widget.dart similarity index 100% rename from lib/views/advertisement/network_images_container.dart rename to lib/views/advertisement/components/network_images_container_widget.dart diff --git a/lib/views/advertisement/picked_images_container.dart b/lib/views/advertisement/components/picked_images_container_widget.dart similarity index 89% rename from lib/views/advertisement/picked_images_container.dart rename to lib/views/advertisement/components/picked_images_container_widget.dart index 2762d80..6089489 100644 --- a/lib/views/advertisement/picked_images_container.dart +++ b/lib/views/advertisement/components/picked_images_container_widget.dart @@ -64,17 +64,6 @@ class PickedFilesContainer extends StatelessWidget { }, ), ); - // return Wrap( - // children: pickedImages - // .map((file) => BuildImageContainer( - // file: file, - // onCrossPressedPrimary: onCrossPressedPrimary, - // onCrossPressedSecondary: onCrossPressedSecondary, - // index: index, - // isReview: isReview, - // )) - // .toList(), - // ); } } @@ -107,8 +96,8 @@ class BuildFilesContainer extends StatelessWidget { children: [ isPdf ? Container( - height: 72, - width: 70, + height: 75, + width: 73, margin: const EdgeInsets.all(8), decoration: BoxDecoration( border: Border.all( @@ -121,8 +110,8 @@ class BuildFilesContainer extends StatelessWidget { ? Image.network( image.filePath!, fit: BoxFit.fill, - height: 72, - width: 70, + height: 75, + width: 73, ).paddingAll(8) : Image.file( File(image.filePath!), diff --git a/lib/views/advertisement/create_ad_view.dart b/lib/views/advertisement/create_ad_view.dart index 3d26ada..26e7da6 100644 --- a/lib/views/advertisement/create_ad_view.dart +++ b/lib/views/advertisement/create_ad_view.dart @@ -9,14 +9,13 @@ import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_duration_ 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/views/advertisement/components/create_ad_progress_steps_widget.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; - class CreateAdView extends StatefulWidget { const CreateAdView({Key? key}) : super(key: key); @@ -37,7 +36,7 @@ class _CreateAdViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: adVM.isAdEditEnabled ? LocaleKeys.updateAd.tr(): LocaleKeys.createAd.tr(), + title: adVM.isAdEditEnabled ? LocaleKeys.updateAd.tr() : LocaleKeys.createAd.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => adVM.onBackButtonPressed(context), diff --git a/lib/views/advertisement/select_ad_type_view.dart b/lib/views/advertisement/select_ad_type_view.dart index 22d9b0c..02c2720 100644 --- a/lib/views/advertisement/select_ad_type_view.dart +++ b/lib/views/advertisement/select_ad_type_view.dart @@ -1,30 +1,26 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; -import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; -import 'package:mc_common_app/main.dart'; import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; import 'package:mc_common_app/models/general_models/widgets_models.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/views/advertisement/ad_duration_selection_sheet_content.dart'; +import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart'; import 'package:mc_common_app/widgets/bottom_sheet.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; - class SelectAdTypeView extends StatelessWidget { - final bool isProvider; + final List arguments; // [0] isProviderOrCustomer [1] isFromExtendAd - const SelectAdTypeView({ - Key? key, - this.isProvider = true, - }) : super(key: key); + const SelectAdTypeView({Key? key, required this.arguments}) : super(key: key); Widget getVehicleAdTypeIcon(VehicleType vehicleTypeEnum) { switch (vehicleTypeEnum) { @@ -42,26 +38,10 @@ class SelectAdTypeView extends StatelessWidget { } } - // bool checkSelection(VehicleTypeModel vtype, AdVM adVM) { - // bool value = false; - // if (adVM.vehicleTypes.isNotEmpty) { - // for (var vehicle in adVM.vehicleTypes) { - // if (vtype.id == adVM.previousADDetails?.vehicle?.vehicleType) { - // value = true; - // break; - // } - // } - // } - // return value; - // } - // - // clearAll(BuildContext context) { - // AdVM adVM = context.read(); - // adVM.clearEditValues(); - // } - @override Widget build(BuildContext context) { + bool isProvider = arguments[0]; + bool isFromExtendAd = arguments[1]; return Scaffold( appBar: CustomAppBar( title: LocaleKeys.selectAdType.tr(), @@ -79,14 +59,12 @@ class SelectAdTypeView extends StatelessWidget { VehicleTypeModel vehicleTypeModel = adVM.vehicleTypes[index]; return InkWell( onTap: () { - adVM.updateSelectionVehicleTypeId( - SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""), - ); + adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: "")); if (adVM.isAdEditEnabled) { - adVM.autoFillSelectedVehicleAdsDuration(); adVM.autoFillSelectedVehicleAdsDetails(); } - showMyBottomSheet(context, child: const AdDurationSelectionSheetContent(isUpdateAdSelected: false, isFromExtendAd: false)); + log("isUpdateAdSelected: ${adVM.isAdEditEnabled}}"); + showMyBottomSheet(context, child: AdDurationSelectionSheet(isUpdateAdSelected: adVM.isAdEditEnabled, isFromExtendAd: isFromExtendAd)); }, child: SizedBox( width: double.infinity, @@ -110,7 +88,7 @@ class SelectAdTypeView extends StatelessWidget { Row( children: [ LocaleKeys.duration.tr().toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - LocaleKeys.validUntilSubscriptionExpiration.tr() .toText(fontSize: 13, isBold: true), + LocaleKeys.validUntilSubscriptionExpiration.tr().toText(fontSize: 13, isBold: true), ], ).paddingOnly(top: 5, bottom: 5), ] else ...[ @@ -140,7 +118,7 @@ class SelectAdTypeView extends StatelessWidget { ), ], ), - ).toWhiteContainer(width: double.infinity, isBorderRequired: vehicleTypeModel.isSelected! ? true : false, pading: const EdgeInsets.symmetric(horizontal: 20, vertical: 10)), + ).toWhiteContainer(width: double.infinity, isBorderRequired: vehicleTypeModel.isSelected! ? true : false, pading: const EdgeInsets.symmetric(horizontal: 20, vertical: 10)), ); }, separatorBuilder: (BuildContext context, int index) { @@ -160,7 +138,7 @@ class SelectAdTypeView extends StatelessWidget { LocaleKeys.adsRemainingVar.tr().toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true), ], ), - Text.rich( + Text.rich( TextSpan( children: [ TextSpan( diff --git a/lib/views/appointments/book_appointment_schedules_view.dart b/lib/views/appointments/book_appointment_schedules_view.dart index 234cb9c..ab527ea 100644 --- a/lib/views/appointments/book_appointment_schedules_view.dart +++ b/lib/views/appointments/book_appointment_schedules_view.dart @@ -24,7 +24,7 @@ class ScreenArgumentsForAppointmentDetailPage { class BookAppointmentSchedulesView extends StatelessWidget { final ScreenArgumentsForAppointmentDetailPage screenArgumentsForAppointmentDetailPage; - BookAppointmentSchedulesView({Key? key, required this.screenArgumentsForAppointmentDetailPage}) : super(key: key); + const BookAppointmentSchedulesView({Key? key, required this.screenArgumentsForAppointmentDetailPage}) : super(key: key); @override Widget build(BuildContext context) { @@ -47,14 +47,14 @@ class BookAppointmentSchedulesView extends StatelessWidget { itemBuilder: (BuildContext context, int scheduleIndex) { ServiceAppointmentScheduleModel scheduleData = appointmentsVM.serviceAppointmentScheduleList[scheduleIndex]; return ExpansionTile( - tilePadding: EdgeInsets.symmetric(horizontal: 21, vertical: 10), - childrenPadding: EdgeInsets.only(left: 16, bottom: 10, right: 16), + tilePadding: const EdgeInsets.symmetric(horizontal: 21, vertical: 10), + childrenPadding: const EdgeInsets.only(left: 16, bottom: 10, right: 16), title: Column( children: [ Row( children: [ Expanded( - child: (LocaleKeys.schedule.tr() + " ${scheduleIndex + 1}").toText(fontSize: 20, isBold: true), + child: ("${LocaleKeys.schedule.tr()} ${scheduleIndex + 1}").toText(fontSize: 20, isBold: true), ), ], ), @@ -62,7 +62,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ (LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - ("${scheduleData.appointmentType == 2 ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()}").toText(fontSize: 12, isBold: true).expand(), + (scheduleData.appointmentType == 2 ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(), ], ), Column( @@ -70,7 +70,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { children: [ 5.height, ListView.builder( - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].servicesListInAppointment!.length, itemBuilder: (BuildContext context, int serviceIndex) { diff --git a/lib/views/appointments/book_appointment_services_view.dart b/lib/views/appointments/book_appointment_services_view.dart index 909734e..2d581b1 100644 --- a/lib/views/appointments/book_appointment_services_view.dart +++ b/lib/views/appointments/book_appointment_services_view.dart @@ -1,6 +1,4 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; @@ -8,15 +6,15 @@ import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/appointments_view_model.dart'; -import 'package:mc_common_app/views/advertisement/custom_add_button.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/common_widgets/custom_add_button_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; class BookAppointmentServicesView extends StatelessWidget { - BookAppointmentServicesView({Key? key}) : super(key: key); + const BookAppointmentServicesView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -31,8 +29,7 @@ class BookAppointmentServicesView extends StatelessWidget { }, ), body: Consumer( - builder: (BuildContext context, AppointmentsVM appointmentsVM, - Widget? child) { + builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -40,14 +37,12 @@ class BookAppointmentServicesView extends StatelessWidget { CustomAddButton( needsBorder: true, bgColor: MyColors.white, - onTap: () => appointmentsVM.openTheAddServiceBottomSheet( - context, appointmentsVM), + onTap: () => appointmentsVM.openTheAddServiceBottomSheet(context, appointmentsVM), text: LocaleKeys.addServices.tr(), icon: Container( height: 24, width: 24, - decoration: const BoxDecoration( - shape: BoxShape.circle, color: MyColors.darkTextColor), + decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), child: const Icon(Icons.add, color: MyColors.white), ), ).horPaddingMain(), @@ -56,56 +51,34 @@ class BookAppointmentServicesView extends StatelessWidget { shrinkWrap: true, itemCount: appointmentsVM.servicesInCurrentAppointment.length, itemBuilder: (BuildContext context, int serviceIndex) { - ServiceModel serviceData = appointmentsVM - .servicesInCurrentAppointment[serviceIndex]; + ServiceModel serviceData = appointmentsVM.servicesInCurrentAppointment[serviceIndex]; return Column( children: [ Row( children: [ Expanded( - child: (serviceData.serviceDescription ?? "") - .toText(fontSize: 15, isBold: true), + child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true), ), - IconButton( - onPressed: () => appointmentsVM - .removeServiceInCurrentAppointment( - serviceIndex), - icon: Icon(Icons.delete_outline, - color: MyColors.redColor), - ) + IconButton(onPressed: () => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex), icon: const Icon(Icons.delete_outline, color: MyColors.redColor)) ], ), if (true) ...[ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (LocaleKeys.serviceLocation.tr()).toText( - fontSize: 12, - color: MyColors.lightTextColor, - isBold: true), - (serviceData.isHomeSelected - ? serviceData.homeLocation - : LocaleKeys.workshop.tr()) - .toText(fontSize: 12, isBold: true) - .expand(), + (LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + (serviceData.isHomeSelected ? serviceData.homeLocation : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(), ], ), 5.height, Column( - children: List.generate( - serviceData.serviceItems!.length, (itemIndex) { - ItemData itemData = - serviceData.serviceItems![itemIndex]; + children: List.generate(serviceData.serviceItems!.length, (itemIndex) { + ItemData itemData = serviceData.serviceItems![itemIndex]; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "${itemData.name}: ".toText( - fontSize: 13, - color: MyColors.lightTextColor, - isBold: true), - ("${itemData.price}") - .toText(fontSize: 13, isBold: true) - .expand(), + "${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true), + ("${itemData.price}").toText(fontSize: 13, isBold: true).expand(), ], ); }), @@ -114,33 +87,15 @@ class BookAppointmentServicesView extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - ((appointmentsVM - .servicesInCurrentAppointment[ - serviceIndex] - .currentTotalServicePrice) - .toString()) - .toText(fontSize: 32, isBold: true), + ((appointmentsVM.servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true), 2.width, - LocaleKeys.sar - .tr() - .toText( - color: MyColors.lightTextColor, - fontSize: 16, - isBold: true) - .paddingOnly(bottom: 5), - Icon(Icons.arrow_drop_down, size: 30) + LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), + const Icon(Icons.arrow_drop_down, size: 30) ], - ).onPress(() => appointmentsVM.priceBreakDownClicked( - context, - appointmentsVM - .servicesInCurrentAppointment[serviceIndex])), + ).onPress(() => appointmentsVM.priceBreakDownClicked(context, appointmentsVM.servicesInCurrentAppointment[serviceIndex])), ], ], - ).toWhiteContainer( - width: double.infinity, - allPading: 12, - margin: const EdgeInsets.symmetric( - horizontal: 21, vertical: 10)); + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); }, ).expand(), Row( diff --git a/lib/views/appointments/widgets/common_appointment_slider_widget.dart b/lib/views/appointments/widgets/common_appointment_slider_widget.dart index df71f61..b29d45b 100644 --- a/lib/views/appointments/widgets/common_appointment_slider_widget.dart +++ b/lib/views/appointments/widgets/common_appointment_slider_widget.dart @@ -14,7 +14,7 @@ import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/view_models/appointments_view_model.dart'; import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart'; -import 'package:mc_common_app/views/advertisement/custom_add_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/custom_add_button_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; @@ -223,8 +223,7 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - (AppState().currentAppType == AppType.provider ? appointmentListModel!.customerName ?? "" : appointmentListModel!.branchName ?? "") - .toText(color: MyColors.black, isBold: true, fontSize: 16), + (AppState().currentAppType == AppType.provider ? appointmentListModel!.customerName ?? "" : appointmentListModel!.branchName ?? "").toText(color: MyColors.black, isBold: true, fontSize: 16), Row( children: [ MyAssets.miniClock.buildSvg(height: 12), diff --git a/lib/views/common_fragments/ads_fragment.dart b/lib/views/common_fragments/ads_fragment.dart index c2131da..fe3a368 100644 --- a/lib/views/common_fragments/ads_fragment.dart +++ b/lib/views/common_fragments/ads_fragment.dart @@ -11,7 +11,7 @@ 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/ads_list.dart'; +import 'package:mc_common_app/views/advertisement/components/ads_list_widget.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/common_widgets/categories_list.dart'; @@ -102,10 +102,10 @@ class AdsFragment extends StatelessWidget { if (adVM.adsFiltersCounter == 0) ...[ 16.height, FiltersList( - filterList: adVM.exploreAdsFilterOptions, - onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum()), - needLeftPadding: false) - .paddingOnly(left: 21), + filterList: adVM.exploreAdsFilterOptions, + onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum()), + needLeftPadding: false, + ).paddingOnly(left: 21), ] ] else ...[ 16.height, @@ -126,7 +126,7 @@ class AdsFragment extends StatelessWidget { await adVM.getExploreAds(); await adVM.getMyAds(); }, - child: BuildAdsList(isAdsFragment: true, shouldShowAdStatus: !adVM.isExploreAdsTapped, adsList: getAdsList(adVM)), + child: AdsListWidget(isAdsFragment: true, shouldShowAdStatus: !adVM.isExploreAdsTapped, adsList: getAdsList(adVM)), ), ) ], @@ -134,7 +134,7 @@ class AdsFragment extends StatelessWidget { ), floatingActionButton: FloatingActionButton( onPressed: () async { - navigateWithName(context, AppRoutes.selectAdTypeView, arguments: injector.get().currentAppType == AppType.provider); + navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [injector.get().currentAppType == AppType.provider, false]); }, backgroundColor: MyColors.darkPrimaryColor, child: const Icon(Icons.add, color: MyColors.white), diff --git a/lib/views/common_fragments/my_requests_fragment.dart b/lib/views/common_fragments/my_requests_fragment.dart index 8dee432..b56da74 100644 --- a/lib/views/common_fragments/my_requests_fragment.dart +++ b/lib/views/common_fragments/my_requests_fragment.dart @@ -53,7 +53,7 @@ class MyRequestsFragment extends StatelessWidget { ) : ListView.separated( itemBuilder: (context, index) { - return RequestItem(request: requestsVM.myFilteredRequests[index], appType: AppType.provider, requestIndex: index); + return RequestItem(request: requestsVM.myFilteredRequests[index], appType: AppState().currentAppType, requestIndex: index); }, separatorBuilder: (context, index) { return 16.height; diff --git a/lib/views/requests/create_request_page.dart b/lib/views/requests/create_request_page.dart index ef572ae..16c209c 100644 --- a/lib/views/requests/create_request_page.dart +++ b/lib/views/requests/create_request_page.dart @@ -7,7 +7,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.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:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; diff --git a/lib/views/requests/widget/request_item.dart b/lib/views/requests/widget/request_item.dart index 1d6fa66..dc2e056 100644 --- a/lib/views/requests/widget/request_item.dart +++ b/lib/views/requests/widget/request_item.dart @@ -65,13 +65,9 @@ class RequestItem extends StatelessWidget { ), ], 2.height, - request.cityName.toText( - color: MyColors.lightTextColor, - ), + request.cityName.toText(color: MyColors.lightTextColor), if (request.createdOn != null) ...[ - DateTime.parse(request.createdOn!).getTimeAgo().toText( - color: MyColors.lightTextColor, - ), + DateTime.parse(request.createdOn!).getTimeAgo().toText(color: MyColors.lightTextColor), ], ], ) @@ -92,15 +88,7 @@ class RequestItem extends StatelessWidget { isBold: true, ), 2.width, - LocaleKeys.sar - .tr() - .toText( - color: MyColors.lightTextColor, - fontSize: 10, - ) - .paddingOnly( - bottom: 3, - ), + LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10).paddingOnly(bottom: 3), ], ), request.requestStatus == RequestStatus.submitted diff --git a/lib/widgets/common_widgets/app_bar.dart b/lib/widgets/common_widgets/app_bar.dart index 0dec6b6..1b3bcf4 100644 --- a/lib/widgets/common_widgets/app_bar.dart +++ b/lib/widgets/common_widgets/app_bar.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -20,7 +22,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { final String profileImageUrl; final bool isDrawerEnabled; final VoidCallback? onTap; - final VoidCallback? onBackButtonTapped; + final Function? onBackButtonTapped; final double? leadingWidth; const CustomAppBar({ @@ -53,73 +55,70 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { centerTitle: isTitleCenter ?? true, leading: isDrawerEnabled ? InkWell( - onTap: onTap, - child: Row( - children: [ - profileImageUrl.isEmpty && AppState().getUser.data!.userInfo!.userLocalImage != null - ? Image.file( - AppState().getUser.data!.userInfo!.userLocalImage!, - width: 34, - height: 34, - fit: BoxFit.fill, - ).toCircle(borderRadius: 100) - : profileImageUrl.isEmpty && AppState().getUser.data!.userInfo!.userImageUrl != null - ? CachedNetworkImage( - imageUrl: AppState().getUser.data!.userInfo!.userImageUrl, - imageBuilder: (context, imageProvider) => - Container( - decoration: BoxDecoration( - image: DecorationImage( - image: imageProvider, - fit: BoxFit.cover, - ), - ), - ), - placeholder: (context, url) => const Center(child: CircularProgressIndicator()), - errorWidget: (context, url, error) => const Icon(Icons.supervised_user_circle_outlined), - fadeInCurve: Curves.easeIn, - width: 34, - height: 34, - fit: BoxFit.fill, - fadeInDuration: Duration(milliseconds: 1000), - useOldImageOnUrlChange: false - ).toCircle(borderRadius: 100) - : Image.asset( - MyAssets.carBanner, - width: 34, - height: 34, - fit: BoxFit.fill, - ).toCircle(borderRadius: 100), - 10.width, - SvgPicture.asset(MyAssets.dashboardDrawerIcon), - ], - ).paddingOnly(left: 21), - ) + onTap: onTap, + child: Row( + children: [ + profileImageUrl.isEmpty && AppState().getUser.data!.userInfo!.userLocalImage != null + ? Image.file( + AppState().getUser.data!.userInfo!.userLocalImage!, + width: 34, + height: 34, + fit: BoxFit.fill, + ).toCircle(borderRadius: 100) + : profileImageUrl.isEmpty && AppState().getUser.data!.userInfo!.userImageUrl != null + ? CachedNetworkImage( + imageUrl: AppState().getUser.data!.userInfo!.userImageUrl, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover, + ), + ), + ), + placeholder: (context, url) => const Center(child: CircularProgressIndicator()), + errorWidget: (context, url, error) => const Icon(Icons.supervised_user_circle_outlined), + fadeInCurve: Curves.easeIn, + width: 34, + height: 34, + fit: BoxFit.fill, + fadeInDuration: const Duration(milliseconds: 1000), + useOldImageOnUrlChange: false) + .toCircle(borderRadius: 100) + : Image.asset( + MyAssets.carBanner, + width: 34, + height: 34, + fit: BoxFit.fill, + ).toCircle(borderRadius: 100), + 10.width, + SvgPicture.asset(MyAssets.dashboardDrawerIcon), + ], + ).paddingOnly(left: 21), + ) : isRemoveBackButton - ? null - : Row( - children: [ - 21.width, - IconButton( - icon: const Icon( - Icons.arrow_back_ios, - color: Colors.black, - size: 16, - ), - onPressed: onBackButtonTapped ?? - () { - Navigator.pop(context); - }, - ).toContainer( - paddingAll: 0, - borderRadius: 100, - borderColor: MyColors.lightGreyEFColor, - isEnabledBorder: true, - height: 40, - width: 40, - ), - ], - ), + ? null + : Row( + children: [ + 21.width, + const Icon(Icons.arrow_back_ios, color: Colors.black, size: 16) + .toContainer( + padding: const EdgeInsets.only(left: 5), + borderRadius: 100, + borderColor: MyColors.lightGreyEFColor, + isEnabledBorder: true, + height: 40, + width: 40, + ) + .onPress(() { + if (onBackButtonTapped != null) { + onBackButtonTapped!(); + } else { + Navigator.pop(context); + } + }), + ], + ), iconTheme: IconThemeData( color: backIconColor ?? Colors.black, //change your color here ), diff --git a/lib/views/advertisement/custom_add_button.dart b/lib/widgets/common_widgets/custom_add_button_widget.dart similarity index 100% rename from lib/views/advertisement/custom_add_button.dart rename to lib/widgets/common_widgets/custom_add_button_widget.dart