Minor Fixes

aamir_dev
Faiz Hashmi 1 year ago
parent e51df0651c
commit a1d7dcab13

@ -777,5 +777,12 @@
"requestCreatedOn": "تم إنشاء الطلب في",
"online": "عبر الإنترنت",
"deliveryStatus": "حالة توصيلك / الشحن هي:",
"markAsCompleted": "ضع علامة كمكتمل"
"markAsCompleted": "ضع علامة كمكتمل",
"searchByServiceDelivery": "البحث حسب خدمة التوصيل",
"searchByMobileNumber": "البحث بواسطة رقم الجوال",
"enterMobileNumber": "أدخل رقم الجوال",
"enterCustomerName": "أدخل اسم العميل",
"tapToView": "انقر لعرض",
"noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.",
"copySelectedItems": "نسخ العناصر المحددة"
}

@ -775,6 +775,12 @@
"onlyJPGandPNG": "Only JPG and PNG files are allowed",
"expiryDate": "Expiry Date",
"deliveryStatus": "Your Delivery / Shipping Status is:",
"markAsCompleted": "Mark as Completed"
"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"
}

@ -257,11 +257,10 @@ class GlobalConsts {
return appInvitationMessageEn;
}
// Attachment Values
static int maxFileCount = 7;
static int maxFileSizeInBytes = 2 * 1024 * 1024;
static int maxFileCount = 7;
static int maxFileSizeInBytes = 2 * 1024 * 1024;
}
class MyAssets {
@ -403,6 +402,4 @@ class SignalrConsts {
// General
static String sendMessageGeneral = "SendMessageGeneral";
static String receiveMessageGeneral = "ReceiveMessageGeneral";
}

@ -793,7 +793,14 @@ class CodegenLoader extends AssetLoader{
"requestCreatedOn": "تم إنشاء الطلب في",
"online": "عبر الإنترنت",
"deliveryStatus": "حالة توصيلك / الشحن هي:",
"markAsCompleted": "ضع علامة كمكتمل"
"markAsCompleted": "ضع علامة كمكتمل",
"searchByServiceDelivery": "البحث حسب خدمة التوصيل",
"searchByMobileNumber": "البحث بواسطة رقم الجوال",
"enterMobileNumber": "أدخل رقم الجوال",
"enterCustomerName": "أدخل اسم العميل",
"tapToView": "انقر لعرض",
"noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.",
"copySelectedItems": "نسخ العناصر المحددة"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1572,7 +1579,14 @@ static const Map<String,dynamic> en_US = {
"onlyJPGandPNG": "Only JPG and PNG files are allowed",
"expiryDate": "Expiry Date",
"deliveryStatus": "Your Delivery / Shipping Status is:",
"markAsCompleted": "Mark as Completed"
"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"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -757,5 +757,12 @@ abstract class LocaleKeys {
static const online = 'online';
static const deliveryStatus = 'deliveryStatus';
static const markAsCompleted = 'markAsCompleted';
static const searchByServiceDelivery = 'searchByServiceDelivery';
static const searchByMobileNumber = 'searchByMobileNumber';
static const enterMobileNumber = 'enterMobileNumber';
static const enterCustomerName = 'enterCustomerName';
static const tapToView = 'tapToView';
static const noServicesAvailableToCopy = 'noServicesAvailableToCopy';
static const copySelectedItems = 'copySelectedItems';
}

@ -80,7 +80,7 @@ class ReqOffer {
String? offerStatusText;
String? comment;
String? serviceItemName;
int? manufacturedById;
String? manufacturedByName;
String? manufacturedOn;
double? price;
bool? isDeliveryAvailable;
@ -96,7 +96,7 @@ class ReqOffer {
this.offerStatusText,
this.comment,
this.serviceItemName,
this.manufacturedById,
this.manufacturedByName,
this.manufacturedOn,
this.price,
this.isDeliveryAvailable,
@ -113,7 +113,7 @@ class ReqOffer {
offerStatusText = json['offerStatusText'];
comment = json['comment'];
serviceItemName = json['serviceItem'];
manufacturedById = json['offeredItemCreatedBy'];
manufacturedByName = json['offeredItemCreatedBy'].toString();
manufacturedOn = json['offeredItemCreatedOn'];
price = json['price'];
isDeliveryAvailable = json['isDeliveryAvailable'];
@ -138,7 +138,7 @@ class ReqOffer {
@override
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}';
}
}

@ -21,7 +21,7 @@ import 'package:mc_common_app/utils/utils.dart';
abstract class AdsRepo {
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});
@ -89,14 +89,34 @@ class AdsRepoImp implements AdsRepo {
}
@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 = {
"SpecialServiceType": specialServiceType.toString(),
"CountryID": countryId.toString(),
};
GenericRespModel adsGenericModel =
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]));
return vehicleAdsDuration;
List<SpecialServiceModel> list = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index]));
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

