Merge branch 'refs/heads/master' into aamir_dev

# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/generated/codegen_loader.g.dart
#	lib/generated/locale_keys.g.dart
aamir_dev
Aamir Muhammad 1 year ago
commit 9efb174e0c

@ -745,6 +745,16 @@
"active": "نشط", "active": "نشط",
"paymentType": "نوع الدفع", "paymentType": "نوع الدفع",
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء", "searchByCreatedDate": "البحث حسب تاريخ الإنشاء",
"cityNameMandatory": "المدينة إلزامية",
"genderMandatory": "الجنس إلزامي",
"updateCity": "تحديث المدينة",
"userGender": "جنس",
"userMale": "ذكر",
"userFemale": "أنثى",
"maxFileSelection": "يمكنك تحديد الحد الأقصى لملفات 7",
"maxFileSize": "يجب أن يكون حجم كل ملف أقل من 2 ميغابايت",
"onlyJPGandPNG": "يُسمح فقط بملفات JPG وPNG",
"expiryDate": "تاريخ انتهاء الصلاحية",
"dealCompleted": "تم إتمام الصفقة", "dealCompleted": "تم إتمام الصفقة",
"theDealNotCompleted": "لم تكتمل الصفقة", "theDealNotCompleted": "لم تكتمل الصفقة",
"cancelRequest": "أريد إلغاء الطلب.", "cancelRequest": "أريد إلغاء الطلب.",
@ -765,16 +775,16 @@
"tapToSelect": "اضغط للاختيار", "tapToSelect": "اضغط للاختيار",
"noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.", "noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.",
"requestCreatedOn": "تم إنشاء الطلب في", "requestCreatedOn": "تم إنشاء الطلب في",
"cityNameMandatory": "المدينة إلزامية", "online": "عبر الإنترنت",
"genderMandatory": "الجنس إلزامي", "deliveryStatus": "حالة توصيلك / الشحن هي:",
"updateCity": "تحديث المدينة", "markAsCompleted": "ضع علامة كمكتمل",
"userGender": "جنس", "searchByServiceDelivery": "البحث حسب خدمة التوصيل",
"userMale": "ذكر", "searchByMobileNumber": "البحث بواسطة رقم الجوال",
"userFemale": "أنثى", "enterMobileNumber": "أدخل رقم الجوال",
"maxFileSelection" :"يمكنك تحديد الحد الأقصى لملفات 7", "enterCustomerName": "أدخل اسم العميل",
"maxFileSize": "يجب أن يكون حجم كل ملف أقل من 2 ميغابايت", "tapToView": "انقر لعرض",
"onlyJPGandPNG": "يُسمح فقط بملفات JPG وPNG", "noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.",
"expiryDate": "تاريخ انتهاء الصلاحية" "copySelectedItems": "نسخ العناصر المحددة"
} }

@ -738,7 +738,6 @@
"blockedByAdmin": "Blocked by admin", "blockedByAdmin": "Blocked by admin",
"active": "Active", "active": "Active",
"paymentType": "Payment Type", "paymentType": "Payment Type",
"searchByCreatedDate": "Search By Created Date",
"dealCompleted": "The Deal Completed", "dealCompleted": "The Deal Completed",
"theDealNotCompleted": "The Deal Not Completed", "theDealNotCompleted": "The Deal Not Completed",
"cancelRequest": "I want to cancel the request.", "cancelRequest": "I want to cancel the request.",
@ -759,6 +758,32 @@
"tapToSeeItems": "Tap to see items", "tapToSeeItems": "Tap to see items",
"noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.", "noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.",
"requestCreatedOn": "Request created on", "requestCreatedOn": "Request created on",
"online": "Online",
"searchByCreatedDate": "Search By Created Date",
"updateUserDetails": "Update User Details",
"enterNewFirstName": "Enter First Name",
"enterNewLastName": "Enter Last Name",
"userDetailsUpdated": "User Details is Updated",
"cityNameMandatory": "City is mandatory",
"genderMandatory": "Gender is mandatory",
"updateCity": "Update City",
"userGender": "Gender",
"userMale": "Male",
"userFemale": "Female",
"maxFileSelection": "You can select a maximum of 7 files",
"maxFileSize": "Each file size must be less than 2 MB",
"onlyJPGandPNG": "Only JPG and PNG files are allowed",
"expiryDate": "Expiry Date",
"deliveryStatus": "Your Delivery / Shipping Status is:",
"markAsCompleted": "Mark as Completed",
"searchByServiceDelivery": "Search by Service Delivery",
"searchByMobileNumber": "Search by Mobile Number",
"enterMobileNumber": "Enter Mobile Number",
"enterCustomerName": "Enter Customer Name",
"tapToView": "Tap to view",
"noServicesAvailableToCopy": "There are no services available in this branch to copy.",
"copySelectedItems": "Copy Selected Items"
"requestCreatedOn": "Request created on",
"updateUserDetails": "Update User Details", "updateUserDetails": "Update User Details",
"enterNewFirstName": "Enter First Name", "enterNewFirstName": "Enter First Name",
"enterNewLastName": "Enter Last Name", "enterNewLastName": "Enter Last Name",

@ -56,7 +56,7 @@ class ApiConsts {
static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get"; static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get";
static String serviceProviderServiceCreate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create"; static String serviceProviderServiceCreate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create";
static String serviceProviderServiceUpdate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update"; static String serviceProviderServiceUpdate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update";
static String serviceProviderServiceStatusUpdate = "${baseUrlServices}api/ServiceProviders/CategoryAndServiceDeactivateBySP"; static String serviceProviderServiceStatusUpdate = "${baseUrlServices}api/ServiceProviders/CategoryAndService_ActivateDeactivateBySP";
static String getProviderServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get"; static String getProviderServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String setScheduleInactive = "${baseUrlServices}api/ServiceProviders/BranchAppointmentSchedule_IsActiveUpdate"; static String setScheduleInactive = "${baseUrlServices}api/ServiceProviders/BranchAppointmentSchedule_IsActiveUpdate";
static String serviceProviderAppointmentGetByCategoryOrService = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_GetByCategoryOrService"; static String serviceProviderAppointmentGetByCategoryOrService = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_GetByCategoryOrService";
@ -257,11 +257,10 @@ class GlobalConsts {
return appInvitationMessageEn; return appInvitationMessageEn;
} }
// Attachment Values // Attachment Values
int maxFileCount = 7; static int maxFileCount = 7;
int maxFileSizeInBytes = 2 * 1024 * 1024; static int maxFileSizeInBytes = 2 * 1024 * 1024;
} }
class MyAssets { class MyAssets {
@ -403,6 +402,4 @@ class SignalrConsts {
// General // General
static String sendMessageGeneral = "SendMessageGeneral"; static String sendMessageGeneral = "SendMessageGeneral";
static String receiveMessageGeneral = "ReceiveMessageGeneral"; static String receiveMessageGeneral = "ReceiveMessageGeneral";
} }

@ -998,3 +998,12 @@ extension ShippingStatusEnumToInt on ShippingRequestStatusEnum {
} }
} }
} }
extension CapitalizeFirstLetter on String {
String capitalizeFirstLetter() {
if (isEmpty) {
return this; // Return the string as-is if it's empty
}
return this[0].toUpperCase() + substring(1).toLowerCase();
}
}