@ -15,7 +15,15 @@ import 'package:mc_common_app/utils/enums.dart';
abstract class AppointmentRepo {
Future<List<AppointmentListModel>> getMyAppointmentsForProvider(Map<String, dynamic> map);
Future<List<AppointmentListModel>> getMyProviderAppointmentsByFilters({required int serviceProviderID});
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({
List<String>? providerIdsList,
@ -29,7 +37,7 @@ abstract class AppointmentRepo {
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);
@ -222,14 +230,33 @@ class AppointmentRepoImp implements AppointmentRepo {
}
@override
Future<List<AppointmentListModel>> getMyProviderAppointmentsByFilters({required int serviceProviderID}) async {
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 ?? "",
};
final map = {"ServiceProviderID": "$serviceProviderID"};
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
token: t,
(json) => GenericRespModel.fromJson(json),
queryParameters: map,
queryParameters: params,
ApiConsts.serviceProvidersAppointmentGet,
);
List<AppointmentListModel> appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
@ -263,8 +290,9 @@ class AppointmentRepoImp implements AppointmentRepo {
}
@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 ?? "";
final map = {"ProviderBranchID": branchID.toString(), "FromDate": fromDate, "ToDate": toDate};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),

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

@ -17,6 +17,7 @@ class AppEnums {
static const int appointmentsFilterEnumId = 13; // 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 serviceDeliveryTypeEnumId = 24; // to get the serviceDeliveryType
static const int shippingStatusEnumId = 30; // to get the Shipping Filter Enums
}

@ -378,8 +378,8 @@ class AdVM extends BaseVM {
notifyListeners();
}
Future<void> getVehicleAdsSpecialServices() async {
vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: 1);
Future<void> getVehicleAdsSpecialServices({required int cityId, required int countryId, required int specialServiceType}) async {
vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: specialServiceType, countryId: countryId, cityId: cityId);
notifyListeners();
}
@ -1188,9 +1188,7 @@ class AdVM extends BaseVM {
getVehicleAdsDuration();
}
if (vehicleAdsSpecialServices.isEmpty) {
getVehicleAdsSpecialServices();
}
getVehicleAdsSpecialServices(countryId: vehicleCountryId.selectedId, cityId: vehicleCityId.selectedId, specialServiceType: 1);
notifyListeners();
}