@ -761,6 +761,16 @@ class CodegenLoader extends AssetLoader{
"active": "نشط", "active": "نشط",
"paymentType": "نوع الدفع", "paymentType": "نوع الدفع",
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء", "searchByCreatedDate": "البحث حسب تاريخ الإنشاء",
"cityNameMandatory": "المدينة إلزامية",
"genderMandatory": "الجنس إلزامي",
"updateCity": "تحديث المدينة",
"userGender": "جنس",
"userMale": "ذكر",
"userFemale": "أنثى",
"maxFileSelection": "يمكنك تحديد الحد الأقصى لملفات 7",
"maxFileSize": "يجب أن يكون حجم كل ملف أقل من 2 ميغابايت",
"onlyJPGandPNG": "يُسمح فقط بملفات JPG وPNG",
"expiryDate": "تاريخ انتهاء الصلاحية",
"dealCompleted": "تم إتمام الصفقة", "dealCompleted": "تم إتمام الصفقة",
"theDealNotCompleted": "لم تكتمل الصفقة", "theDealNotCompleted": "لم تكتمل الصفقة",
"cancelRequest": "أريد إلغاء الطلب.", "cancelRequest": "أريد إلغاء الطلب.",
@ -780,6 +790,17 @@ class CodegenLoader extends AssetLoader{
"tapToSeeItems": "اضغط لرؤية العناصر", "tapToSeeItems": "اضغط لرؤية العناصر",
"tapToSelect": "اضغط للاختيار", "tapToSelect": "اضغط للاختيار",
"noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.", "noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.",
"requestCreatedOn": "تم إنشاء الطلب في",
"online": "عبر الإنترنت",
"deliveryStatus": "حالة توصيلك / الشحن هي:",
"markAsCompleted": "ضع علامة كمكتمل",
"searchByServiceDelivery": "البحث حسب خدمة التوصيل",
"searchByMobileNumber": "البحث بواسطة رقم الجوال",
"enterMobileNumber": "أدخل رقم الجوال",
"enterCustomerName": "أدخل اسم العميل",
"tapToView": "انقر لعرض",
"noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.",
"copySelectedItems": "نسخ العناصر المحددة"
"requestCreatedOn": "تم إنشاء الطلب في" "requestCreatedOn": "تم إنشاء الطلب في"
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء", "searchByCreatedDate": "البحث حسب تاريخ الإنشاء",
"cityNameMandatory": "المدينة إلزامية", "cityNameMandatory": "المدينة إلزامية",
@ -1533,7 +1554,6 @@ static const Map<String,dynamic> en_US = {
"blockedByAdmin": "Blocked by admin", "blockedByAdmin": "Blocked by admin",
"active": "Active", "active": "Active",
"paymentType": "Payment Type", "paymentType": "Payment Type",
"searchByCreatedDate": "Search By Created Date",
"dealCompleted": "The Deal Completed", "dealCompleted": "The Deal Completed",
"theDealNotCompleted": "The Deal Not Completed", "theDealNotCompleted": "The Deal Not Completed",
"cancelRequest": "I want to cancel the request.", "cancelRequest": "I want to cancel the request.",
@ -1554,6 +1574,32 @@ static const Map<String,dynamic> en_US = {
"tapToSeeItems": "Tap to see items", "tapToSeeItems": "Tap to see items",
"noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.", "noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.",
"requestCreatedOn": "Request created on", "requestCreatedOn": "Request created on",
"online": "Online",
"searchByCreatedDate": "Search By Created Date",
"updateUserDetails": "Update User Details",
"enterNewFirstName": "Enter First Name",
"enterNewLastName": "Enter Last Name",
"userDetailsUpdated": "User Details is Updated",
"cityNameMandatory": "City is mandatory",
"genderMandatory": "Gender is mandatory",
"updateCity": "Update City",
"userGender": "Gender",
"userMale": "Male",
"userFemale": "Female",
"maxFileSelection": "You can select a maximum of 7 files",
"maxFileSize": "Each file size must be less than 2 MB",
"onlyJPGandPNG": "Only JPG and PNG files are allowed",
"expiryDate": "Expiry Date",
"deliveryStatus": "Your Delivery / Shipping Status is:",
"markAsCompleted": "Mark as Completed",
"searchByServiceDelivery": "Search by Service Delivery",
"searchByMobileNumber": "Search by Mobile Number",
"enterMobileNumber": "Enter Mobile Number",
"enterCustomerName": "Enter Customer Name",
"tapToView": "Tap to view",
"noServicesAvailableToCopy": "There are no services available in this branch to copy.",
"copySelectedItems": "Copy Selected Items"
"requestCreatedOn": "Request created on",
"updateUserDetails": "Update User Details", "updateUserDetails": "Update User Details",
"enterNewFirstName": "Enter First Name", "enterNewFirstName": "Enter First Name",
"enterNewLastName": "Enter Last Name", "enterNewLastName": "Enter Last Name",

@ -724,6 +724,16 @@ abstract class LocaleKeys {
static const active = 'active'; static const active = 'active';
static const paymentType = 'paymentType'; static const paymentType = 'paymentType';
static const searchByCreatedDate = 'searchByCreatedDate'; static const searchByCreatedDate = 'searchByCreatedDate';
static const cityNameMandatory = 'cityNameMandatory';
static const genderMandatory = 'genderMandatory';
static const updateCity = 'updateCity';
static const userGender = 'userGender';
static const userMale = 'userMale';
static const userFemale = 'userFemale';
static const maxFileSelection = 'maxFileSelection';
static const maxFileSize = 'maxFileSize';
static const onlyJPGandPNG = 'onlyJPGandPNG';
static const expiryDate = 'expiryDate';
static const dealCompleted = 'dealCompleted'; static const dealCompleted = 'dealCompleted';
static const theDealNotCompleted = 'theDealNotCompleted'; static const theDealNotCompleted = 'theDealNotCompleted';
static const cancelRequest = 'cancelRequest'; static const cancelRequest = 'cancelRequest';
@ -744,15 +754,16 @@ abstract class LocaleKeys {
static const tapToSelect = 'tapToSelect'; static const tapToSelect = 'tapToSelect';
static const noteCopyItemsExplanation = 'noteCopyItemsExplanation'; static const noteCopyItemsExplanation = 'noteCopyItemsExplanation';
static const requestCreatedOn = 'requestCreatedOn'; static const requestCreatedOn = 'requestCreatedOn';
static const cityNameMandatory = 'cityNameMandatory'; static const online = 'online';
static const genderMandatory = 'genderMandatory'; static const deliveryStatus = 'deliveryStatus';
static const updateCity = 'updateCity'; static const markAsCompleted = 'markAsCompleted';
static const userGender = 'userGender'; static const searchByServiceDelivery = 'searchByServiceDelivery';
static const userMale = 'userMale'; static const searchByMobileNumber = 'searchByMobileNumber';
static const userFemale = 'userFemale'; static const enterMobileNumber = 'enterMobileNumber';
static const maxFileSelection = 'maxFileSelection'; static const enterCustomerName = 'enterCustomerName';
static const maxFileSize = 'maxFileSize'; static const tapToView = 'tapToView';
static const onlyJPGandPNG = 'onlyJPGandPNG'; static const noServicesAvailableToCopy = 'noServicesAvailableToCopy';
static const expiryDate = 'expiryDate'; static const copySelectedItems = 'copySelectedItems';
} }

@ -50,6 +50,7 @@ class AdDetailsModel {
String? warrantyYears; String? warrantyYears;
CreatedByRoleEnum? createdByRoleEnum; CreatedByRoleEnum? createdByRoleEnum;
List<ChatMessageModel>? adMessages; List<ChatMessageModel>? adMessages;
int? totalItemsCount;
AdDetailsModel({ AdDetailsModel({
this.id, this.id,
@ -95,6 +96,7 @@ class AdDetailsModel {
this.createdByRoleEnum, this.createdByRoleEnum,
this.modifiedOn, this.modifiedOn,
this.adMessages, this.adMessages,
this.totalItemsCount,
}); });
int getRandomValue({required int min, required int max}) { int getRandomValue({required int min, required int max}) {
@ -103,7 +105,7 @@ class AdDetailsModel {
return randomNumber; return randomNumber;
} }
AdDetailsModel.fromJson(Map<String, dynamic> json, bool isMyAds) { AdDetailsModel.fromJson(Map<String, dynamic> json, bool isMyAds, int totalItems) {
id = json['id']; id = json['id'];
startdate = json['startdate']; startdate = json['startdate'];
enddate = json['enddate']; enddate = json['enddate'];
@ -150,6 +152,7 @@ class AdDetailsModel {
createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum(); createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum();
isMyAd = isMyAds; isMyAd = isMyAds;
isReservedByMe = false; isReservedByMe = false;
totalItemsCount = totalItems;
} }
} }

@ -80,7 +80,7 @@ class ReqOffer {
String? offerStatusText; String? offerStatusText;
String? comment; String? comment;
String? serviceItemName; String? serviceItemName;
int? manufacturedById; String? manufacturedByName;
String? manufacturedOn; String? manufacturedOn;
double? price; double? price;
bool? isDeliveryAvailable; bool? isDeliveryAvailable;
@ -96,7 +96,7 @@ class ReqOffer {
this.offerStatusText, this.offerStatusText,
this.comment, this.comment,
this.serviceItemName, this.serviceItemName,
this.manufacturedById, this.manufacturedByName,
this.manufacturedOn, this.manufacturedOn,
this.price, this.price,
this.isDeliveryAvailable, this.isDeliveryAvailable,
@ -113,7 +113,7 @@ class ReqOffer {
offerStatusText = json['offerStatusText']; offerStatusText = json['offerStatusText'];
comment = json['comment']; comment = json['comment'];
serviceItemName = json['serviceItem']; serviceItemName = json['serviceItem'];
manufacturedById = json['offeredItemCreatedBy']; manufacturedByName = json['offeredItemCreatedBy'].toString();
manufacturedOn = json['offeredItemCreatedOn']; manufacturedOn = json['offeredItemCreatedOn'];
price = json['price']; price = json['price'];
isDeliveryAvailable = json['isDeliveryAvailable']; isDeliveryAvailable = json['isDeliveryAvailable'];
@ -138,7 +138,7 @@ class ReqOffer {
@override @override
String toString() { String toString() {
return 'ReqOffer{id: $id, requestID: $requestID, serviceProviderID: $serviceProviderID, offerStatus: $offerStatus, offerStatusText: $offerStatusText, comment: $comment, serviceItemName: $serviceItemName, manufacturedById: $manufacturedById, manufacturedOn: $manufacturedOn, price: $price, requestsTypeEnum: $requestsTypeEnum, requestOfferStatusEnum: $requestOfferStatusEnum}'; return 'ReqOffer{id: $id, requestID: $requestID, serviceProviderID: $serviceProviderID, offerStatus: $offerStatus, offerStatusText: $offerStatusText, comment: $comment, serviceItemName: $serviceItemName, manufacturedById: $manufacturedByName, manufacturedOn: $manufacturedOn, price: $price, requestsTypeEnum: $requestsTypeEnum, requestOfferStatusEnum: $requestOfferStatusEnum}';
} }
} }

@ -101,7 +101,7 @@ class RequestModel {
requestStatusName: json["requestStatusName"], requestStatusName: json["requestStatusName"],
requestStatus: (json['requestStatus'] as int).toRequestStatusEnum(), requestStatus: (json['requestStatus'] as int).toRequestStatusEnum(),
shippingStatus: json['shippingRequestStatus'], shippingStatus: json['shippingRequestStatus'],
shippingStatusEnum: json['shippingRequestStatus'] != null ? (json['shippingRequestStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.initiated, shippingStatusEnum: json['shippingRequestStatus'] != null ? (json['shippingRequestStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.pending,
cityName: json["cityName"], cityName: json["cityName"],
vehicleTypeName: json["vehicleTypeName"], vehicleTypeName: json["vehicleTypeName"],
countryName: json["countryName"], countryName: json["countryName"],

@ -1,10 +1,12 @@
import 'dart:developer'; import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependency_injection.dart'; import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/string_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/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/models/advertisment_models/ads_bank_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_bank_details_model.dart';
import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart';
@ -14,15 +16,22 @@ import 'package:mc_common_app/models/advertisment_models/special_service_model.d
import 'package:mc_common_app/models/chat_models/buyers_chat_for_ads_model.dart'; import 'package:mc_common_app/models/chat_models/buyers_chat_for_ads_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
abstract class AdsRepo { abstract class AdsRepo {
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId}); Future<List<AdsDurationModel>> getAdsDuration({required int? countryId});
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType}); Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType, required int cityId, required int countryId});
Future<GenericRespModel> createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew}); Future<GenericRespModel> createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew});
Future<List<AdDetailsModel>> getAllAds({required bool isMyAds, AdPostStatus? adPostStatus, CreatedByRoleEnum? createdByRoleEnum}); Future<List<AdDetailsModel>> getAllAds({
required bool isMyAds,
AdPostStatus? adPostStatus,
CreatedByRoleEnum? createdByRoleEnum,
int? vehicleBrandId,
int? page,
});
Future<List<AdDetailsModel>> getExploreAdsBasedOnFilters({ Future<List<AdDetailsModel>> getExploreAdsBasedOnFilters({
List<String>? cityIdsList, List<String>? cityIdsList,
@ -31,6 +40,8 @@ abstract class AdsRepo {
List<String>? createdByRolesIdsList, List<String>? createdByRolesIdsList,
List<String>? vehicleAdConditionIdsList, List<String>? vehicleAdConditionIdsList,
List<String>? vehicleAdCreatedDateList, List<String>? vehicleAdCreatedDateList,
int page,
bool isMyAds = false,
}); });
Future<List<AdDetailsModel>> getMyReservedAds(); Future<List<AdDetailsModel>> getMyReservedAds();
@ -62,10 +73,10 @@ class AdsRepoImp implements AdsRepo {
@override @override
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId}) async { Future<List<AdsDurationModel>> getAdsDuration({required int? countryId}) async {
int roleID = appState.getUser!.data!.userInfo!.roleId ?? 0; int roleID = appState.getUser.data!.userInfo!.roleId ?? 0;
var param = { var param = {
"CountryID": countryId.toString() ?? "0", "CountryID": countryId.toString(),
"roleID": roleID.toString() ?? "0", "roleID": roleID.toString(),
}; };
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,
@ -78,14 +89,34 @@ class AdsRepoImp implements AdsRepo {
} }
@override @override
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType}) async { Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType, required int cityId, required int countryId}) async {
log("getSpecialServices cityId: $cityId");
var params = { var params = {
"SpecialServiceType": specialServiceType.toString(), "SpecialServiceType": specialServiceType.toString(),
"CountryID": countryId.toString(),
}; };
GenericRespModel adsGenericModel = GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params); await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params);
List<SpecialServiceModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index])); List<SpecialServiceModel> list = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index]));
return vehicleAdsDuration;
List<SpecialServiceModel> specialServicesByCity = getOfficesOnlyByCity(list, cityId);
return specialServicesByCity;
}
List<SpecialServiceModel> getOfficesOnlyByCity(List<SpecialServiceModel> allServices, int cityId) {
List<SpecialServiceModel> list = [];
for (var service in allServices) {
if (service.office != null && service.office!.isNotEmpty) {
for (var office in service.office!) {
if (office.cityID == cityId) {
list.add(service);
}
}
}
}
return list;
} }
@override @override
@ -168,7 +199,13 @@ class AdsRepoImp implements AdsRepo {
} }
@override @override
Future<List<AdDetailsModel>> getAllAds({required isMyAds, AdPostStatus? adPostStatus, CreatedByRoleEnum? createdByRoleEnum}) async { Future<List<AdDetailsModel>> getAllAds({
required isMyAds,
AdPostStatus? adPostStatus,
CreatedByRoleEnum? createdByRoleEnum,
int? vehicleBrandId,
int? page,
}) async {
Map<String, dynamic> onlyMyAdsParams = { Map<String, dynamic> onlyMyAdsParams = {
"userID": appState.getUser.data!.userInfo!.userId ?? "", "userID": appState.getUser.data!.userInfo!.userId ?? "",
}; };
@ -176,6 +213,7 @@ class AdsRepoImp implements AdsRepo {
onlyMyAdsParams.addAll({ onlyMyAdsParams.addAll({
"AdsStatuses": ["${adPostStatus.getIdFromAdPostStatusEnum()}"], "AdsStatuses": ["${adPostStatus.getIdFromAdPostStatusEnum()}"],
"PageSize": "30", "PageSize": "30",
"PageIndex": page != null ? page.toString() : "0",
}); });
} }
var allAdsParams = { var allAdsParams = {
@ -183,6 +221,7 @@ class AdsRepoImp implements AdsRepo {
"isActive": "true", //only Active ADS "isActive": "true", //only Active ADS
"isExplore": "true", "isExplore": "true",
"PageSize": "30", "PageSize": "30",
"PageIndex": page != null ? page.toString() : "0",
}; };
if (!isMyAds && createdByRoleEnum != null) { if (!isMyAds && createdByRoleEnum != null) {
@ -190,13 +229,18 @@ class AdsRepoImp implements AdsRepo {
"CreatedByRoles": ["${createdByRoleEnum.getIdFromCreatedByRoleEnum()}"], "CreatedByRoles": ["${createdByRoleEnum.getIdFromCreatedByRoleEnum()}"],
}); });
} }
if (!isMyAds && vehicleBrandId != null && vehicleBrandId != 0) {
allAdsParams.addAll({
"VehicleBrandIDs": ["$vehicleBrandId"],
});
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet, ApiConsts.vehicleAdsGet,
queryParameters: isMyAds ? onlyMyAdsParams : allAdsParams, queryParameters: isMyAds ? onlyMyAdsParams : allAdsParams,
); );
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], isMyAds)); List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], isMyAds, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails; return vehicleAdsDetails;
} }
@ -208,6 +252,8 @@ class AdsRepoImp implements AdsRepo {
List<String>? createdByRolesIdsList, List<String>? createdByRolesIdsList,
List<String>? vehicleAdConditionIdsList, List<String>? vehicleAdConditionIdsList,
List<String>? vehicleAdCreatedDateList, List<String>? vehicleAdCreatedDateList,
int? page,
bool isMyAds = false,
}) async { }) async {
var parameters = { var parameters = {
"CityIDs": cityIdsList ?? [], "CityIDs": cityIdsList ?? [],
@ -218,17 +264,29 @@ class AdsRepoImp implements AdsRepo {
"VehicleNew": vehicleAdConditionIdsList ?? [], "VehicleNew": vehicleAdConditionIdsList ?? [],
"CreatedOn": (vehicleAdCreatedDateList != null && vehicleAdCreatedDateList.isNotEmpty) ? vehicleAdCreatedDateList.first.toString() : "", "CreatedOn": (vehicleAdCreatedDateList != null && vehicleAdCreatedDateList.isNotEmpty) ? vehicleAdCreatedDateList.first.toString() : "",
"isActive": "true", //only Active ADS "isActive": "true", //only Active ADS
"isExplore": "true", "isExplore": (!isMyAds).toString(),
"PageSize": "30", "PageSize": "30",
"PageIndex": page != null ? page.toString() : "1",
}; };
if (isMyAds) {
parameters.addAll({
"userID": appState.getUser.data!.userInfo!.userId ?? "",
});
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet, ApiConsts.vehicleAdsGet,
queryParameters: parameters, queryParameters: parameters,
); );
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], false));
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], false, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails; return vehicleAdsDetails;
} }
@ -244,6 +302,11 @@ class AdsRepoImp implements AdsRepo {
ApiConsts.myAdsReserveGet, ApiConsts.myAdsReserveGet,
queryParameters: params, queryParameters: params,
); );
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<MyReservedAdsRespModel> reservedAds = List.generate(adsGenericModel.data.length, (index) => MyReservedAdsRespModel.fromJson(adsGenericModel.data[index])); List<MyReservedAdsRespModel> reservedAds = List.generate(adsGenericModel.data.length, (index) => MyReservedAdsRespModel.fromJson(adsGenericModel.data[index]));
List<String> selectedIdsString = reservedAds.map((component) => component.adsID.toString()).toList(); List<String> selectedIdsString = reservedAds.map((component) => component.adsID.toString()).toList();
@ -266,7 +329,11 @@ class AdsRepoImp implements AdsRepo {
queryParameters: params, queryParameters: params,
ApiConsts.vehicleAdsGet, ApiConsts.vehicleAdsGet,
); );
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true)); if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true, adsGenericModel.totalItemsCount ?? 1));
for (int i = 0; i < vehicleAdsDetails.length; i++) { for (int i = 0; i < vehicleAdsDetails.length; i++) {
vehicleAdsDetails[i].adReserveStatus = (reservedAds[i].adsReserveStatus ?? 0).toAdRserveStatusEnum(); vehicleAdsDetails[i].adReserveStatus = (reservedAds[i].adsReserveStatus ?? 0).toAdRserveStatusEnum();
@ -288,7 +355,11 @@ class AdsRepoImp implements AdsRepo {
queryParameters: params, queryParameters: params,
ApiConsts.vehicleAdsGet, ApiConsts.vehicleAdsGet,
); );
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true)); if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails; return vehicleAdsDetails;
} }