@ -55,20 +55,17 @@ class AppointmentsVM extends BaseVM {
bool isUpcomingEnabled = true;
bool isFetchingLists = false;
int selectedBranch = 0;
int selectedAppointmentIndex = 0;
int selectedAppointmentSubIndex = 0;
int selectedAppointmentId = 0;
int selectedBranchIdForAppointments = 0;
List<AppointmentListModel> myAppointments = [];
List<AppointmentListModel> myUpComingAppointments = [];
List<AppointmentListModel> myFilteredAppointments = [];
List<FilterListModel> appointmentsFilterOptions = [];
List<CustomerData> customersAppointments = [];
List<AppointmentListModel> myFilteredAppointments2 = [];
// List<ScheduleData> availableSchedules = [];
bool isFetchingServices = false;
List<DropValue> branchCategories = [];
@ -234,7 +231,6 @@ class AppointmentsVM extends BaseVM {
Utils.showToast(genericRespModel.message.toString());
await getMyAppointmentsForCustomer();
Utils.hideLoading(context);
getMyAppointmentsForCustomer();
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
} catch (e) {
@ -374,7 +370,7 @@ class AppointmentsVM extends BaseVM {
// appointmentStatusEnum.getIdFromAppointmentStatusEnum()]
// .isSelected = true;
if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) {
if (appointmentStatusEnum == AppointmentStatusEnum.allAppointments) {
myFilteredAppointments = myAppointments;
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners();
@ -459,10 +455,10 @@ class AppointmentsVM extends BaseVM {
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);
try {
GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(map);
GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(branchID: branchID, fromDate: selectedDateForAppointments, toDate: selectedDateForAppointments);
if (genericRespModel.messageStatus == 1) {
appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
} 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);
myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map);
myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(branchID: branchID);
myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments
.where((element) =>
@ -1272,6 +1268,21 @@ class AppointmentsVM extends BaseVM {
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
double branchFilterByRating = 4.0;
@ -1285,6 +1296,7 @@ class AppointmentsVM extends BaseVM {
List<DropValue> providersDropList = [];
List<DropValue> servicesDropList = [];
List<DropValue> itemsDropList = [];
List<DropValue> serviceDeliveryTypesDropList = [];
Future<void> fetchAllProviders() async {
if (providersDropList.isNotEmpty) return;
@ -1351,6 +1363,25 @@ class AppointmentsVM extends BaseVM {
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 {
await fetchAllProviders();
await fetchAllCategories();
@ -1440,7 +1471,6 @@ class AppointmentsVM extends BaseVM {
branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", ""));
}
setState(ViewState.idle);
log("branchesDropList: ${branchesDropList.length}");
}
@ -1449,6 +1479,7 @@ class AppointmentsVM extends BaseVM {
await fetchAllCategories();
await fetchAllServices();
await fetchAllItems();
await fetchAllServiceDeliveryTypes();
}
int appointmentFiltersCounter = 0;
@ -1661,15 +1692,132 @@ class AppointmentsVM extends BaseVM {
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() {
appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedItemId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedServiceDeliveryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
}
void clearAppointmentFilters() {
appointmentFilterServiceDeliverySearchHistory.clear();
appointmentFilterCustomerNameSearchHistory.clear();
appointmentFilterMobilePhoneSearchHistory.clear();
appointmentFilterItemsSearchHistory.clear();
appointmentFilterServicesSearchHistory.clear();
appointmentFilterCategorySearchHistory.clear();
@ -1677,11 +1825,16 @@ class AppointmentsVM extends BaseVM {
appointmentFilterBranchSearchHistory.clear();
appointmentFiltersCounter = 0;
clearAppointmentFilterSelections();
getMyAppointmentsForCustomer();
if (AppState().currentAppType == AppType.provider) {
getMyAppointmentsForProvider(branchID: selectedBranchIdForAppointments);
} else {
getMyAppointmentsForCustomer();
}
notifyListeners();
}
Future<void> getAppointmentsBasedOnFilters() async {
Future<void> getAppointmentsBasedOnFiltersForCustomer() async {
setState(ViewState.busy);
List<String> providersIdsList = [];
if (appointmentFilterProviderSearchHistory.isNotEmpty) {
@ -1725,6 +1878,56 @@ class AppointmentsVM extends BaseVM {
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 {
Utils.showLoading(context);
try {

@ -97,8 +97,8 @@ class ChatVM extends BaseVM {
notifyListeners();
}
List<int> indexesForCancelSpecialCarOffer = [0, 1, 5, 6, 10];
List<int> indexesForCancelSparePartOffer = [2, 5, 6, 10];
List<int> indexesForCancelSpecialCarOffer = [0, 1, 6, 10];
List<int> indexesForCancelSparePartOffer = [2, 10];
List<int> indexesForRejectOffer = [3, 4, 10];
List<int> indexesForDealNotCompleted = [7, 4, 8, 9, 10];
@ -363,7 +363,7 @@ class ChatVM extends BaseVM {
required String offerPrice,
required bool isDeliveryAvailable,
required String serviceItemName,
required int manufacturedById,
required String manufacturedByName,
required String manufacturedOn,
required List<dynamic> offerImages,
required BuildContext context,
@ -387,7 +387,7 @@ class ChatVM extends BaseVM {
"IsDeliveryAvailable": isDeliveryAvailable,
"ServiceItem": serviceItemName,
"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
"ServiceProviderID": providerId,
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
@ -652,7 +652,7 @@ class ChatVM extends BaseVM {
required int requestOfferID,
required String offerPrice,
required String serviceItemName,
required int manufacturedById,
required String manufacturedByName,
required String manufacturedOn,
required RequestOfferStatusEnum requestOfferStatusEnum,
required BuildContext context,
@ -674,8 +674,8 @@ class ChatVM extends BaseVM {
"RequestID": requestId,
"Price": double.parse(offerPrice),
"ServiceItem": serviceItemName,
"OfferedItemCreatedBy": manufacturedById, // TODO: The ID should be used from the manufacturer database
// "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime
"OfferedItemCreatedBy": manufacturedByName,
// "OfferedItemCreatedOn": manufacturedOn,
"ServiceProviderID": serviceProviderID,
"OfferStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum(),
"Comment": comments,

@ -83,7 +83,7 @@ class DashboardVMProvider extends BaseVM {
shippingManagementVM.populateShippingRequestFilterList();
await serviceVM.getBranchAndServices();
await serviceVM.populateBranchServiceFilters();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0"});
await appointmentVM.getMyAppointmentsForProvider(branchID: appointmentVM.selectedBranchIdForAppointments);
adVM.populateAdsFilterList();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
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});
List<RequestModel> myRequests = [];
List<RequestModel> myFilteredRequests = [];
List<FilterListModel> requestsTypeFilterOptions = [];
@ -125,7 +124,6 @@ class RequestsVM extends BaseVM {
// }
Future<bool> getRequestsBasedOnFilters() async {
myFilteredRequests.clear();
setState(ViewState.busy);
int requestTypeIdApi = requestsTypeFilterOptions.firstWhere((element) => element.isSelected).id;
@ -218,7 +216,7 @@ class RequestsVM extends BaseVM {
}
overwriteChatMessagesInRequestsModel({required List<ChatMessageModel> messages, required int index, required BuildContext context}) {
myFilteredRequests[index].chatMessages.clear();
if (myFilteredRequests.isEmpty) return;
myFilteredRequests[index].chatMessages = messages;
if (myFilteredRequests[index].chatMessages.isNotEmpty) {
for (var message in myFilteredRequests[index].chatMessages) {
@ -278,8 +276,6 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
bool isFetchingRequestType = false;
bool isFetchingVehicleType = true;
bool isFetchingVehicleDetail = false;
@ -946,7 +942,7 @@ class RequestsVM extends BaseVM {
return genericRespModel.messageStatus == 1;
} catch (e) {
logger.i(e.toString());
// Utils.showToast(e.toString());
Utils.showToast(e.toString());
if (needLoading) {
Utils.hideLoading(context);
}
@ -965,7 +961,7 @@ class RequestsVM extends BaseVM {
offerPriceError = "";
}
if (offerDescription.isEmpty) {
if (offerDescription.isEmpty || offerDescription.length < 5) {
offerDescriptionError = GlobalConsts.descriptionError;
isValidated = false;
notifyListeners();
@ -1054,7 +1050,7 @@ class RequestsVM extends BaseVM {
required String offerPrice,
required bool isDeliveryAvailable,
required String serviceItemName,
required int manufacturedById,
required String manufacturedByName,
required String manufacturedOn,
required int receiverId,
required int customerRequestIndex,
@ -1076,7 +1072,7 @@ class RequestsVM extends BaseVM {
offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable,
serviceItemName: serviceItemName,
manufacturedById: manufacturedById,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
requestImages: offerImages,
requestOfferStatusEnum: RequestOfferStatusEnum.offer,
@ -1114,7 +1110,7 @@ class RequestsVM extends BaseVM {
required int requestId,
required String offerPrice,
required String serviceItemName,
required int manufacturedById,
required String manufacturedByName,
required String manufacturedOn,
required RequestModel requestModel,
required bool isDeliveryAvailable,
@ -1137,7 +1133,7 @@ class RequestsVM extends BaseVM {
requestId: requestId,
offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable,
manufacturedById: manufacturedById,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
offerImages: offerImages,
@ -1171,7 +1167,7 @@ class RequestsVM extends BaseVM {
requestID: requestModel.id,
price: double.parse(offerPrice),
isDeliveryAvailable: isDeliveryAvailable,
manufacturedById: manufacturedById,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
requestOfferStatusEnum: RequestOfferStatusEnum.offer,

@ -646,6 +646,7 @@ class ServiceVM extends BaseVM {
}
List<ServiceModel>? matchedServices;
bool isAllSelected = false;
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
? const Center(child: CircularProgressIndicator())
: 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: (context) {
List<DropValue> vehicleCitiesDrop = [];

@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:developer';
import 'package:easy_localization/easy_localization.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/extensions/int_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/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
@ -33,6 +36,7 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
void initState() {
appointmentsVM = context.read<AppointmentsVM>();
scheduleMicrotask(() async {
log('herre called');
await appointmentsVM.populateDataForAppointmentsFilter();
});
super.initState();
@ -44,6 +48,21 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
super.dispose();
}
// Provider filters
// * Service
// * Customer name
// * Mobile number
// * Type of service Delivery
// Customer filters
// * Provider
// * Branch
// * Category
// * Service
// * Item
@override
Widget build(BuildContext context) {
return Scaffold(
@ -59,96 +78,154 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
),
body: Consumer<AppointmentsVM>(
builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
return WillPopScope(
onWillPop: () async {
context.read<AdVM>().resetValues();
return true;
return PopScope(
onPopInvokedWithResult: (bool result, dynamic) {
if (result) {
context.read<AdVM>().resetValues();
}
},
child: Column(
children: [
ListView(
children: [
20.height,
SearchEntityWidget(
title: LocaleKeys.searchByProvider.tr(),
actionWidget: Builder(
builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.providersDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedProviderId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedProviderId.selectedId, appointmentsVM.appointmentFilterSelectedProviderId.selectedOption, "")
: null,
hint: LocaleKeys.selectProvider.tr(),
);
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
),
historyContent: appointmentsVM.appointmentFilterProviderSearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterProviderSearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) =>
appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
),
if (appointmentsVM.state == ViewState.busy) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 5.h,
width: 5.h,
child: const CircularProgressIndicator(),
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
),
],
if (appointmentsVM.appointmentFilterProviderSearchHistory.isNotEmpty) ...[
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
] else ...[
SearchEntityWidget(
title: LocaleKeys.searchByBranch.tr(),
title: LocaleKeys.searchByProvider.tr(),
actionWidget: Builder(
builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.branchesDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedBranchId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedBranchId.selectedId, appointmentsVM.appointmentFilterSelectedBranchId.selectedOption, "")
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.providersDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedProviderId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedProviderId.selectedId, appointmentsVM.appointmentFilterSelectedProviderId.selectedOption, "")
: null,
hint: LocaleKeys.selectBranch.tr(),
hint: LocaleKeys.selectProvider.tr(),
);
},
),
historyContent: appointmentsVM.appointmentFilterBranchSearchHistory,
historyContent: appointmentsVM.appointmentFilterProviderSearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterBranchSearchHistory(index: index);
appointmentsVM.removeAppointmentFilterProviderSearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) =>
appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
),
],
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
SearchEntityWidget(
title: LocaleKeys.searchByCategory.tr(),
actionWidget: Builder(
builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.categoryDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedCategoryId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedCategoryId.selectedId, appointmentsVM.appointmentFilterSelectedCategoryId.selectedOption, "")
: null,
hint: LocaleKeys.selectCategory.tr(),
);
if (appointmentsVM.state == ViewState.busy) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 5.h,
width: 5.h,
child: const CircularProgressIndicator(),
),
],
),
],
if (appointmentsVM.appointmentFilterProviderSearchHistory.isNotEmpty) ...[
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
SearchEntityWidget(
title: LocaleKeys.searchByBranch.tr(),
actionWidget: Builder(
builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.branchesDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedBranchId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedBranchId.selectedId, appointmentsVM.appointmentFilterSelectedBranchId.selectedOption, "")
: null,
hint: LocaleKeys.selectBranch.tr(),
);
},
),
historyContent: appointmentsVM.appointmentFilterBranchSearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterBranchSearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) =>
appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
),
],
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
SearchEntityWidget(
title: LocaleKeys.searchByCategory.tr(),
actionWidget: Builder(
builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.categoryDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedCategoryId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedCategoryId.selectedId, appointmentsVM.appointmentFilterSelectedCategoryId.selectedOption, "")
: null,
hint: LocaleKeys.selectCategory.tr(),
);
},
),
historyContent: appointmentsVM.appointmentFilterCategorySearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterCategorySearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) =>
appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
),
historyContent: appointmentsVM.appointmentFilterCategorySearchHistory,
onHistoryItemDeleted: (index) {
appointmentsVM.removeAppointmentFilterCategorySearchHistory(index: index);
},
onHistoryItemTapped: (DropValue value) =>
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(
title: LocaleKeys.searchByService.tr(),
actionWidget: Builder(builder: (context) {
@ -166,22 +243,41 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
onHistoryItemTapped: (DropValue value) => null,
),
const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5),
SearchEntityWidget(
title: LocaleKeys.searchByItem.tr(),
actionWidget: Builder(builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedItemId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.itemsDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedItemId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedItemId.selectedId, appointmentsVM.appointmentFilterSelectedItemId.selectedOption, "")
: null,
hint: LocaleKeys.selectItems.tr(),
);
}),
historyContent: appointmentsVM.appointmentFilterItemsSearchHistory,
onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterItemsSearchHistory(index: index),
onHistoryItemTapped: (DropValue value) => null,
),
if (AppState().currentAppType == AppType.customer) ...[
SearchEntityWidget(
title: LocaleKeys.searchByItem.tr(),
actionWidget: Builder(builder: (context) {
return DropdownField(
(DropValue value) => appointmentsVM.updateAppointmentFilterSelectedItemId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: appointmentsVM.itemsDropList,
dropdownValue: appointmentsVM.appointmentFilterSelectedItemId.selectedId != -1
? DropValue(appointmentsVM.appointmentFilterSelectedItemId.selectedId, appointmentsVM.appointmentFilterSelectedItemId.selectedOption, "")
: null,
hint: LocaleKeys.selectItems.tr(),
);
}),
historyContent: appointmentsVM.appointmentFilterItemsSearchHistory,
onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterItemsSearchHistory(index: index),
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(),
Container(
@ -197,7 +293,12 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
title: LocaleKeys.search.tr(),
onPressed: () {
Navigator.pop(context);
appointmentsVM.getAppointmentsBasedOnFilters();
if (AppState().currentAppType == AppType.provider) {
appointmentsVM.getAppointmentsBasedOnFiltersForProviders(branchID: appointmentsVM.selectedBranchIdForAppointments);
} else {
appointmentsVM.getAppointmentsBasedOnFiltersForCustomer();
}
},
backgroundColor: MyColors.darkPrimaryColor,
txtColor: MyColors.white,
@ -208,7 +309,9 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
),
8.height,
InkWell(
onTap: () => appointmentsVM.clearAppointmentFilters(),
onTap: () {
appointmentsVM.clearAppointmentFilters();
},
child: LocaleKeys.clearFilters.tr().toText(
fontSize: 14,
isBold: true,

@ -160,7 +160,9 @@ class _ChatViewState extends State<ChatView> {
if (AppState().currentAppType == AppType.customer && chatVM.serviceProviderOffersList.isNotEmpty) {
chatMessages = chatVM.serviceProviderOffersList[chatViewArgumentsForRequest!.providerIndex].chatMessages ?? [];
} else {
chatMessages = requestVM.myFilteredRequests[chatViewArgumentsForRequest!.requestIndex].chatMessages;
if (requestVM.myFilteredRequests.isNotEmpty) {
chatMessages = requestVM.myFilteredRequests[chatViewArgumentsForRequest!.requestIndex].chatMessages;
}
}
}
return Column(
@ -173,20 +175,20 @@ class _ChatViewState extends State<ChatView> {
child: chatMessages.isEmpty
? Center(child: LocaleKeys.noChatMessage.tr().toText(fontSize: 16, color: MyColors.lightTextColor, textAlign: TextAlign.center)).paddingAll(22)
: ListView.separated(
controller: chatVM.scrollController,
itemCount: chatMessages.length,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel,
requestModel: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel! : null,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
);
},
).horPaddingMain(),
controller: chatVM.scrollController,
itemCount: chatMessages.length,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel,
requestModel: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel! : null,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
);
},
).horPaddingMain(),
),
10.height,
Row(
@ -230,88 +232,90 @@ class _ChatViewState extends State<ChatView> {
// ),
// ]
//
else ...[
if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.local_offer_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() {
requestVM.resetSendOfferBottomSheet();
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: chatViewArgumentsForRequest!.requestIndex,
requestModel: chatViewArgumentsForRequest!.requestModel!,
);
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
},
else
...[
if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.local_offer_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() {
requestVM.resetSendOfferBottomSheet();
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: chatViewArgumentsForRequest!.requestIndex,
requestModel: chatViewArgumentsForRequest!.requestModel!,
);
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
},
),
),
),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
),
),
),
] else if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
] else
if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.photo_library_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(() => chatVM.pickMultipleImages()),
),
],
if (chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 8,
child: TxtField(
value: chatVM.chatMessageText,
hint: LocaleKeys.typeMessageHere.tr(),
keyboardType: TextInputType.text,
isNeedBorder: false,
onChanged: (v) => chatVM.updateChatMessageText(v),
),
),
],
Expanded(
flex: 1,
child: const Icon(
Icons.photo_library_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(() => chatVM.pickMultipleImages()),
),
],
if (chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 8,
child: TxtField(
value: chatVM.chatMessageText,
hint: LocaleKeys.typeMessageHere.tr(),
keyboardType: TextInputType.text,
isNeedBorder: false,
onChanged: (v) => chatVM.updateChatMessageText(v),
),
),
],
Expanded(
flex: 1,
child: const Icon(Icons.send_rounded, color: MyColors.darkPrimaryColor, size: 30).onPress(
() async {
ChatMessageTypeEnum chatMessageTypeEnum = ChatMessageTypeEnum.freeText;
child: const Icon(Icons.send_rounded, color: MyColors.darkPrimaryColor, size: 30).onPress(
() async {
ChatMessageTypeEnum chatMessageTypeEnum = ChatMessageTypeEnum.freeText;
if (chatVM.pickedImagesForMessage.isNotEmpty) {
chatMessageTypeEnum = ChatMessageTypeEnum.image;
}
final status = await onMessageSend(chatMessageType: chatMessageTypeEnum);
if (chatVM.pickedImagesForMessage.isNotEmpty) {
chatMessageTypeEnum = ChatMessageTypeEnum.image;
}
final status = await onMessageSend(chatMessageType: chatMessageTypeEnum);
if (status) {
chatVM.scrollChatDown();
if (chatMessageTypeEnum == ChatMessageTypeEnum.freeText) {
chatVM.clearChatMessageText();
} else if (chatMessageTypeEnum == ChatMessageTypeEnum.image) {
chatVM.clearPickedImagesForMessage();
if (status) {
chatVM.scrollChatDown();
if (chatMessageTypeEnum == ChatMessageTypeEnum.freeText) {
chatVM.clearChatMessageText();
} else if (chatMessageTypeEnum == ChatMessageTypeEnum.image) {
chatVM.clearPickedImagesForMessage();
}
}
}
},
},
),
),
),
],
],
],
).toContainer(isShadowEnabled: true)
],

@ -129,7 +129,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0,
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.rejected,
context: context,
);
@ -228,7 +228,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0,
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.accepted,
context: context,
);
@ -375,7 +375,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0,
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: requestOfferStatusEnum,
context: context,
);
@ -429,7 +429,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0,
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
requestOfferStatusEnum: RequestOfferStatusEnum.accepted,
context: context,
);
@ -738,7 +738,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
ReqOffer offer = widget.chatMessageModel.reqOffer!;
requestVM.updateOfferPrice((offer.price ?? "").toString());
requestVM.updateServiceItem((offer.serviceItemName ?? "").toString());
requestVM.updateItemManufacturer((offer.manufacturedById ?? "").toString());
requestVM.updateItemManufacturer((offer.manufacturedByName ?? "").toString());
requestVM.updateServiceItemCreatedOn((offer.manufacturedOn ?? "").toString());
requestVM.updateOfferDescription((widget.chatMessageModel.chatText ?? "").toString());
requestVM.updateIsDeliveryAvailableStatus((offer.isDeliveryAvailable ?? false));
@ -749,8 +749,6 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
id: element.id,
filePath: element.imageStr != null && element.imageStr!.isNotEmpty ? element.imageStr : element.imageUrl,
isFromNetwork: element.imageStr != null && element.imageStr!.isNotEmpty ? false : true);
log("imageModelimageModel: ${imageModel.toString()}");
requestVM.addImageToPickedVehicleImages(imageModel);
}
}

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