@ -15,6 +15,16 @@ import 'package:mc_common_app/utils/enums.dart';
abstract class AppointmentRepo { abstract class AppointmentRepo {
Future<List<AppointmentListModel>> getMyAppointmentsForProvider(Map<String, dynamic> map); Future<List<AppointmentListModel>> getMyAppointmentsForProvider(Map<String, dynamic> map);
Future<List<AppointmentListModel>> getMyAppointmentsForProvidersByFilters({
required int branchID,
List<String>? serviceProviderServiceIdsList,
List<String>? customerNamesList,
List<String>? customerPhonesList,
List<String>? deliveryTypeIdsList,
String? fromDate,
String? toDate,
});
Future<List<AppointmentListModel>> getMyAppointmentsForCustomersByFilters({ Future<List<AppointmentListModel>> getMyAppointmentsForCustomersByFilters({
List<String>? providerIdsList, List<String>? providerIdsList,
List<String>? categoryIdsList, List<String>? categoryIdsList,
@ -27,7 +37,7 @@ abstract class AppointmentRepo {
Future<GenericRespModel> updateAppointmentPaymentStatus(Map<String, dynamic> map); Future<GenericRespModel> updateAppointmentPaymentStatus(Map<String, dynamic> map);
Future<GenericRespModel> getAppointmentSlots(Map<String, dynamic> map); Future<GenericRespModel> getAppointmentSlots({required int branchID, required String fromDate, required String toDate});
Future<GenericRespModel> createMergeAppointment(Map<String, dynamic> map); Future<GenericRespModel> createMergeAppointment(Map<String, dynamic> map);
@ -219,6 +229,40 @@ class AppointmentRepoImp implements AppointmentRepo {
return appointmentList; return appointmentList;
} }
@override
Future<List<AppointmentListModel>> getMyAppointmentsForProvidersByFilters({
required int branchID,
List<String>? serviceProviderServiceIdsList,
List<String>? customerNamesList,
List<String>? customerPhonesList,
List<String>? deliveryTypeIdsList,
String? fromDate,
String? toDate,
}) async {
String t = appState.getUser.data!.accessToken ?? "";
String providerId = appState.getUser.data!.userInfo!.providerId.toString();
var params = {
"ServiceProviderID": providerId.toString(),
"ProviderBranchID": branchID.toString(),
"IsSearchFilter": true.toString(),
"SPServiceIDs": serviceProviderServiceIdsList ?? [],
"CustomerNames": customerNamesList ?? [],
"CustomerMobileNos": customerPhonesList ?? [],
"AppointmentTypes": deliveryTypeIdsList ?? [],
"FromDate": fromDate ?? "",
"DateTo": toDate ?? "",
};
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
token: t,
(json) => GenericRespModel.fromJson(json),
queryParameters: params,
ApiConsts.serviceProvidersAppointmentGet,
);
List<AppointmentListModel> appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList;
}
@override @override
Future<List<AppointmentListModel>> getMyAppointmentsForCustomersByFilters({ Future<List<AppointmentListModel>> getMyAppointmentsForCustomersByFilters({
List<String>? providerIdsList, List<String>? providerIdsList,
@ -246,8 +290,9 @@ class AppointmentRepoImp implements AppointmentRepo {
} }
@override @override
Future<GenericRespModel> getAppointmentSlots(Map<String, dynamic> map) async { Future<GenericRespModel> getAppointmentSlots({required int branchID, required String fromDate, required String toDate}) async {
String t = appState.getUser.data!.accessToken ?? ""; String t = appState.getUser.data!.accessToken ?? "";
final map = {"ProviderBranchID": branchID.toString(), "FromDate": fromDate, "ToDate": toDate};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),

@ -75,6 +75,8 @@ abstract class BranchRepo {
Future<GenericRespModel> updateServiceStatus({required int branchId, required List<int> serviceIds, required ServiceStatusEnum serviceStatusEnum}); Future<GenericRespModel> updateServiceStatus({required int branchId, required List<int> serviceIds, required ServiceStatusEnum serviceStatusEnum});
Future<GenericRespModel> updateCategoryStatus({required int branchId, required int categoryId, required ServiceStatusEnum serviceStatusEnum});
Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}); Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId});
Future<GenericRespModel> getMatchedServices(int oldBranchId, int newBranchId, int categoryId); Future<GenericRespModel> getMatchedServices(int oldBranchId, int newBranchId, int categoryId);
@ -269,8 +271,7 @@ class BranchRepoImp implements BranchRepo {
serviceProviderBranchImages.add(imageMap); serviceProviderBranchImages.add(imageMap);
} }
String lat = "0", String lat = "0", long = "0";
long = "0";
try { try {
lat = latitude.toString().substring(0, 9); lat = latitude.toString().substring(0, 9);
long = longitude.toString().substring(0, 9); long = longitude.toString().substring(0, 9);
@ -333,6 +334,19 @@ class BranchRepoImp implements BranchRepo {
return await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.serviceProviderServiceStatusUpdate, queryParameters: map, token: t); return await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.serviceProviderServiceStatusUpdate, queryParameters: map, token: t);
} }
@override
Future<GenericRespModel> updateCategoryStatus({required int branchId, required int categoryId, required ServiceStatusEnum serviceStatusEnum}) async {
int providerID = AppState().getUser.data!.userInfo!.providerId;
var map = {
"ServiceProviderID": providerID.toString(),
"ProviderBranchID": branchId.toString(),
"ServiceCategoryID": categoryId.toString(),
"Status": serviceStatusEnum.getIdFromServiceStatusEnum().toString(),
};
String t = AppState().getUser.data!.accessToken ?? "";
return await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.serviceProviderServiceStatusUpdate, queryParameters: map, token: t);
}
@override @override
Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}) async { Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}) async {
var map = { var map = {

@ -63,7 +63,7 @@ abstract class RequestRepo {
required String offerPrice, required String offerPrice,
required bool isDeliveryAvailable, required bool isDeliveryAvailable,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required List requestImages, required List requestImages,
required RequestOfferStatusEnum requestOfferStatusEnum, required RequestOfferStatusEnum requestOfferStatusEnum,
@ -354,7 +354,7 @@ class RequestRepoImp implements RequestRepo {
required String offerPrice, required String offerPrice,
required bool isDeliveryAvailable, required bool isDeliveryAvailable,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required List requestImages, required List requestImages,
required RequestOfferStatusEnum requestOfferStatusEnum, required RequestOfferStatusEnum requestOfferStatusEnum,
@ -369,7 +369,7 @@ class RequestRepoImp implements RequestRepo {
"serviceItem": serviceItemName, "serviceItem": serviceItemName,
"comment": message, "comment": message,
"price": offerPrice, "price": offerPrice,
"offeredItemCreatedBy": manufacturedById.toString(), "offeredItemCreatedBy": manufacturedByName.toString(),
"offeredItemCreatedOn": manufacturedOn.toString(), "offeredItemCreatedOn": manufacturedOn.toString(),
"reqOfferImages": requestImages, "reqOfferImages": requestImages,
"isDeliveryAvailable": isDeliveryAvailable "isDeliveryAvailable": isDeliveryAvailable

@ -6,7 +6,6 @@ import 'package:local_auth/local_auth.dart';
import 'package:local_auth_android/local_auth_android.dart'; import 'package:local_auth_android/local_auth_android.dart';
import 'package:local_auth_darwin/types/auth_messages_ios.dart'; import 'package:local_auth_darwin/types/auth_messages_ios.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
abstract class CommonAuthServices { abstract class CommonAuthServices {
@ -18,10 +17,11 @@ abstract class CommonAuthServices {
class CommonAuthImp implements CommonAuthServices { class CommonAuthImp implements CommonAuthServices {
final LocalAuthentication localAuth = LocalAuthentication(); final LocalAuthentication localAuth = LocalAuthentication();
@override
Future<bool> authenticate() async { Future<bool> authenticate() async {
try { try {
final availableBiometrics = await localAuth.getAvailableBiometrics(); final availableBiometrics = await localAuth.getAvailableBiometrics();
if (availableBiometrics == null || availableBiometrics.isEmpty) { if (availableBiometrics.isEmpty) {
return false; return false;
} }

@ -58,8 +58,7 @@ class CommonServicesImp implements CommonAppServices {
return pickedFiles; return pickedFiles;
} }
@override
Future<List<File>> pickMultipleImages() async { Future<List<File>> pickMultipleImages() async {
final picker = ImagePicker(); final picker = ImagePicker();
List<File> imageModels = []; List<File> imageModels = [];
@ -74,16 +73,16 @@ class CommonServicesImp implements CommonAppServices {
return []; return [];
} }
if (await element.length() > GlobalConsts().maxFileSizeInBytes) { if (await element.length() > GlobalConsts.maxFileSizeInBytes) {
Utils.showToast(LocaleKeys.maxFileSize); Utils.showToast(LocaleKeys.maxFileSize);
return []; return [];
} }
imageModels.add(File(element.path)); imageModels.add(File(element.path));
} }
if (imageModels.length > GlobalConsts().maxFileCount) { if (imageModels.length > GlobalConsts.maxFileCount) {
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
imageModels = imageModels.sublist(0, GlobalConsts().maxFileCount); // Keep only the first 7 images imageModels = imageModels.sublist(0, GlobalConsts.maxFileCount); // Keep only the first 7 images
} }
pickedImages.addAll(imageModels); pickedImages.addAll(imageModels);
@ -120,7 +119,7 @@ class CommonServicesImp implements CommonAppServices {
destLongitude, destLongitude,
); );
return (distance / 1000) ?? 0.0; return (distance / 1000);
} catch (e) { } catch (e) {
logger.e(e.toString()); logger.e(e.toString());
return 0.0; return 0.0;

@ -13,10 +13,11 @@ class AppEnums {
static const int requestFilterEnumId = 16; // Requests Filter Enums static const int requestFilterEnumId = 16; // Requests Filter Enums
static const int branchServicesEnumId = 6; // Branch Services Filter Enums static const int branchServicesEnumId = 6; // Branch Services Filter Enums
static const int myAdsFilterEnumId = 18; // My Ads Filter Enums static const int myAdsFilterEnumId = 18; // My Ads Filter Enums
static const int exploreAdsFilterEnumId = 23; // Explore Ads Filter Enums static const int adOwnersFilterEnumId = 23; // Explore Ads Filter Enums
static const int appointmentsFilterEnumId = 13; // Appointments Filter Enums static const int appointmentsFilterEnumId = 13; // Appointments Filter Enums
static const int requestStatusesFilterEnumId = 15; // Appointments Filter Enums static const int requestStatusesFilterEnumId = 15; // Appointments Filter Enums
static const int conditionEnumId = -1; // to get the Condition Filter Enums static const int conditionEnumId = -1; // to get the Condition Filter Enums
static const int serviceDeliveryTypeEnumId = 24; // to get the serviceDeliveryType
static const int shippingStatusEnumId = 30; // to get the Shipping Filter Enums static const int shippingStatusEnumId = 30; // to get the Shipping Filter Enums
} }

@ -165,9 +165,8 @@ class AdVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
List<EnumsModel> exploreAdsEnums = []; List<EnumsModel> myAdsStatusEnums = [];
List<VehicleBrandsModel> vehicleBrandsForFilters = [];
List<EnumsModel> myAdsEnums = [];
List<FilterListModel> exploreAdsFilterOptions = []; List<FilterListModel> exploreAdsFilterOptions = [];
List<FilterListModel> myAdsFilterOptions = []; List<FilterListModel> myAdsFilterOptions = [];
@ -177,60 +176,119 @@ class AdVM extends BaseVM {
return; return;
} }
if (myAdsEnums.isEmpty) { if (myAdsStatusEnums.isEmpty) {
myAdsEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.myAdsFilterEnumId); myAdsStatusEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.myAdsFilterEnumId);
} }
if (exploreAdsEnums.isEmpty) { if (vehicleBrandsForFilters.isEmpty) {
exploreAdsEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.exploreAdsFilterEnumId); vehicleBrandsForFilters = await commonRepo.getVehicleBrands(vehicleTypeId: -1); // to get all the brands
} }
exploreAdsFilterOptions.clear(); exploreAdsFilterOptions.clear();
myAdsFilterOptions.clear(); myAdsFilterOptions.clear();
for (int i = 0; i < myAdsEnums.length; i++) { for (int i = 0; i < myAdsStatusEnums.length; i++) {
myAdsFilterOptions.add(FilterListModel(title: myAdsEnums[i].enumValueStr, isSelected: false, id: myAdsEnums[i].enumValue)); myAdsFilterOptions.add(FilterListModel(title: myAdsStatusEnums[i].enumValueStr, isSelected: false, id: myAdsStatusEnums[i].enumValue));
} }
myAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0)); myAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0));
log("myAdsFilterOptions: ${myAdsFilterOptions.last.id}"); for (int i = 0; i < vehicleBrandsForFilters.length; i++) {
exploreAdsFilterOptions.add(FilterListModel(
for (int i = 0; i < exploreAdsEnums.length; i++) { id: vehicleBrandsForFilters[i].id!,
exploreAdsFilterOptions.add(FilterListModel(title: "${exploreAdsEnums[i].enumValueStr} Ads", isSelected: false, id: exploreAdsEnums[i].enumValue)); title: "${vehicleBrandsForFilters[i].vehicleBrandDescription}",
iconUrl: "",
isSelected: false,
));
} }
exploreAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0)); exploreAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0));
notifyListeners(); notifyListeners();
} }
applyFilterOnExploreAds({required CreatedByRoleEnum createdByRoleFilter}) async { applyFilterOnExploreAds({required int vehicleBrandId}) async {
pageIndexForExploreAds = 1;
hasMoreDataForExploreAds = true;
if (exploreAdsFilterOptions.isEmpty) return; if (exploreAdsFilterOptions.isEmpty) return;
int index = exploreAdsFilterOptions.indexWhere((element) => element.id.toCreatedByRoleEnum() == createdByRoleFilter); int index = exploreAdsFilterOptions.indexWhere((element) => element.id == vehicleBrandId);
for (var value in exploreAdsFilterOptions) { for (var value in exploreAdsFilterOptions) {
value.isSelected = false; value.isSelected = false;
} }
exploreAdsFilterOptions[index].isSelected = true; exploreAdsFilterOptions[index].isSelected = true;
if (createdByRoleFilter == CreatedByRoleEnum.allAds) { if (vehicleBrandId == 0) {
// all ads
getExploreAds(); getExploreAds();
return; return;
} }
setState(ViewState.busy); setState(ViewState.busy);
exploreAdsFilteredList = await getAdsByFilter(createdByRoleEnum: createdByRoleFilter, isMyAds: false); exploreAdsFilteredList = await getAdsByFilter(vehicleBrandId: vehicleBrandId, isMyAds: false);
setState(ViewState.idle); setState(ViewState.idle);
notifyListeners(); notifyListeners();
} }
int currentPageForExploreAds = 1; int pageIndexForExploreAds = 1;
int currentPageForMyAds = 1; int pageIndexForMyAds = 1;
bool hasMoreDataForExploreAds = true;
bool hasMoreDataForMyAds = true;
bool isLoadingMore = false; bool isLoadingMore = false;
bool hasMoreData = true;
fetchMoreAds() async {} Future<void> fetchMoreExploreAds() async {
if (isLoadingMore) return;
isLoadingMore = true;
hasMoreDataForExploreAds = true;
notifyListeners();
try {
final List<AdDetailsModel> newAds = await getAdsBasedOnFilters(pageIndex: pageIndexForExploreAds, isFromLazyLoad: true);
if (newAds.isEmpty) {
hasMoreDataForExploreAds = false;
} else {
exploreAdsFilteredList.addAll(newAds);
pageIndexForExploreAds++;
if (exploreAdsFilteredList.length < exploreAdsFilteredList.last.totalItemsCount!) {
hasMoreDataForExploreAds = true;
} else {
hasMoreDataForExploreAds = false;
}
}
} catch (error) {
isLoadingMore = false;
Utils.showToast(error.toString());
}
isLoadingMore = false;
notifyListeners();
}
Future<void> fetchMoreMyAds({required AdPostStatus adsStatus}) async {
if (isLoadingMore) return;
hasMoreDataForMyAds = true;
isLoadingMore = true;
notifyListeners();
try {
final List<AdDetailsModel> newAds = await adsRepo.getAllAds(page: pageIndexForMyAds, isMyAds: true, adPostStatus: adsStatus);
if (newAds.isEmpty) {
hasMoreDataForMyAds = false;
} else {
myAdsFilteredList.addAll(newAds);
pageIndexForMyAds++;
if (myAdsFilteredList.length < myAdsFilteredList.last.totalItemsCount!) {
hasMoreDataForMyAds = true;
} else {
hasMoreDataForMyAds = false;
}
}
} catch (error) {
isLoadingMore = false;
Utils.showToast(error.toString());
}
isLoadingMore = false;
notifyListeners();
}
Future<List<AdDetailsModel>> getAdsByFilter({AdPostStatus? adPostStatus, required bool isMyAds, CreatedByRoleEnum? createdByRoleEnum}) async { Future<List<AdDetailsModel>> getAdsByFilter({AdPostStatus? adPostStatus, required bool isMyAds, CreatedByRoleEnum? createdByRoleEnum, int? vehicleBrandId}) async {
return await adsRepo.getAllAds(isMyAds: isMyAds, adPostStatus: adPostStatus, createdByRoleEnum: createdByRoleEnum); return await adsRepo.getAllAds(isMyAds: isMyAds, adPostStatus: adPostStatus, createdByRoleEnum: createdByRoleEnum, vehicleBrandId: vehicleBrandId);
} }
applyFilterOnMyAds({required AdPostStatus adPostStatusEnum}) async { applyFilterOnMyAds({required AdPostStatus adPostStatusEnum}) async {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
if (myAdsFilterOptions.isEmpty) return; if (myAdsFilterOptions.isEmpty) return;
int index = myAdsFilterOptions.indexWhere((element) => element.id.toAdPostEnum() == adPostStatusEnum); int index = myAdsFilterOptions.indexWhere((element) => element.id.toAdPostEnum() == adPostStatusEnum);
@ -265,7 +323,7 @@ class AdVM extends BaseVM {
if (genericRespModel.messageStatus == null) { if (genericRespModel.messageStatus == null) {
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.showToast(genericRespModel.message ?? "Something went wrong!"); Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
return false; return false;
} }
Utils.hideLoading(context); Utils.hideLoading(context);
@ -273,6 +331,8 @@ class AdVM extends BaseVM {
} }
Future<void> getExploreAds() async { Future<void> getExploreAds() async {
pageIndexForExploreAds = 1;
hasMoreDataForExploreAds = true;
setState(ViewState.busy); setState(ViewState.busy);
exploreAds = await adsRepo.getAllAds(isMyAds: false); exploreAds = await adsRepo.getAllAds(isMyAds: false);
exploreAdsFilteredList = exploreAds; exploreAdsFilteredList = exploreAds;
@ -281,6 +341,8 @@ class AdVM extends BaseVM {
} }
Future<void> getMyAds() async { Future<void> getMyAds() async {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
setState(ViewState.busy); setState(ViewState.busy);
myAds = await adsRepo.getAllAds(isMyAds: true); myAds = await adsRepo.getAllAds(isMyAds: true);
myAdsFilteredList = myAds; myAdsFilteredList = myAds;
@ -316,8 +378,8 @@ class AdVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
Future<void> getVehicleAdsSpecialServices() async { Future<void> getVehicleAdsSpecialServices({required int cityId, required int countryId, required int specialServiceType}) async {
vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: 1); vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: specialServiceType, countryId: countryId, cityId: cityId);
notifyListeners(); notifyListeners();
} }
@ -1126,9 +1188,7 @@ class AdVM extends BaseVM {
getVehicleAdsDuration(); getVehicleAdsDuration();
} }
if (vehicleAdsSpecialServices.isEmpty) { getVehicleAdsSpecialServices(countryId: vehicleCountryId.selectedId, cityId: vehicleCityId.selectedId, specialServiceType: 1);
getVehicleAdsSpecialServices();
}
notifyListeners(); notifyListeners();
} }
@ -1205,8 +1265,8 @@ class AdVM extends BaseVM {
pickedPostingImages.addAll(imageModels); pickedPostingImages.addAll(imageModels);
// Added By Aamir // Added By Aamir
if (pickedPostingImages.length > GlobalConsts().maxFileCount) { if (pickedPostingImages.length > GlobalConsts.maxFileCount) {
pickedPostingImages = pickedPostingImages.sublist(0, GlobalConsts().maxFileCount); pickedPostingImages = pickedPostingImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
@ -1253,8 +1313,8 @@ class AdVM extends BaseVM {
} else { } else {
vehicleDamageCards[index].partImages!.addAll(imageModels); vehicleDamageCards[index].partImages!.addAll(imageModels);
// Added By Aamir // Added By Aamir
if (vehicleDamageCards[index].partImages!.length > GlobalConsts().maxFileCount) { if (vehicleDamageCards[index].partImages!.length > GlobalConsts.maxFileCount) {
vehicleDamageCards[index].partImages = vehicleDamageCards[index].partImages!.sublist(0, GlobalConsts().maxFileCount); vehicleDamageCards[index].partImages = vehicleDamageCards[index].partImages!.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
} }
@ -1309,8 +1369,8 @@ class AdVM extends BaseVM {
List<File> images = await commonServices.pickMultipleImages(); List<File> images = await commonServices.pickMultipleImages();
pickedDamageImages.addAll(images); pickedDamageImages.addAll(images);
if (pickedDamageImages.length > GlobalConsts().maxFileCount) { if (pickedDamageImages.length > GlobalConsts.maxFileCount) {
pickedDamageImages = pickedDamageImages.sublist(0, GlobalConsts().maxFileCount); pickedDamageImages = pickedDamageImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
if (pickedDamageImages.isNotEmpty) vehicleDamageImageError = ""; if (pickedDamageImages.isNotEmpty) vehicleDamageImageError = "";
@ -1596,20 +1656,32 @@ class AdVM extends BaseVM {
// ************ ADS SEARCH VIEW **************** // ************ ADS SEARCH VIEW ****************
List<EnumsModel> vehicleConditionsEnum = []; List<EnumsModel> vehicleConditionsEnum = [];
List<EnumsModel> adOwnerEnumsFilter = [];
Future<void> populateDataForAdFilter() async { Future<void> populateDataForAdFilter() async {
setState(ViewState.busy); setState(ViewState.busy);
pageIndexForExploreAds = 1;
pageIndexForMyAds = 1;
hasMoreDataForExploreAds = true;
hasMoreDataForMyAds = true;
isLoadingMore = false;
if (adOwnerEnumsFilter.isEmpty) {
adOwnerEnumsFilter = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.adOwnersFilterEnumId);
}
if (vehicleConditionsEnum.isEmpty) { if (vehicleConditionsEnum.isEmpty) {
vehicleConditionsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.conditionEnumId); vehicleConditionsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.conditionEnumId);
} }
if (vehicleBrands.isEmpty) { if (vehicleBrandsForFilters.isEmpty) {
vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: -1); vehicleBrandsForFilters = await commonRepo.getVehicleBrands(vehicleTypeId: -1); // to get all the brands
} }
if (vehicleModelYears.isEmpty) { if (vehicleModelYears.isEmpty) {
vehicleModelYears = await commonRepo.getVehicleModelYears(vehicleTypeId: -1); vehicleModelYears = await commonRepo.getVehicleModelYears(vehicleTypeId: -1);
} }
vehicleCities = await commonRepo.getVehicleCities(countryId: -1); // fetch all the cities vehicleCities = await commonRepo.getVehicleCities(countryId: -1); // fetch all the cities
setState(ViewState.idle); setState(ViewState.idle);
} }
@ -1678,9 +1750,9 @@ class AdVM extends BaseVM {
SelectionModel vehicleOwnerId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); SelectionModel vehicleOwnerId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleAdOwnerId(SelectionModel id, {bool isForSearch = false}) { void updateSelectionVehicleAdOwnerId(SelectionModel id, {bool showSelectionInDropdown = true, bool isForSearch = false}) {
if (isForSearch) { if (isForSearch) {
EnumsModel owner = exploreAdsEnums.firstWhere((element) => element.enumValue == id.selectedId); EnumsModel owner = adOwnerEnumsFilter.firstWhere((element) => element.enumValue == id.selectedId);
DropValue ownerValue = DropValue(owner.enumValue, "${owner.enumValueStr} Ads", ""); DropValue ownerValue = DropValue(owner.enumValue, "${owner.enumValueStr} Ads", "");
if (!ifAlreadyExist(list: vehicleAdOwnerSearchHistory, value: ownerValue)) { if (!ifAlreadyExist(list: vehicleAdOwnerSearchHistory, value: ownerValue)) {
addToVehicleAdOwnerSearchHistory(value: ownerValue); addToVehicleAdOwnerSearchHistory(value: ownerValue);
@ -1688,7 +1760,9 @@ class AdVM extends BaseVM {
notifyListeners(); notifyListeners();
return; return;
} }
if (showSelectionInDropdown) {
vehicleOwnerId = id; vehicleOwnerId = id;
}
notifyListeners(); notifyListeners();
} }
@ -1819,9 +1893,14 @@ class AdVM extends BaseVM {
vehicleOwnerId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleOwnerId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
} }
Future<void> getAdsBasedOnFilters() async { Future<List<AdDetailsModel>> getAdsBasedOnFilters({
required int pageIndex,
required bool isFromLazyLoad,
}) async {
if (!isFromLazyLoad) {
exploreAdsFilteredList.clear(); exploreAdsFilteredList.clear();
setState(ViewState.busy); setState(ViewState.busy);
}
List<String> cityIdsList = []; List<String> cityIdsList = [];
if (vehicleLocationAdSearchHistory.isNotEmpty) { if (vehicleLocationAdSearchHistory.isNotEmpty) {
for (var element in vehicleLocationAdSearchHistory) { for (var element in vehicleLocationAdSearchHistory) {
@ -1863,15 +1942,25 @@ class AdVM extends BaseVM {
} }
} }
exploreAdsFilteredList = await adsRepo.getExploreAdsBasedOnFilters( List<AdDetailsModel> list = await adsRepo.getExploreAdsBasedOnFilters(
cityIdsList: cityIdsList, cityIdsList: cityIdsList,
createdByRolesIdsList: adOwnerIdsList, createdByRolesIdsList: adOwnerIdsList,
vehicleBrandIdsList: brandsIdsList, vehicleBrandIdsList: brandsIdsList,
vehicleModelYearIdsList: vehicleYearIdsList, vehicleModelYearIdsList: vehicleYearIdsList,
vehicleAdConditionIdsList: conditionsIdsList, vehicleAdConditionIdsList: conditionsIdsList,
vehicleAdCreatedDateList: createdDatesList, vehicleAdCreatedDateList: createdDatesList,
page: pageIndex,
); );
if (!isFromLazyLoad) {
exploreAdsFilteredList.clear();
exploreAdsFilteredList = list;
setState(ViewState.idle); setState(ViewState.idle);
} else {
return list;
}
return [];
} }
void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd}) { void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd}) {
@ -1962,7 +2051,9 @@ class AdVM extends BaseVM {
updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.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 ?? "")); updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? ""));
updateSelectionVehicleMileageId(SelectionModel( updateSelectionVehicleMileageId(SelectionModel(
selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}")); 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 ?? "")); updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? ""));
updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? "")); updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? ""));
int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID); int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID);