@ -48,6 +48,7 @@ class RequestDetailPage extends StatelessWidget {
if (requestTypeEnum == RequestsTypeEnum.serviceRequest) {
return Utils.buildStatusContainer(LocaleKeys.awaitingPaymentFromCustomer.tr());
} else {
return Utils.buildStatusContainer(LocaleKeys.awaitingResponseFromCustomer.tr());
}

@ -153,9 +153,9 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
SingleDetailWidget(text: requestVM.currentSelectedRequest!.vehicleTypeName, type: LocaleKeys.vehicleType.tr()),
16.height,
SingleDetailWidget(text: '${requestVM.currentSelectedRequest!.model} ${requestVM.currentSelectedRequest!.year}', type: LocaleKeys.model.tr()),
if (requestVM.acceptedRequestOffer!.manufacturedById != null) ...[
if (requestVM.acceptedRequestOffer!.manufacturedByName != null) ...[
16.height,
SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedById ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()),
SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedByName ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()),
],
// 16.height,
// SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()),

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/gestures.dart';
import 'package:mc_common_app/classes/app_state.dart';
@ -63,20 +64,6 @@ class _ProviderAcceptedRequestsViewState extends State<ProviderAcceptedRequestsV
mainAxisAlignment: MainAxisAlignment.center,
children: [
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(
@ -84,7 +71,7 @@ class _ProviderAcceptedRequestsViewState extends State<ProviderAcceptedRequestsV
return RequestItem(
request: requestsVM.providersAcceptedRequestsList[index],
onTap: () async {
RequestModel request = requestsVM.myFilteredRequests[index];
RequestModel request = requestsVM.providersAcceptedRequestsList[index];
requestsVM.updateCurrentSelectedRequest(request);
if (request.requestStatus == RequestStatusEnum.pending ||
request.requestStatus == RequestStatusEnum.cancelled ||

@ -1,7 +1,7 @@
import 'package:flutter/material.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>(
context: context,
isScrollControlled: true,

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

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

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

Loading…
Cancel
Save