@ -55,20 +55,17 @@ class AppointmentsVM extends BaseVM {
bool isUpcomingEnabled = true; bool isUpcomingEnabled = true;
bool isFetchingLists = false; bool isFetchingLists = false;
int selectedBranch = 0;
int selectedAppointmentIndex = 0; int selectedAppointmentIndex = 0;
int selectedAppointmentSubIndex = 0; int selectedAppointmentSubIndex = 0;
int selectedAppointmentId = 0; int selectedAppointmentId = 0;
int selectedBranchIdForAppointments = 0;
List<AppointmentListModel> myAppointments = []; List<AppointmentListModel> myAppointments = [];
List<AppointmentListModel> myUpComingAppointments = []; List<AppointmentListModel> myUpComingAppointments = [];
List<AppointmentListModel> myFilteredAppointments = []; List<AppointmentListModel> myFilteredAppointments = [];
List<FilterListModel> appointmentsFilterOptions = []; List<FilterListModel> appointmentsFilterOptions = [];
List<CustomerData> customersAppointments = [];
List<AppointmentListModel> myFilteredAppointments2 = []; List<AppointmentListModel> myFilteredAppointments2 = [];
// List<ScheduleData> availableSchedules = [];
bool isFetchingServices = false; bool isFetchingServices = false;
List<DropValue> branchCategories = []; List<DropValue> branchCategories = [];
@ -234,7 +231,6 @@ class AppointmentsVM extends BaseVM {
Utils.showToast(genericRespModel.message.toString()); Utils.showToast(genericRespModel.message.toString());
await getMyAppointmentsForCustomer(); await getMyAppointmentsForCustomer();
Utils.hideLoading(context); Utils.hideLoading(context);
getMyAppointmentsForCustomer();
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
} }
} catch (e) { } catch (e) {
@ -374,7 +370,7 @@ class AppointmentsVM extends BaseVM {
// appointmentStatusEnum.getIdFromAppointmentStatusEnum()] // appointmentStatusEnum.getIdFromAppointmentStatusEnum()]
// .isSelected = true; // .isSelected = true;
if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) { if (appointmentStatusEnum == AppointmentStatusEnum.allAppointments) {
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(); if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners(); notifyListeners();
@ -459,10 +455,10 @@ class AppointmentsVM extends BaseVM {
AppointmentSlots? appointmentSlots; AppointmentSlots? appointmentSlots;
Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map, required BuildContext context, bool isNeedToRebuild = false}) async { Future<void> getAppointmentSlotsInfo({required int branchID, required BuildContext context, bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(map); GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(branchID: branchID, fromDate: selectedDateForAppointments, toDate: selectedDateForAppointments);
if (genericRespModel.messageStatus == 1) { if (genericRespModel.messageStatus == 1) {
appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data); appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
} else { } else {
@ -473,9 +469,9 @@ class AppointmentsVM extends BaseVM {
} }
} }
Future<void> getMyAppointmentsForProvider(Map<String, dynamic> map) async { Future<void> getMyAppointmentsForProvider({required int branchID}) async {
setState(ViewState.busy); setState(ViewState.busy);
myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map); myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(branchID: branchID);
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments myUpComingAppointments = myAppointments
.where((element) => .where((element) =>
@ -1272,6 +1268,21 @@ class AppointmentsVM extends BaseVM {
return false; return false;
} }
ifAlreadyExistForStringValue({required List<String> list, required String value}) {
int index = list.indexWhere((element) {
log("element: $element");
log("value: $value");
return element == value;
});
if (index != -1) {
return true;
}
return false;
}
// Rating filter // Rating filter
double branchFilterByRating = 4.0; double branchFilterByRating = 4.0;
@ -1285,6 +1296,7 @@ class AppointmentsVM extends BaseVM {
List<DropValue> providersDropList = []; List<DropValue> providersDropList = [];
List<DropValue> servicesDropList = []; List<DropValue> servicesDropList = [];
List<DropValue> itemsDropList = []; List<DropValue> itemsDropList = [];
List<DropValue> serviceDeliveryTypesDropList = [];
Future<void> fetchAllProviders() async { Future<void> fetchAllProviders() async {
if (providersDropList.isNotEmpty) return; if (providersDropList.isNotEmpty) return;
@ -1351,6 +1363,25 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.idle); setState(ViewState.idle);
} }
Future<void> fetchAllServiceDeliveryTypes() async {
if (serviceDeliveryTypesDropList.isNotEmpty) return;
serviceDeliveryTypesDropList.clear();
setState(ViewState.busy);
List<EnumsModel> enums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.serviceDeliveryTypeEnumId);
for (EnumsModel element in enums) {
serviceDeliveryTypesDropList.add(
DropValue(
element.enumValue,
element.enumValueStr,
"",
),
);
}
setState(ViewState.idle);
}
Future<void> populateDataForBranchesFilter() async { Future<void> populateDataForBranchesFilter() async {
await fetchAllProviders(); await fetchAllProviders();
await fetchAllCategories(); await fetchAllCategories();
@ -1440,7 +1471,6 @@ class AppointmentsVM extends BaseVM {
branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", "")); branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", ""));
} }
setState(ViewState.idle); setState(ViewState.idle);
log("branchesDropList: ${branchesDropList.length}"); log("branchesDropList: ${branchesDropList.length}");
} }
@ -1449,6 +1479,7 @@ class AppointmentsVM extends BaseVM {
await fetchAllCategories(); await fetchAllCategories();
await fetchAllServices(); await fetchAllServices();
await fetchAllItems(); await fetchAllItems();
await fetchAllServiceDeliveryTypes();
} }
int appointmentFiltersCounter = 0; int appointmentFiltersCounter = 0;
@ -1661,15 +1692,132 @@ class AppointmentsVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
// Customer Name Filter for PROVIDER ONLY
List<String> appointmentFilterCustomerNameSearchHistory = [];
String currentCustomerNameFilter = '';
void onCurrentCustomerNameFilterChanged(var value) {
currentCustomerNameFilter = value;
notifyListeners();
}
void removeAppointmentFilterCustomerNameSearchHistory({bool isClear = false, required int index}) {
if (isClear) {
appointmentFilterCustomerNameSearchHistory.clear();
notifyListeners();
return;
}
appointmentFilterCustomerNameSearchHistory.removeAt(index);
if (appointmentFilterCustomerNameSearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
}
notifyListeners();
}
void addAppointmentFilterCustomerNameSearchHistory({required String value}) {
if (appointmentFilterCustomerNameSearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
}
if (!ifAlreadyExistForStringValue(list: appointmentFilterCustomerNameSearchHistory, value: value)) {
appointmentFilterCustomerNameSearchHistory.add(value);
currentCustomerNameFilter = "";
}
notifyListeners();
}
// MOBILE PHONE Filter for PROVIDER ONLY
String currentMobilePhoneFilter = '';
void onCurrentMobilePhoneFilterChanged(var value) {
currentMobilePhoneFilter = value;
notifyListeners();
}
List<String> appointmentFilterMobilePhoneSearchHistory = [];
void removeAppointmentFilterMobilePhoneSearchHistory({bool isClear = false, required int index}) {
if (isClear) {
appointmentFilterMobilePhoneSearchHistory.clear();
notifyListeners();
return;
}
appointmentFilterMobilePhoneSearchHistory.removeAt(index);
if (appointmentFilterMobilePhoneSearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
}
notifyListeners();
}
void addAppointmentFilterMobilePhoneSearchHistory({required String value}) {
if (appointmentFilterMobilePhoneSearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
}
if (!ifAlreadyExistForStringValue(list: appointmentFilterMobilePhoneSearchHistory, value: value)) {
appointmentFilterMobilePhoneSearchHistory.add(value);
currentMobilePhoneFilter = "";
}
notifyListeners();
}
// Service Delivery Types For PROVIDER ONLY
List<DropValue> appointmentFilterServiceDeliverySearchHistory = [];
void removeAppointmentFilterServiceDeliverySearchHistory({bool isClear = false, required int index}) {
if (isClear) {
appointmentFilterServiceDeliverySearchHistory.clear();
notifyListeners();
return;
}
appointmentFilterServiceDeliverySearchHistory.removeAt(index);
if (appointmentFilterServiceDeliverySearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
}
notifyListeners();
}
void addAppointmentFilterServiceDeliverySearchHistory({required DropValue value}) {
if (appointmentFilterServiceDeliverySearchHistory.isEmpty) {
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
}
appointmentFilterServiceDeliverySearchHistory.add(value);
notifyListeners();
}
SelectionModel appointmentFilterSelectedServiceDeliveryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateAppointmentFilterSelectedServiceDeliveryId(SelectionModel id, {bool isForSearch = false}) async {
if (isForSearch) {
DropValue itemsDrop = serviceDeliveryTypesDropList.firstWhere((element) => element.id == id.selectedId);
if (!ifAlreadyExist(list: appointmentFilterServiceDeliverySearchHistory, value: itemsDrop)) {
addAppointmentFilterServiceDeliverySearchHistory(value: itemsDrop);
}
}
// appointmentFilterSelectedServiceId = id;
notifyListeners();
}
void clearAppointmentFilterSelections() { void clearAppointmentFilterSelections() {
appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedItemId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); appointmentFilterSelectedItemId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedServiceDeliveryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
} }
void clearAppointmentFilters() { void clearAppointmentFilters() {
appointmentFilterServiceDeliverySearchHistory.clear();
appointmentFilterCustomerNameSearchHistory.clear();
appointmentFilterMobilePhoneSearchHistory.clear();
appointmentFilterItemsSearchHistory.clear(); appointmentFilterItemsSearchHistory.clear();
appointmentFilterServicesSearchHistory.clear(); appointmentFilterServicesSearchHistory.clear();
appointmentFilterCategorySearchHistory.clear(); appointmentFilterCategorySearchHistory.clear();
@ -1677,11 +1825,16 @@ class AppointmentsVM extends BaseVM {
appointmentFilterBranchSearchHistory.clear(); appointmentFilterBranchSearchHistory.clear();
appointmentFiltersCounter = 0; appointmentFiltersCounter = 0;
clearAppointmentFilterSelections(); clearAppointmentFilterSelections();
if (AppState().currentAppType == AppType.provider) {
getMyAppointmentsForProvider(branchID: selectedBranchIdForAppointments);
} else {
getMyAppointmentsForCustomer(); getMyAppointmentsForCustomer();
}
notifyListeners(); notifyListeners();
} }
Future<void> getAppointmentsBasedOnFilters() async { Future<void> getAppointmentsBasedOnFiltersForCustomer() async {
setState(ViewState.busy); setState(ViewState.busy);
List<String> providersIdsList = []; List<String> providersIdsList = [];
if (appointmentFilterProviderSearchHistory.isNotEmpty) { if (appointmentFilterProviderSearchHistory.isNotEmpty) {
@ -1725,6 +1878,56 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.idle); setState(ViewState.idle);
} }
String selectedDateForAppointments = "";
Future<void> getAppointmentsBasedOnFiltersForProviders({required int branchID}) async {
setState(ViewState.busy);
List<String> servicesIdsList = [];
if (appointmentFilterServicesSearchHistory.isNotEmpty) {
for (var element in appointmentFilterServicesSearchHistory) {
servicesIdsList.add(element.id.toString());
}
}
List<String> customerNamesList = [];
if (appointmentFilterCustomerNameSearchHistory.isNotEmpty) {
for (var element in appointmentFilterCustomerNameSearchHistory) {
customerNamesList.add(element.toString());
}
}
List<String> customerPhonesList = [];
if (appointmentFilterMobilePhoneSearchHistory.isNotEmpty) {
for (var element in appointmentFilterMobilePhoneSearchHistory) {
customerPhonesList.add(element.toString());
}
}
List<String> customerDeliveryTypesList = [];
if (appointmentFilterServiceDeliverySearchHistory.isNotEmpty) {
for (var element in appointmentFilterServiceDeliverySearchHistory) {
customerDeliveryTypesList.add(element.id.toString());
}
}
log("customerNamesList: $customerNamesList");
log("customerPhonesList: $customerPhonesList");
log("customerDeliveryTypesList: $customerDeliveryTypesList");
log("servicesIdsList: $servicesIdsList");
myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(
branchID: branchID,
customerNamesList: customerNamesList,
customerPhonesList: customerPhonesList,
deliveryTypeIdsList: customerDeliveryTypesList,
serviceProviderServiceIdsList: servicesIdsList,
fromDate: selectedDateForAppointments,
toDate: selectedDateForAppointments);
log(" myFilteredAppointments : ${myFilteredAppointments.length}");
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
setState(ViewState.idle);
}
Future<bool> addProviderToFavorite({required int serviceProviderID, required BuildContext context}) async { Future<bool> addProviderToFavorite({required int serviceProviderID, required BuildContext context}) async {
Utils.showLoading(context); Utils.showLoading(context);
try { try {

@ -97,8 +97,8 @@ class ChatVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
List<int> indexesForCancelSpecialCarOffer = [0, 1, 5, 6, 10]; List<int> indexesForCancelSpecialCarOffer = [0, 1, 6, 10];
List<int> indexesForCancelSparePartOffer = [2, 5, 6, 10]; List<int> indexesForCancelSparePartOffer = [2, 10];
List<int> indexesForRejectOffer = [3, 4, 10]; List<int> indexesForRejectOffer = [3, 4, 10];
List<int> indexesForDealNotCompleted = [7, 4, 8, 9, 10]; List<int> indexesForDealNotCompleted = [7, 4, 8, 9, 10];
@ -363,7 +363,7 @@ class ChatVM extends BaseVM {
required String offerPrice, required String offerPrice,
required bool isDeliveryAvailable, required bool isDeliveryAvailable,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required List<dynamic> offerImages, required List<dynamic> offerImages,
required BuildContext context, required BuildContext context,
@ -387,7 +387,7 @@ class ChatVM extends BaseVM {
"IsDeliveryAvailable": isDeliveryAvailable, "IsDeliveryAvailable": isDeliveryAvailable,
"ServiceItem": serviceItemName, "ServiceItem": serviceItemName,
"ReqOfferImages": offerImages, "ReqOfferImages": offerImages,
"OfferedItemCreatedBy": manufacturedById, // TODO: The ID should be used from the manufacturer database "OfferedItemCreatedBy": manufacturedByName,
// "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime // "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime
"ServiceProviderID": providerId, "ServiceProviderID": providerId,
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(), "OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
@ -443,8 +443,8 @@ class ChatVM extends BaseVM {
imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false));
} }
pickedImagesForMessage.addAll(imageModels); pickedImagesForMessage.addAll(imageModels);
if (pickedImagesForMessage.length > GlobalConsts().maxFileCount) { if (pickedImagesForMessage.length > GlobalConsts.maxFileCount) {
pickedImagesForMessage = pickedImagesForMessage.sublist(0, GlobalConsts().maxFileCount); pickedImagesForMessage = pickedImagesForMessage.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
@ -652,7 +652,7 @@ class ChatVM extends BaseVM {
required int requestOfferID, required int requestOfferID,
required String offerPrice, required String offerPrice,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required RequestOfferStatusEnum requestOfferStatusEnum, required RequestOfferStatusEnum requestOfferStatusEnum,
required BuildContext context, required BuildContext context,
@ -674,8 +674,8 @@ class ChatVM extends BaseVM {
"RequestID": requestId, "RequestID": requestId,
"Price": double.parse(offerPrice), "Price": double.parse(offerPrice),
"ServiceItem": serviceItemName, "ServiceItem": serviceItemName,
"OfferedItemCreatedBy": manufacturedById, // TODO: The ID should be used from the manufacturer database "OfferedItemCreatedBy": manufacturedByName,
// "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime // "OfferedItemCreatedOn": manufacturedOn,
"ServiceProviderID": serviceProviderID, "ServiceProviderID": serviceProviderID,
"OfferStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum(), "OfferStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum(),
"Comment": comments, "Comment": comments,

@ -83,7 +83,7 @@ class DashboardVMProvider extends BaseVM {
shippingManagementVM.populateShippingRequestFilterList(); shippingManagementVM.populateShippingRequestFilterList();
await serviceVM.getBranchAndServices(); await serviceVM.getBranchAndServices();
await serviceVM.populateBranchServiceFilters(); await serviceVM.populateBranchServiceFilters();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0"}); await appointmentVM.getMyAppointmentsForProvider(branchID: appointmentVM.selectedBranchIdForAppointments);
adVM.populateAdsFilterList(); adVM.populateAdsFilterList();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true); await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) { if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) {

@ -39,7 +39,6 @@ class RequestsVM extends BaseVM {
RequestsVM({required this.commonServices, required this.commonRepo, required this.requestRepo}); RequestsVM({required this.commonServices, required this.commonRepo, required this.requestRepo});
List<RequestModel> myRequests = [];
List<RequestModel> myFilteredRequests = []; List<RequestModel> myFilteredRequests = [];
List<FilterListModel> requestsTypeFilterOptions = []; List<FilterListModel> requestsTypeFilterOptions = [];
@ -92,8 +91,39 @@ class RequestsVM extends BaseVM {
setState(ViewState.idle); setState(ViewState.idle);
} }
int pageIndexForRequests = 1;
bool hasMoreDataRequests = true;
bool isLoadingMore = false;
// Future<void> fetchMoreRequests() async {
// log("isLoadingMore: $isLoadingMore");
// log("hasMoreDataRequests: $hasMoreDataRequests");
// if (isLoadingMore) return;
// isLoadingMore = true;
// hasMoreDataRequests = true;
// notifyListeners();
// try {
// final List<RequestModel> newRequests = await requestRepo.getRequestsBasedOnFilters(requestedDate: requestedDateFilter, requestTypeId: requestTypeId);
// if (newAds.isEmpty) {
// hasMoreDataForExploreAds = false;
// } else {
// exploreAdsFilteredList.addAll(newAds);
// pageIndexForExploreAds++;
// if (exploreAdsFilteredList.length < exploreAdsFilteredList.last.totalItemsCount!) {
// hasMoreDataForExploreAds = true;
// } else {
// hasMoreDataForExploreAds = false;
// }
// }
// } catch (error) {
// isLoadingMore = false;
// Utils.showToast(error.toString());
// }
// isLoadingMore = false;
// notifyListeners();
// }
Future<bool> getRequestsBasedOnFilters() async { Future<bool> getRequestsBasedOnFilters() async {
myFilteredRequests.clear();
setState(ViewState.busy); setState(ViewState.busy);
int requestTypeIdApi = requestsTypeFilterOptions.firstWhere((element) => element.isSelected).id; int requestTypeIdApi = requestsTypeFilterOptions.firstWhere((element) => element.isSelected).id;
@ -127,7 +157,7 @@ class RequestsVM extends BaseVM {
); );
setState(ViewState.idle); setState(ViewState.idle);
return true; return true;
} catch (e, s) { } catch (e) {
logger.i("e: ${e.toString()}"); logger.i("e: ${e.toString()}");
setState(ViewState.idle); setState(ViewState.idle);
return false; return false;
@ -186,7 +216,7 @@ class RequestsVM extends BaseVM {
} }
overwriteChatMessagesInRequestsModel({required List<ChatMessageModel> messages, required int index, required BuildContext context}) { overwriteChatMessagesInRequestsModel({required List<ChatMessageModel> messages, required int index, required BuildContext context}) {
myFilteredRequests[index].chatMessages.clear(); if (myFilteredRequests.isEmpty) return;
myFilteredRequests[index].chatMessages = messages; myFilteredRequests[index].chatMessages = messages;
if (myFilteredRequests[index].chatMessages.isNotEmpty) { if (myFilteredRequests[index].chatMessages.isNotEmpty) {
for (var message in myFilteredRequests[index].chatMessages) { for (var message in myFilteredRequests[index].chatMessages) {
@ -237,8 +267,8 @@ class RequestsVM extends BaseVM {
imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false));
} }
pickedVehicleImages.addAll(imageModels); pickedVehicleImages.addAll(imageModels);
if (pickedVehicleImages.length > GlobalConsts().maxFileCount) { if (pickedVehicleImages.length > GlobalConsts.maxFileCount) {
pickedVehicleImages = pickedVehicleImages.sublist(0, GlobalConsts().maxFileCount); pickedVehicleImages = pickedVehicleImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
@ -246,8 +276,6 @@ class RequestsVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
bool isFetchingRequestType = false; bool isFetchingRequestType = false;
bool isFetchingVehicleType = true; bool isFetchingVehicleType = true;
bool isFetchingVehicleDetail = false; bool isFetchingVehicleDetail = false;
@ -914,7 +942,7 @@ class RequestsVM extends BaseVM {
return genericRespModel.messageStatus == 1; return genericRespModel.messageStatus == 1;
} catch (e) { } catch (e) {
logger.i(e.toString()); logger.i(e.toString());
// Utils.showToast(e.toString()); Utils.showToast(e.toString());
if (needLoading) { if (needLoading) {
Utils.hideLoading(context); Utils.hideLoading(context);
} }
@ -933,7 +961,7 @@ class RequestsVM extends BaseVM {
offerPriceError = ""; offerPriceError = "";
} }
if (offerDescription.isEmpty) { if (offerDescription.isEmpty || offerDescription.length < 5) {
offerDescriptionError = GlobalConsts.descriptionError; offerDescriptionError = GlobalConsts.descriptionError;
isValidated = false; isValidated = false;
notifyListeners(); notifyListeners();
@ -1022,7 +1050,7 @@ class RequestsVM extends BaseVM {
required String offerPrice, required String offerPrice,
required bool isDeliveryAvailable, required bool isDeliveryAvailable,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required int receiverId, required int receiverId,
required int customerRequestIndex, required int customerRequestIndex,
@ -1044,7 +1072,7 @@ class RequestsVM extends BaseVM {
offerPrice: offerPrice, offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable, isDeliveryAvailable: isDeliveryAvailable,
serviceItemName: serviceItemName, serviceItemName: serviceItemName,
manufacturedById: manufacturedById, manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn, manufacturedOn: manufacturedOn,
requestImages: offerImages, requestImages: offerImages,
requestOfferStatusEnum: RequestOfferStatusEnum.offer, requestOfferStatusEnum: RequestOfferStatusEnum.offer,
@ -1068,7 +1096,7 @@ class RequestsVM extends BaseVM {
pop(context); pop(context);
} }
} }
} catch (e, s) { } catch (e) {
Utils.hideLoading(context); Utils.hideLoading(context);
log(e.toString()); log(e.toString());
Utils.showToast(e.toString()); Utils.showToast(e.toString());
@ -1082,7 +1110,7 @@ class RequestsVM extends BaseVM {
required int requestId, required int requestId,
required String offerPrice, required String offerPrice,
required String serviceItemName, required String serviceItemName,
required int manufacturedById, required String manufacturedByName,
required String manufacturedOn, required String manufacturedOn,
required RequestModel requestModel, required RequestModel requestModel,
required bool isDeliveryAvailable, required bool isDeliveryAvailable,
@ -1105,7 +1133,7 @@ class RequestsVM extends BaseVM {
requestId: requestId, requestId: requestId,
offerPrice: offerPrice, offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable, isDeliveryAvailable: isDeliveryAvailable,
manufacturedById: manufacturedById, manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn, manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName, serviceItemName: serviceItemName,
offerImages: offerImages, offerImages: offerImages,
@ -1139,7 +1167,7 @@ class RequestsVM extends BaseVM {
requestID: requestModel.id, requestID: requestModel.id,
price: double.parse(offerPrice), price: double.parse(offerPrice),
isDeliveryAvailable: isDeliveryAvailable, isDeliveryAvailable: isDeliveryAvailable,
manufacturedById: manufacturedById, manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn, manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName, serviceItemName: serviceItemName,
requestOfferStatusEnum: RequestOfferStatusEnum.offer, requestOfferStatusEnum: RequestOfferStatusEnum.offer,

@ -140,8 +140,8 @@ class ServiceVM extends BaseVM {
imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false));
} }
pickedBranchImages.addAll(imageModels); pickedBranchImages.addAll(imageModels);
if (pickedBranchImages.length > GlobalConsts().maxFileCount) { if (pickedBranchImages.length > GlobalConsts.maxFileCount) {
pickedBranchImages = pickedBranchImages.sublist(0, GlobalConsts().maxFileCount); pickedBranchImages = pickedBranchImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection);
} }
if (pickedBranchImages.isNotEmpty) branchImageError = ""; if (pickedBranchImages.isNotEmpty) branchImageError = "";
@ -168,7 +168,6 @@ class ServiceVM extends BaseVM {
final BranchDetailModel currentBranch = branches!.data!.serviceProviderBranch!.firstWhere((element) => element.id == selectedBranchId); final BranchDetailModel currentBranch = branches!.data!.serviceProviderBranch!.firstWhere((element) => element.id == selectedBranchId);
for (var element in currentBranch.branchServices!) { for (var element in currentBranch.branchServices!) {
// TODO: Here , we need to add the category deactivated status.
categories.add( categories.add(
CategoryData( CategoryData(
id: element.categoryId, id: element.categoryId,
@ -567,6 +566,25 @@ class ServiceVM extends BaseVM {
} }
} }
Future<bool> updateCategoryStatus({required BuildContext context, required ServiceStatusEnum serviceStatusEnum, required int branchId, required int categoryId}) async {
try {
Utils.showLoading(context);
GenericRespModel genericRespModel = await branchRepo.updateCategoryStatus(
branchId: branchId,
categoryId: categoryId,
serviceStatusEnum: serviceStatusEnum,
);
Utils.hideLoading(context);
Utils.showToast(genericRespModel.message ?? "");
return genericRespModel.messageStatus == 1;
} catch (e) {
Utils.hideLoading(context);
log(e.toString());
Utils.showToast(e.toString());
return false;
}
}
Future buildDealNotCompletedBottomSheetOptions({required BuildContext mainContext, required List<AppointmentBasicDetailsModel> appointments, required String branchName}) async { Future buildDealNotCompletedBottomSheetOptions({required BuildContext mainContext, required List<AppointmentBasicDetailsModel> appointments, required String branchName}) async {
return actionConfirmationBottomSheet( return actionConfirmationBottomSheet(
isOnlyOneButton: true, isOnlyOneButton: true,
@ -628,6 +646,7 @@ class ServiceVM extends BaseVM {
} }
List<ServiceModel>? matchedServices; List<ServiceModel>? matchedServices;
bool isAllSelected = false; bool isAllSelected = false;
Future<void> getAllMatchedServices({required int oldBranchId, required int newBranchId, required int categoryId}) async { Future<void> getAllMatchedServices({required int oldBranchId, required int newBranchId, required int categoryId}) async {

@ -294,7 +294,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
adVM.state == ViewState.busy adVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: adVM.photoSSSchedulesByOffices.isEmpty : adVM.photoSSSchedulesByOffices.isEmpty
? LocaleKeys.noAvailableOfficesInCity.tr().toText(fontSize: 14, height: 1.2) ? LocaleKeys.noAvailableOfficesInCity.tr().toText(fontSize: 14, height: 1.2, color: MyColors.lightTextColor)
: Builder( : Builder(
builder: (context) { builder: (context) {
List<DropValue> vehicleCitiesDrop = []; List<DropValue> vehicleCitiesDrop = [];

@ -78,13 +78,13 @@ class _AdsFilterViewState extends State<AdsFilterView> {
SearchEntityWidget( SearchEntityWidget(
title: LocaleKeys.searchByCity.tr(), title: LocaleKeys.searchByCity.tr(),
actionWidget: Builder(builder: (context) { actionWidget: Builder(builder: (context) {
List<DropValue> vehicleBrandsDrop = []; List<DropValue> vehicleCitiesDrop = [];
for (var element in adVM.vehicleCities) { for (var element in adVM.vehicleCities) {
vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); vehicleCitiesDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", ""));
} }
return DropdownField( return DropdownField(
(DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), (DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: vehicleBrandsDrop, list: vehicleCitiesDrop,
dropdownValue: adVM.vehicleCityId.selectedId != -1 ? DropValue(adVM.vehicleCityId.selectedId, adVM.vehicleCityId.selectedOption, "") : null, dropdownValue: adVM.vehicleCityId.selectedId != -1 ? DropValue(adVM.vehicleCityId.selectedId, adVM.vehicleCityId.selectedOption, "") : null,
hint: LocaleKeys.selectCity.tr(), hint: LocaleKeys.selectCity.tr(),
errorValue: adVM.vehicleCityId.errorValue, errorValue: adVM.vehicleCityId.errorValue,
@ -99,7 +99,7 @@ class _AdsFilterViewState extends State<AdsFilterView> {
title: LocaleKeys.searchByBrandName.tr(), title: LocaleKeys.searchByBrandName.tr(),
actionWidget: Builder(builder: (context) { actionWidget: Builder(builder: (context) {
List<DropValue> vehicleBrandsDrop = []; List<DropValue> vehicleBrandsDrop = [];
for (var element in adVM.vehicleBrands) { for (var element in adVM.vehicleBrandsForFilters) {
vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", "")); vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", ""));
} }
return DropdownField( return DropdownField(
@ -160,6 +160,29 @@ class _AdsFilterViewState extends State<AdsFilterView> {
onHistoryItemTapped: (DropValue value) => null, onHistoryItemTapped: (DropValue value) => null,
), ),
const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7),
SearchEntityWidget(
title: LocaleKeys.searchByAdOwner.tr(),
actionWidget: Builder(
builder: (context) {
List<DropValue> vehicleOwnerDrop = [];
for (var element in adVM.adOwnerEnumsFilter) {
vehicleOwnerDrop.add(DropValue(element.enumValue.toInt(), element.enumValueStr, ""));
}
return DropdownField(
(DropValue value) =>
adVM.updateSelectionVehicleAdOwnerId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true, showSelectionInDropdown: false),
list: vehicleOwnerDrop,
dropdownValue: adVM.vehicleOwnerId.selectedId != -1 ? DropValue(adVM.vehicleOwnerId.selectedId, adVM.vehicleOwnerId.selectedOption, "") : null,
hint: LocaleKeys.selectOwner.tr(),
errorValue: adVM.vehicleOwnerId.errorValue,
);
},
),
historyContent: adVM.vehicleAdOwnerSearchHistory,
onHistoryItemDeleted: (index) => adVM.removeVehicleAdOwnerSearchHistory(index: index),
onHistoryItemTapped: (DropValue value) => null,
),
const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7),
SearchEntityWidget( SearchEntityWidget(
title: LocaleKeys.searchByCreatedDate.tr(), title: LocaleKeys.searchByCreatedDate.tr(),
actionWidget: TxtField( actionWidget: TxtField(
@ -197,7 +220,7 @@ class _AdsFilterViewState extends State<AdsFilterView> {
title: LocaleKeys.search.tr(), title: LocaleKeys.search.tr(),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
adVM.getAdsBasedOnFilters(); adVM.getAdsBasedOnFilters(isFromLazyLoad: false, pageIndex: 0);
}, },
backgroundColor: MyColors.darkPrimaryColor, backgroundColor: MyColors.darkPrimaryColor,
txtColor: MyColors.white, txtColor: MyColors.white,

@ -10,6 +10,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/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.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/ad_view_model.dart';
@ -21,12 +22,14 @@ class AdsListWidget extends StatelessWidget {
final ScrollPhysics? scrollPhysics; final ScrollPhysics? scrollPhysics;
final bool isAdsFragment; final bool isAdsFragment;
final bool shouldShowAdStatus; final bool shouldShowAdStatus;
final bool hasMoreData;
final Function()? onFetchMoreAds; final Function()? onFetchMoreAds;
const AdsListWidget({ const AdsListWidget({
super.key, super.key,
required this.adsList, required this.adsList,
required this.shouldShowAdStatus, required this.shouldShowAdStatus,
required this.hasMoreData,
this.onFetchMoreAds, this.onFetchMoreAds,
this.scrollPhysics, this.scrollPhysics,
this.isAdsFragment = false, this.isAdsFragment = false,
@ -44,7 +47,8 @@ class AdsListWidget extends StatelessWidget {
} }
return NotificationListener<ScrollNotification>( return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) { onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && context.read<AdVM>().hasMoreData) { log("hasMoreData: $hasMoreData");
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && hasMoreData) {
if (onFetchMoreAds != null) { if (onFetchMoreAds != null) {
onFetchMoreAds!(); onFetchMoreAds!();
} }
@ -104,7 +108,9 @@ class AdCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
if (isAdsFragment && !context.read<AdVM>().isExploreAdsTapped) ...[ if (isAdsFragment && adDetails.adPostStatus! == AdPostStatus.sold) ...[
Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
] else if (isAdsFragment && !context.read<AdVM>().isExploreAdsTapped) ...[
Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)), Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
], ],
(adDetails.vehicle!.vehicleTitle ?? "").toText( (adDetails.vehicle!.vehicleTitle ?? "").toText(

@ -1,7 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
@ -16,6 +18,7 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/search_entity_widget.dart'; import 'package:mc_common_app/widgets/common_widgets/search_entity_widget.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.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/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart'; import 'package:sizer/sizer.dart';
@ -33,6 +36,7 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
void initState() { void initState() {
appointmentsVM = context.read<AppointmentsVM>(); appointmentsVM = context.read<AppointmentsVM>();
scheduleMicrotask(() async { scheduleMicrotask(() async {
log('herre called');
await appointmentsVM.populateDataForAppointmentsFilter(); await appointmentsVM.populateDataForAppointmentsFilter();
}); });
super.initState(); super.initState();
@ -44,6 +48,21 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
super.dispose(); super.dispose();
} }
// Provider filters
// * Service
// * Customer name
// * Mobile number
// * Type of service Delivery
// Customer filters
// * Provider
// * Branch
// * Category
// * Service
// * Item
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -59,16 +78,73 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
), ),
body: Consumer<AppointmentsVM>( body: Consumer<AppointmentsVM>(
builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
return WillPopScope( return PopScope(
onWillPop: () async { onPopInvokedWithResult: (bool result, dynamic) {
if (result) {
context.read<AdVM>().resetValues(); context.read<AdVM>().resetValues();
return true; }
}, },
child: Column( child: Column(
children: [ children: [
ListView( ListView(
children: [ children: [
20.height, 20.height,
if (AppState().currentAppType == AppType.provider) ...[
SearchEntityWidget(
title: LocaleKeys.searchByCustomerName.tr(),
isForString: true,
actionWidget: TxtField(
value: appointmentsVM.currentCustomerNameFilter,
onChanged: (value) => appointmentsVM.onCurrentCustomerNameFilterChanged(value),
hint: LocaleKeys.enterCustomerName.tr(),
postfixWidget: Consumer(
builder: (BuildContext context, AppointmentsVM appointmentVm, Widget? child) {
if (appointmentsVM.currentCustomerNameFilter.isEmpty) {
return const SizedBox();
}
return IconButton(
onPressed: () => appointmentsVM.addAppointmentFilterCustomerNameSearchHistory(value: appointmentsVM.currentCustomerNameFilter),
icon: const Icon(Icons.done, color: MyColors.lightIconColor),
);
},
),
),
historyContentString: appointmentsVM.appointmentFilterCustomerNameSearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterCustomerNameSearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) => null,
historyContent: const [], // ignore in the case of TEXT FIELD
),
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
SearchEntityWidget(
title: LocaleKeys.searchByMobileNumber.tr(),
isForString: true,
actionWidget: TxtField(
onChanged: (value) => appointmentsVM.onCurrentMobilePhoneFilterChanged(value),
value: appointmentsVM.currentMobilePhoneFilter,
hint: LocaleKeys.enterMobileNumber.tr(),
postfixWidget: Consumer(
builder: (BuildContext context, AppointmentsVM appointmentVm, Widget? child) {
if (appointmentsVM.currentMobilePhoneFilter.isEmpty) {
return const SizedBox();
}
return IconButton(
onPressed: () => appointmentsVM.addAppointmentFilterMobilePhoneSearchHistory(value: appointmentsVM.currentMobilePhoneFilter),
icon: const Icon(Icons.done, color: MyColors.lightIconColor),
);
},
),
),
historyContentString: appointmentsVM.appointmentFilterMobilePhoneSearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterMobilePhoneSearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) => null,
historyContent: const [], // ignore in the case of TEXT FIELD
),
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
] else ...[
SearchEntityWidget( SearchEntityWidget(
title: LocaleKeys.searchByProvider.tr(), title: LocaleKeys.searchByProvider.tr(),
actionWidget: Builder( actionWidget: Builder(
@ -149,6 +225,7 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
), ),
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
],
SearchEntityWidget( SearchEntityWidget(
title: LocaleKeys.searchByService.tr(), title: LocaleKeys.searchByService.tr(),
actionWidget: Builder(builder: (context) { actionWidget: Builder(builder: (context) {
@ -166,6 +243,7 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
onHistoryItemTapped: (DropValue value) => null, onHistoryItemTapped: (DropValue value) => null,
), ),
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
if (AppState().currentAppType == AppType.customer) ...[
SearchEntityWidget( SearchEntityWidget(
title: LocaleKeys.searchByItem.tr(), title: LocaleKeys.searchByItem.tr(),
actionWidget: Builder(builder: (context) { actionWidget: Builder(builder: (context) {
@ -182,6 +260,24 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterItemsSearchHistory(index: index), onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterItemsSearchHistory(index: index),
onHistoryItemTapped: (DropValue value) => null, onHistoryItemTapped: (DropValue value) => null,
), ),
] else ...[
SearchEntityWidget(
title: LocaleKeys.searchByServiceDelivery.tr(),
actionWidget: Builder(builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedServiceDeliveryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.serviceDeliveryTypesDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedServiceDeliveryId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedServiceDeliveryId.selectedId, appointmentsVM.appointmentFilterSelectedServiceDeliveryId.selectedOption, "")
: null,
hint: LocaleKeys.selectDeliveryType.tr(),
);
}),
historyContent: appointmentsVM.appointmentFilterServiceDeliverySearchHistory,
onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterServiceDeliverySearchHistory(index: index),
onHistoryItemTapped: (DropValue value) => null,
),
],
], ],
).expand(), ).expand(),
Container( Container(
@ -197,7 +293,12 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
title: LocaleKeys.search.tr(), title: LocaleKeys.search.tr(),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
appointmentsVM.getAppointmentsBasedOnFilters();
if (AppState().currentAppType == AppType.provider) {
appointmentsVM.getAppointmentsBasedOnFiltersForProviders(branchID: appointmentsVM.selectedBranchIdForAppointments);
} else {
appointmentsVM.getAppointmentsBasedOnFiltersForCustomer();
}
}, },
backgroundColor: MyColors.darkPrimaryColor, backgroundColor: MyColors.darkPrimaryColor,
txtColor: MyColors.white, txtColor: MyColors.white,
@ -208,7 +309,9 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
), ),
8.height, 8.height,
InkWell( InkWell(
onTap: () => appointmentsVM.clearAppointmentFilters(), onTap: () {
appointmentsVM.clearAppointmentFilters();
},
child: LocaleKeys.clearFilters.tr().toText( child: LocaleKeys.clearFilters.tr().toText(
fontSize: 14, fontSize: 14,
isBold: true, isBold: true,

@ -13,6 +13,7 @@ import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart'; import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart'; import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ads_buyer_chats_view.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart'; import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart'; import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart';
import 'package:mc_common_app/views/chat/widgets/chat_message_widget.dart'; import 'package:mc_common_app/views/chat/widgets/chat_message_widget.dart';
@ -111,18 +112,39 @@ class _ChatViewState extends State<ChatView> {
padding: const EdgeInsets.symmetric(horizontal: 21, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 21, vertical: 10),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"Your Delivery / Shipping Status is: ".toText( Expanded(
flex: 4,
child: Row(
children: [
Flexible(
child: "${LocaleKeys.deliveryStatus.tr()} ${Utils.getNameByShippingRequestStatusEnum(requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.pending)}"
.toText(
fontSize: 12, fontSize: 12,
color: Colors.white, color: Colors.white,
decorationColor: MyColors.white, decorationColor: MyColors.white,
), ),
Utils.getNameByShippingRequestStatusEnum(requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated).toText(
fontSize: 16,
color: Colors.white,
), ),
], ],
), ),
),
10.width,
if ((requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.pending) == ShippingRequestStatusEnum.delivered) ...[
Expanded(
flex: 2,
child: "${LocaleKeys.markAsCompleted.tr()} ".toText(isUnderLine: true, fontSize: 12, color: Colors.white, decorationColor: MyColors.white).onPress(() {
return dealCompletedConsentBottomSheet(
mainContext: context,
requestStatusEnum: RequestStatusEnum.completed,
requestId: requestVM.currentSelectedRequest!.id,
showAcknowledgement: false,
);
}),
),
],
],
),
); );
} }
@ -138,9 +160,11 @@ class _ChatViewState extends State<ChatView> {
if (AppState().currentAppType == AppType.customer && chatVM.serviceProviderOffersList.isNotEmpty) { if (AppState().currentAppType == AppType.customer && chatVM.serviceProviderOffersList.isNotEmpty) {
chatMessages = chatVM.serviceProviderOffersList[chatViewArgumentsForRequest!.providerIndex].chatMessages ?? []; chatMessages = chatVM.serviceProviderOffersList[chatViewArgumentsForRequest!.providerIndex].chatMessages ?? [];
} else { } else {
if (requestVM.myFilteredRequests.isNotEmpty) {
chatMessages = requestVM.myFilteredRequests[chatViewArgumentsForRequest!.requestIndex].chatMessages; chatMessages = requestVM.myFilteredRequests[chatViewArgumentsForRequest!.requestIndex].chatMessages;
} }
} }
}
return Column( return Column(
children: [ children: [
if (appBarHeadlines != null) ...[ if (appBarHeadlines != null) ...[
@ -208,7 +232,8 @@ class _ChatViewState extends State<ChatView> {
// ), // ),
// ] // ]
// //
else ...[ else
...[
if (AppState().currentAppType == AppType.provider && if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer && chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted && requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
@ -245,7 +270,8 @@ class _ChatViewState extends State<ChatView> {
onAddFilePressed: () => chatVM.pickMultipleImages(), onAddFilePressed: () => chatVM.pickMultipleImages(),
), ),
), ),
] else if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[ ] else
if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
Expanded( Expanded(
flex: 1, flex: 1,
child: const Icon( child: const Icon(

@ -18,14 +18,20 @@ import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart'; import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
void dealCompletedConsentBottomSheet({required BuildContext mainContext, required RequestStatusEnum requestStatusEnum, required int requestId, Function()? acceptRequestOffer}) { void dealCompletedConsentBottomSheet({
required BuildContext mainContext,
required RequestStatusEnum requestStatusEnum,
required int requestId,
required bool showAcknowledgement,
Function()? acceptRequestOffer,
}) {
final requestVM = mainContext.read<RequestsVM>(); final requestVM = mainContext.read<RequestsVM>();
return actionConfirmationBottomSheet( return actionConfirmationBottomSheet(
isOnlyOneButton: AppState().currentAppType == AppType.customer, isOnlyOneButton: showAcknowledgement,
context: mainContext, context: mainContext,
title: LocaleKeys.doYouWantToCompleteThisDeal.tr().toText(fontSize: 26, isBold: true, letterSpacing: -1.44), title: LocaleKeys.doYouWantToCompleteThisDeal.tr().toText(fontSize: 26, isBold: true, letterSpacing: -1.44),
subtitle: AppState().currentAppType == AppType.provider ? LocaleKeys.providerCompletingDealMeansThat.tr() : LocaleKeys.customerCompletingDealMeansThat.tr(), subtitle: AppState().currentAppType == AppType.provider ? LocaleKeys.providerCompletingDealMeansThat.tr() : LocaleKeys.customerCompletingDealMeansThat.tr(),
checkBoxConfirmationWidget: AppState().currentAppType == AppType.customer checkBoxConfirmationWidget: showAcknowledgement
? Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) { ? Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) {
return Row( return Row(
children: [ children: [
@ -47,14 +53,13 @@ void dealCompletedConsentBottomSheet({required BuildContext mainContext, require
return Expanded( return Expanded(
child: ShowFillButton( child: ShowFillButton(
maxHeight: 55, maxHeight: 55,
isDisabled: !chatVM.acknowledgePaymentToMowaterStatus, isDisabled: showAcknowledgement == false ? false : !chatVM.acknowledgePaymentToMowaterStatus,
title: AppState().currentAppType == AppType.customer ? LocaleKeys.submit.tr() : LocaleKeys.yes.tr(), title: showAcknowledgement ? LocaleKeys.submit.tr() : LocaleKeys.yes.tr(),
fontSize: 15, fontSize: 15,
onPressed: () async { onPressed: () async {
pop(context); pop(context);
bool statusForReqAccept = false; bool statusForReqAccept = false;
if (acceptRequestOffer != null && showAcknowledgement) {
if (acceptRequestOffer != null) {
statusForReqAccept = await acceptRequestOffer(); statusForReqAccept = await acceptRequestOffer();
if (statusForReqAccept) { if (statusForReqAccept) {
bool status = await requestVM.onActionRequestTapped( bool status = await requestVM.onActionRequestTapped(
@ -79,7 +84,7 @@ void dealCompletedConsentBottomSheet({required BuildContext mainContext, require
context: mainContext, context: mainContext,
requestStatusEnum: requestStatusEnum, requestStatusEnum: requestStatusEnum,
requestId: requestId, requestId: requestId,
needLoading: false, needLoading: showAcknowledgement ? true : false,
); );
log("status: $status"); log("status: $status");
if (status) { if (status) {

@ -129,7 +129,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(), offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "", serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "", manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0, manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.rejected, requestOfferStatusEnum: RequestOfferStatusEnum.rejected,
context: context, context: context,
); );
@ -208,6 +208,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
mainContext: context, mainContext: context,
requestStatusEnum: RequestStatusEnum.completed, requestStatusEnum: RequestStatusEnum.completed,
requestId: requestVM.currentSelectedRequest!.id, requestId: requestVM.currentSelectedRequest!.id,
showAcknowledgement: AppState().currentAppType == AppType.customer,
); );
} else { } else {
final requestVM = context.read<RequestsVM>(); final requestVM = context.read<RequestsVM>();
@ -215,6 +216,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
mainContext: context, mainContext: context,
requestStatusEnum: RequestStatusEnum.completed, requestStatusEnum: RequestStatusEnum.completed,
requestId: requestVM.currentSelectedRequest!.id, requestId: requestVM.currentSelectedRequest!.id,
showAcknowledgement: AppState().currentAppType == AppType.customer,
acceptRequestOffer: () async { acceptRequestOffer: () async {
bool status = await chatVM.onSendMessageForActionOnRequestOffer( bool status = await chatVM.onSendMessageForActionOnRequestOffer(
receiverId: chatMessageModel.senderUserID ?? "", receiverId: chatMessageModel.senderUserID ?? "",
@ -226,7 +228,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(), offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "", serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "", manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0, manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.accepted, requestOfferStatusEnum: RequestOfferStatusEnum.accepted,
context: context, context: context,
); );
@ -373,7 +375,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(), offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "", serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "", manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0, manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: requestOfferStatusEnum, requestOfferStatusEnum: requestOfferStatusEnum,
context: context, context: context,
); );
@ -427,7 +429,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(), offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "", serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "", manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0, manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.accepted, requestOfferStatusEnum: RequestOfferStatusEnum.accepted,
context: context, context: context,
); );
@ -736,7 +738,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
ReqOffer offer = widget.chatMessageModel.reqOffer!; ReqOffer offer = widget.chatMessageModel.reqOffer!;
requestVM.updateOfferPrice((offer.price ?? "").toString()); requestVM.updateOfferPrice((offer.price ?? "").toString());
requestVM.updateServiceItem((offer.serviceItemName ?? "").toString()); requestVM.updateServiceItem((offer.serviceItemName ?? "").toString());
requestVM.updateItemManufacturer((offer.manufacturedById ?? "").toString()); requestVM.updateItemManufacturer((offer.manufacturedByName ?? "").toString());
requestVM.updateServiceItemCreatedOn((offer.manufacturedOn ?? "").toString()); requestVM.updateServiceItemCreatedOn((offer.manufacturedOn ?? "").toString());
requestVM.updateOfferDescription((widget.chatMessageModel.chatText ?? "").toString()); requestVM.updateOfferDescription((widget.chatMessageModel.chatText ?? "").toString());
requestVM.updateIsDeliveryAvailableStatus((offer.isDeliveryAvailable ?? false)); requestVM.updateIsDeliveryAvailableStatus((offer.isDeliveryAvailable ?? false));
@ -747,8 +749,6 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
id: element.id, id: element.id,
filePath: element.imageStr != null && element.imageStr!.isNotEmpty ? element.imageStr : element.imageUrl, filePath: element.imageStr != null && element.imageStr!.isNotEmpty ? element.imageStr : element.imageUrl,
isFromNetwork: element.imageStr != null && element.imageStr!.isNotEmpty ? false : true); isFromNetwork: element.imageStr != null && element.imageStr!.isNotEmpty ? false : true);
log("imageModelimageModel: ${imageModel.toString()}");
requestVM.addImageToPickedVehicleImages(imageModel); requestVM.addImageToPickedVehicleImages(imageModel);
} }
} }
@ -771,7 +771,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
] else if (AppState().currentAppType == AppType.provider && ] else if (AppState().currentAppType == AppType.provider &&
chatMessageTypeEnum == ChatMessageTypeEnum.offer && chatMessageTypeEnum == ChatMessageTypeEnum.offer &&
widget.chatMessageModel.reqOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.offer && widget.chatMessageModel.reqOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.offer &&
(widget.chatMessageModel.isMyMessage == true)) ...[ (widget.chatMessageModel.isMyMessage == true && widget.chatMessageModel.reqOffer != null && widget.chatMessageModel.reqOffer!.id != null)) ...[
MyAssets.icEdit.buildSvg(color: MyColors.white, height: 15).onPress(() => onOfferEditIconPressed()), MyAssets.icEdit.buildSvg(color: MyColors.white, height: 15).onPress(() => onOfferEditIconPressed()),
], ],
Expanded( Expanded(

@ -79,7 +79,9 @@ class AdsFragment extends StatelessWidget {
title: LocaleKeys.exploreAds.tr(), title: LocaleKeys.exploreAds.tr(),
txtColor: adVM.isExploreAdsTapped ? MyColors.white : MyColors.darkTextColor, txtColor: adVM.isExploreAdsTapped ? MyColors.white : MyColors.darkTextColor,
onPressed: () { onPressed: () {
print("accessToken: ${AppState().getUser.data!.accessToken}"); log("accessToken: ${AppState().getUser.data!.accessToken}");
log("AppState().getUser.data!.userInfo!.userId;: ${AppState().getUser.data!.userInfo!.userId}");
if (adVM.myAds.isEmpty) { if (adVM.myAds.isEmpty) {
adVM.getMyAds(); adVM.getMyAds();
} }
@ -107,7 +109,9 @@ class AdsFragment extends StatelessWidget {
16.height, 16.height,
FiltersList( FiltersList(
filterList: adVM.exploreAdsFilterOptions, filterList: adVM.exploreAdsFilterOptions,
onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum()), onFilterTapped: (index, selectedFilterId) {
adVM.applyFilterOnExploreAds(vehicleBrandId: selectedFilterId);
},
needLeftPadding: false, needLeftPadding: false,
).paddingOnly(left: 21), ).paddingOnly(left: 21),
] ]
@ -115,7 +119,9 @@ class AdsFragment extends StatelessWidget {
16.height, 16.height,
FiltersList( FiltersList(
filterList: adVM.myAdsFilterOptions, filterList: adVM.myAdsFilterOptions,
onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnMyAds(adPostStatusEnum: selectedFilterId.toAdPostEnum()), onFilterTapped: (index, selectedFilterId) {
adVM.applyFilterOnMyAds(adPostStatusEnum: selectedFilterId.toAdPostEnum());
},
needLeftPadding: false, needLeftPadding: false,
).paddingOnly(left: 21), ).paddingOnly(left: 21),
], ],
@ -128,8 +134,8 @@ class AdsFragment extends StatelessWidget {
child: RefreshIndicator( child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
if (adVM.isExploreAdsTapped) { if (adVM.isExploreAdsTapped) {
CreatedByRoleEnum createdByRoleEnum = adVM.exploreAdsFilterOptions.firstWhere((element) => element.isSelected).id.toCreatedByRoleEnum(); int vehicleBrandId = adVM.exploreAdsFilterOptions.firstWhere((element) => element.isSelected).id;
adVM.applyFilterOnExploreAds(createdByRoleFilter: createdByRoleEnum); adVM.applyFilterOnExploreAds(vehicleBrandId: vehicleBrandId);
} else { } else {
AdPostStatus adPostStatusEnum = adVM.myAdsFilterOptions.firstWhere((element) => element.isSelected).id.toAdPostEnum(); AdPostStatus adPostStatusEnum = adVM.myAdsFilterOptions.firstWhere((element) => element.isSelected).id.toAdPostEnum();
adVM.applyFilterOnMyAds(adPostStatusEnum: adPostStatusEnum); adVM.applyFilterOnMyAds(adPostStatusEnum: adPostStatusEnum);
@ -141,12 +147,26 @@ class AdsFragment extends StatelessWidget {
isAdsFragment: true, isAdsFragment: true,
shouldShowAdStatus: !adVM.isExploreAdsTapped, shouldShowAdStatus: !adVM.isExploreAdsTapped,
adsList: getAdsList(adVM), adsList: getAdsList(adVM),
onFetchMoreAds: () { hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds,
log("fetch more ads"); onFetchMoreAds: () async {
AdPostStatus adPostStatusEnum = adVM.myAdsFilterOptions.firstWhere((element) => element.isSelected).id.toAdPostEnum();
if (adVM.isExploreAdsTapped) {
await adVM.fetchMoreExploreAds();
} else {
await adVM.fetchMoreMyAds(adsStatus: adPostStatusEnum);
}
}, },
), ),
), ),
) ),
if (adVM.isLoadingMore) ...[
const Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
))
]
], ],
), ),
), ),

@ -158,7 +158,7 @@ class MyRequestsFragment extends StatelessWidget {
}, },
child: RequestItem( child: RequestItem(
request: requestsVM.myFilteredRequests[index], request: requestsVM.myFilteredRequests[index],
shouldShowStatuses: AppState().currentAppType == AppType.customer, shouldShowStatuses: true,
onTap: () async { onTap: () async {
RequestModel request = requestsVM.myFilteredRequests[index]; RequestModel request = requestsVM.myFilteredRequests[index];
requestsVM.updateCurrentSelectedRequest(request); requestsVM.updateCurrentSelectedRequest(request);

@ -56,7 +56,6 @@ Future buildSendOfferBottomSheet({
numbersOnly: true, numbersOnly: true,
onChanged: (v) => requestsVM.updateOfferPrice(v), onChanged: (v) => requestsVM.updateOfferPrice(v),
), ),
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) ...[
12.height, 12.height,
TxtField( TxtField(
value: requestsVM.serviceItem, value: requestsVM.serviceItem,
@ -64,6 +63,7 @@ Future buildSendOfferBottomSheet({
hint: LocaleKeys.serviceItem.tr(), hint: LocaleKeys.serviceItem.tr(),
onChanged: (v) => requestsVM.updateServiceItem(v), onChanged: (v) => requestsVM.updateServiceItem(v),
), ),
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) ...[
12.height, 12.height,
TxtField( TxtField(
value: requestsVM.itemManufacturer, value: requestsVM.itemManufacturer,
@ -157,8 +157,7 @@ Future buildSendOfferBottomSheet({
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus, isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
requestIndex: requestDetailPageArguments.requestIndex, requestIndex: requestDetailPageArguments.requestIndex,
isFromChatScreen: isFromChatScreen, isFromChatScreen: isFromChatScreen,
manufacturedById: 1, manufacturedByName: requestsVM.itemManufacturer,
// Todo: It should be the ID of the manufacturer
manufacturedOn: requestsVM.serviceItemCreatedOn, manufacturedOn: requestsVM.serviceItemCreatedOn,
serviceItemName: requestsVM.serviceItem, serviceItemName: requestsVM.serviceItem,
); );
@ -170,8 +169,7 @@ Future buildSendOfferBottomSheet({
offerPrice: requestsVM.offerPrice, offerPrice: requestsVM.offerPrice,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus, isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
serviceItemName: requestsVM.serviceItem, serviceItemName: requestsVM.serviceItem,
manufacturedById: 1, manufacturedByName: requestsVM.itemManufacturer,
// Todo: It should be the ID of the manufacturer
manufacturedOn: requestsVM.serviceItemCreatedOn, manufacturedOn: requestsVM.serviceItemCreatedOn,
receiverId: requestDetail.customerId, receiverId: requestDetail.customerId,
customerRequestIndex: requestIndex, customerRequestIndex: requestIndex,

@ -29,6 +29,7 @@ class RequestDetailPage extends StatelessWidget {
required int requestId, required int requestId,
required RequestStatusEnum requestStatus, required RequestStatusEnum requestStatus,
required RequestsTypeEnum requestTypeEnum, required RequestsTypeEnum requestTypeEnum,
required ShippingRequestStatusEnum shippingRequestStatusEnum,
required String statusText, required String statusText,
required BuildContext context, required BuildContext context,
}) { }) {
@ -47,6 +48,7 @@ class RequestDetailPage extends StatelessWidget {
if (requestTypeEnum == RequestsTypeEnum.serviceRequest) { if (requestTypeEnum == RequestsTypeEnum.serviceRequest) {
return Utils.buildStatusContainer(LocaleKeys.awaitingPaymentFromCustomer.tr()); return Utils.buildStatusContainer(LocaleKeys.awaitingPaymentFromCustomer.tr());
} else { } else {
return Utils.buildStatusContainer(LocaleKeys.awaitingResponseFromCustomer.tr()); return Utils.buildStatusContainer(LocaleKeys.awaitingResponseFromCustomer.tr());
} }
@ -68,7 +70,28 @@ class RequestDetailPage extends StatelessWidget {
case RequestStatusEnum.shipping: case RequestStatusEnum.shipping:
case RequestStatusEnum.delivery: case RequestStatusEnum.delivery:
if (AppState().currentAppType == AppType.provider) { if (AppState().currentAppType == AppType.provider && shippingRequestStatusEnum == ShippingRequestStatusEnum.delivered) {
return Column(
children: [
Utils.buildStatusContainer("${LocaleKeys.deliveryStatus.tr()} ${Utils.getNameByShippingRequestStatusEnum(shippingRequestStatusEnum).capitalizeFirstLetter()}")
.paddingOnly(left: 8, right: 8),
ShowFillButton(
maxWidth: double.infinity,
margin: const EdgeInsets.all(15),
maxHeight: 55,
title: LocaleKeys.markAsCompleted.tr(),
onPressed: () {
return dealCompletedConsentBottomSheet(
mainContext: context,
requestStatusEnum: RequestStatusEnum.completed,
requestId: requestId,
showAcknowledgement: AppState().currentAppType == AppType.customer,
);
},
)
],
);
} else if (AppState().currentAppType == AppType.provider) {
return Utils.buildStatusContainer(LocaleKeys.shippingManagementInstruction.tr()); return Utils.buildStatusContainer(LocaleKeys.shippingManagementInstruction.tr());
} else { } else {
return ShowFillButton( return ShowFillButton(
@ -81,7 +104,7 @@ class RequestDetailPage extends StatelessWidget {
mainContext: context, mainContext: context,
requestStatusEnum: RequestStatusEnum.completed, requestStatusEnum: RequestStatusEnum.completed,
requestId: requestId, requestId: requestId,
acceptRequestOffer: () {}, showAcknowledgement: AppState().currentAppType == AppType.customer,
); );
}, },
); );
@ -176,8 +199,9 @@ class RequestDetailPage extends StatelessWidget {
requestId: requestDetailPageArguments.requestModel.id, requestId: requestDetailPageArguments.requestModel.id,
requestStatus: requestDetailPageArguments.requestModel.requestStatus, requestStatus: requestDetailPageArguments.requestModel.requestStatus,
statusText: "Offer ${requestDetailPageArguments.requestModel.requestStatusName}", statusText: "Offer ${requestDetailPageArguments.requestModel.requestStatusName}",
context: context,
requestTypeEnum: requestDetailPageArguments.requestModel.requestType.toRequestTypeEnum(), requestTypeEnum: requestDetailPageArguments.requestModel.requestType.toRequestTypeEnum(),
shippingRequestStatusEnum: requestDetailPageArguments.requestModel.shippingStatusEnum ?? ShippingRequestStatusEnum.pending,
context: context,
), ),
], ],
], ],

@ -153,15 +153,16 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
SingleDetailWidget(text: requestVM.currentSelectedRequest!.vehicleTypeName, type: LocaleKeys.vehicleType.tr()), SingleDetailWidget(text: requestVM.currentSelectedRequest!.vehicleTypeName, type: LocaleKeys.vehicleType.tr()),
16.height, 16.height,
SingleDetailWidget(text: '${requestVM.currentSelectedRequest!.model} ${requestVM.currentSelectedRequest!.year}', type: LocaleKeys.model.tr()), SingleDetailWidget(text: '${requestVM.currentSelectedRequest!.model} ${requestVM.currentSelectedRequest!.year}', type: LocaleKeys.model.tr()),
if (requestVM.acceptedRequestOffer!.manufacturedById != null) ...[ if (requestVM.acceptedRequestOffer!.manufacturedByName != null) ...[
16.height, 16.height,
SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedById ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()), SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedByName ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()),
], ],
// 16.height, // 16.height,
// SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()), // SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()),
16.height, 16.height,
SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()), SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()),
16.height, 16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
], ],
), ),
), ),
@ -186,12 +187,14 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
16.height, 16.height,
SingleDetailWidget(text: requestCreatedOn, type: LocaleKeys.requestCreatedOn.tr()), SingleDetailWidget(text: requestCreatedOn, type: LocaleKeys.requestCreatedOn.tr()),
], ],
16.height,
SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()),
], ],
), ),
), ),
], ],
), ),
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
], ],
); );
} }

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/app_state.dart';
@ -63,20 +64,6 @@ class _ProviderAcceptedRequestsViewState extends State<ProviderAcceptedRequestsV
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
LocaleKeys.noRequeststoShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor), LocaleKeys.noRequeststoShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor),
if (requestsVM.requestsFiltersCounter > 0) ...[
8.height,
InkWell(
onTap: () async {
requestsVM.clearRequestsFilters();
await requestsVM.getRequestsBasedOnFilters();
},
child: LocaleKeys.clearFilters.tr().toText(
fontSize: 14,
isBold: true,
color: MyColors.darkPrimaryColor,
),
),
],
], ],
) )
: ListView.separated( : ListView.separated(
@ -84,7 +71,7 @@ class _ProviderAcceptedRequestsViewState extends State<ProviderAcceptedRequestsV
return RequestItem( return RequestItem(
request: requestsVM.providersAcceptedRequestsList[index], request: requestsVM.providersAcceptedRequestsList[index],
onTap: () async { onTap: () async {
RequestModel request = requestsVM.myFilteredRequests[index]; RequestModel request = requestsVM.providersAcceptedRequestsList[index];
requestsVM.updateCurrentSelectedRequest(request); requestsVM.updateCurrentSelectedRequest(request);
if (request.requestStatus == RequestStatusEnum.pending || if (request.requestStatus == RequestStatusEnum.pending ||
request.requestStatus == RequestStatusEnum.cancelled || request.requestStatus == RequestStatusEnum.cancelled ||

@ -1,15 +1,51 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/utils/utils.dart';
import 'package:flutter/material.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:provider/provider.dart';
class SplashPage extends StatelessWidget { class SplashPage extends StatefulWidget {
const SplashPage({Key? key}) : super(key: key); const SplashPage({super.key});
@override @override
Widget build(BuildContext context) { SplashPageState createState() => SplashPageState();
}
class SplashPageState extends State<SplashPage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
performTimer(context); performTimer(context);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
final chatVM = context.read<ChatVM>();
chatVM.buildHubConnection(context);
}
}
// Timer function to navigate after a delay
performTimer(BuildContext context) {
Utils.delay(3).whenComplete(() {
navigateReplaceWithName(context, AppRoutes.registerSelection);
});
}
@override
Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Container( body: Container(
width: double.infinity, width: double.infinity,
@ -17,37 +53,36 @@ class SplashPage extends StatelessWidget {
color: Colors.black, color: Colors.black,
child: Column( child: Column(
children: [ children: [
Utils. mExp(1), // Spacer widget for flexible spacing
Utils.mExp(1),
// Logo Image
Expanded( Expanded(
child: Image.asset( child: Image.asset(
MyAssets.icLogoWhitePng, MyAssets.icLogoWhitePng,
), ),
), ),
// Car Image (flex value adjusted to make it more responsive)
Expanded( Expanded(
flex: 10, flex: 10,
child: Image.asset( child: Image.asset(
MyAssets.bnCar, MyAssets.bnCar,
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity, width: double.infinity,
height: 00, height: double.infinity, // Use full height in this expanded section
), ),
), ),
// Engine Image
Expanded( Expanded(
flex: 3, flex: 3,
child: Image.asset( child: Image.asset(
MyAssets.icEnginePng, MyAssets.icEnginePng,
), ),
), ),
// Spacer widget again for spacing
Utils.mExp(1), Utils.mExp(1),
], ],
), ),
), ),
); );
} }
performTimer(BuildContext context) {
Utils.delay(3).whenComplete(() {
navigateReplaceWithName(context, AppRoutes.registerSelection);
});
}
} }

@ -46,7 +46,6 @@ class _CompleteProfilePageState extends State<CompleteProfilePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) { return Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) {
print("Country ID = " + AppState().getUserRegisterCountrySelection.id.toString());
userVM.getAllCitiesForUser(AppState().getUserRegisterCountrySelection.id); userVM.getAllCitiesForUser(AppState().getUserRegisterCountrySelection.id);
return Scaffold( return Scaffold(
appBar: CustomAppBar( appBar: CustomAppBar(

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
void showMyBottomSheet(BuildContext context, {bool isDismissible = true, required Widget child, VoidCallback? callBackFunc}) { void showMyBottomSheet(BuildContext context, {bool isDismissible = true,bool isScrollControlled = true, required Widget child, VoidCallback? callBackFunc}) {
showModalBottomSheet<String>( showModalBottomSheet<String>(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,

@ -2,20 +2,21 @@ import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; 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/models/general_models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
class FiltersList extends StatelessWidget { class FiltersList extends StatelessWidget {
final List<FilterListModel> filterList; final List<FilterListModel> filterList;
final Function(int, int) onFilterTapped; final Function(int, int) onFilterTapped;
final bool needLeftPadding; final bool needLeftPadding;
EdgeInsets? padding; final EdgeInsets? padding;
FiltersList({ const FiltersList({
Key? key, super.key,
this.padding, this.padding,
required this.filterList, required this.filterList,
this.needLeftPadding = true, this.needLeftPadding = true,
required this.onFilterTapped, required this.onFilterTapped,
}) : super(key: key); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -31,30 +32,42 @@ class FiltersList extends StatelessWidget {
onTap: () { onTap: () {
onFilterTapped(index, filterList[index].id); onFilterTapped(index, filterList[index].id);
}, },
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 80), // Set a minimum width for each filter chip
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
margin: const EdgeInsets.symmetric(horizontal: 4), margin: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: filterList[index].isSelected color: filterList[index].isSelected ? MyColors.darkIconColor : null,
? MyColors.darkIconColor
: null,
border: Border.all( border: Border.all(
color: filterList[index].isSelected color: filterList[index].isSelected ? MyColors.darkIconColor : MyColors.primaryColor,
? MyColors.darkIconColor
: MyColors.primaryColor,
width: 2, width: 2,
), ),
), ),
child: filterList[index].title.toText( child: Row(
fontSize: 12, mainAxisSize: MainAxisSize.min,
children: [
// Icon before the text
// if (index != 0 || filterList[index].iconUrl.isNotEmpty) ...[
// filterList[index].iconUrl.buildNetworkImage(height: 16, width: 16, fit: BoxFit.cover),
// const SizedBox(width: 4), // Space between icon and text
// ],
// Text displayed in the chip
filterList[index].title.toText(
fontSize: 13,
letterSpacing: -0.14, letterSpacing: -0.14,
color: color: filterList[index].isSelected ? MyColors.white : null,
filterList[index].isSelected ? MyColors.white : null, ),
],
),
), ),
), ),
); );
}), },
),
); );
} }
} }

@ -9,16 +9,20 @@ class SearchEntityWidget extends StatelessWidget {
final String title; final String title;
final Widget actionWidget; final Widget actionWidget;
final List<DropValue> historyContent; final List<DropValue> historyContent;
final List<String>? historyContentString;
final Function(int) onHistoryItemDeleted; final Function(int) onHistoryItemDeleted;
final Function(DropValue) onHistoryItemTapped; final Function(DropValue) onHistoryItemTapped;
final bool isForString;
const SearchEntityWidget({ const SearchEntityWidget({
super.key, super.key,
required this.title, required this.title,
required this.actionWidget, required this.actionWidget,
required this.historyContent, required this.historyContent,
this.historyContentString,
required this.onHistoryItemDeleted, required this.onHistoryItemDeleted,
required this.onHistoryItemTapped, required this.onHistoryItemTapped,
this.isForString = false,
}); });
@override @override
@ -30,6 +34,24 @@ class SearchEntityWidget extends StatelessWidget {
8.height, 8.height,
actionWidget, actionWidget,
10.height, 10.height,
if (isForString && historyContentString != null && historyContentString!.isNotEmpty) ...[
SizedBox(
height: 33,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: historyContentString!.length,
itemBuilder: (BuildContext context, int index) {
return CustomRectangleChip(
text: historyContentString![index],
onHistoryItemDeleted: () {
onHistoryItemDeleted(index);
},
onHistoryItemTapped: () {},
).paddingOnly(right: 10);
}),
)
] else ...[
historyContent.isNotEmpty historyContent.isNotEmpty
? SizedBox( ? SizedBox(
height: 33, height: 33,
@ -50,6 +72,7 @@ class SearchEntityWidget extends StatelessWidget {
}), }),
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
]
], ],
); );
} }

@ -56,7 +56,7 @@ class MediaViewerScreenState extends State<MediaViewerScreen> {
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
child: (widget.images[index].isFromNetwork ?? false) child: (widget.images[index].isFromNetwork ?? false)
? widget.images[index].imageUrl.buildNetworkImage( ? widget.images[index].imageUrl.buildNetworkImage(
fit: BoxFit.cover, fit: BoxFit.contain,
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
) )

@ -39,7 +39,7 @@ class TxtField extends StatelessWidget {
bool allowOnlyOneDigit; bool allowOnlyOneDigit;
TxtField({ TxtField({
Key? key, super.key,
this.value, this.value,
this.lable, this.lable,
this.hint, this.hint,
@ -67,7 +67,7 @@ class TxtField extends StatelessWidget {
this.onPostFixPressed, this.onPostFixPressed,
this.numbersOnly = false, this.numbersOnly = false,
this.allowOnlyOneDigit = false, this.allowOnlyOneDigit = false,
}) : super(key: key); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

Loading…
Cancel
Save