Fixed issues in ads extension and appointment

master_new_changes
Faiz Hashmi 1 year ago
parent 5eb1a939dc
commit 56d6bc196b

@ -647,5 +647,12 @@
"callNow": "اتصل الآن",
"condition": "الحالة",
"servicesNotAvailableHomeLocation": "بعض الخدمات غير متوفرة في الموقع المنزلي.",
"additionalChargesNotice": "هذه الرسوم إضافية على رسوم الخدمة الفعلية. قد تختلف الرسوم للعناصر الثقيلة."
"additionalChargesNotice": "هذه الرسوم إضافية على رسوم الخدمة الفعلية. قد تختلف الرسوم للعناصر الثقيلة.",
"selectServiceLocation": "اختر موقع الخدمة",
"apptOn": "التعيين في",
"merged": "مُدمج",
"date": "التاريخ",
"selectAll": "اختر الكل",
"unselectAll": "إلغاء اختيار الكل",
"copySelectedServices": "نسخ الخدمات المحددة"
}

@ -648,5 +648,12 @@
"callNow": "Call Now",
"condition": "Condition",
"servicesNotAvailableHomeLocation": "Some services are not available on home location.",
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary."
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary.",
"selectServiceLocation": "Select Service Location",
"apptOn": "Appt On",
"merged": "Merged",
"date": "Date",
"selectAll": "Select All",
"unselectAll": "Unselect All",
"copySelectedServices": "Copy Selected Services"
}

@ -663,7 +663,14 @@ class CodegenLoader extends AssetLoader{
"callNow": "اتصل الآن",
"condition": "الحالة",
"servicesNotAvailableHomeLocation": "بعض الخدمات غير متوفرة في الموقع المنزلي.",
"additionalChargesNotice": "هذه الرسوم إضافية على رسوم الخدمة الفعلية. قد تختلف الرسوم للعناصر الثقيلة."
"additionalChargesNotice": "هذه الرسوم إضافية على رسوم الخدمة الفعلية. قد تختلف الرسوم للعناصر الثقيلة.",
"selectServiceLocation": "اختر موقع الخدمة",
"apptOn": "التعيين في",
"merged": "مُدمج",
"date": "التاريخ",
"selectAll": "اختر الكل",
"unselectAll": "إلغاء اختيار الكل",
"copySelectedServices": "نسخ الخدمات المحددة"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1315,7 +1322,14 @@ static const Map<String,dynamic> en_US = {
"callNow": "Call Now",
"condition": "Condition",
"servicesNotAvailableHomeLocation": "Some services are not available on home location.",
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary."
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary.",
"selectServiceLocation": "Select Service Location",
"apptOn": "Appt On",
"merged": "Merged",
"date": "Date",
"selectAll": "Select All",
"unselectAll": "Unselect All",
"copySelectedServices": "Copy Selected Services"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -627,5 +627,12 @@ abstract class LocaleKeys {
static const condition = 'condition';
static const servicesNotAvailableHomeLocation = 'servicesNotAvailableHomeLocation';
static const additionalChargesNotice = 'additionalChargesNotice';
static const selectServiceLocation = 'selectServiceLocation';
static const apptOn = 'apptOn';
static const merged = 'merged';
static const date = 'date';
static const selectAll = 'selectAll';
static const unselectAll = 'unselectAll';
static const copySelectedServices = 'copySelectedServices';
}

@ -41,7 +41,7 @@ class ChatMessageModel {
@override
String toString() {
return 'ChatMessageModel{id: $id, senderUserID: $senderUserID, senderName: $senderName, messageType: $messageType, chatMessageTypeEnum: $chatMessageTypeEnum, chatText: $chatText, requestID: $requestID, reqOfferID: $reqOfferID, serviceProviderID: $serviceProviderID, offerStatus: $offerStatus, reqOffer: $reqOffer, isRead: $isRead, readOn: $readOn, isMyMessage: $isMyMessage}';
return 'ChatMessageModel{id: $id, senderUserID: $senderUserID, senderName: $senderName, messageType: $messageType, chatMessageTypeEnum: $chatMessageTypeEnum, chatText: $chatText, requestID: $requestID, reqOfferID: $reqOfferID, serviceProviderID: $serviceProviderID, offerStatus: $offerStatus, reqOffer: ${reqOffer.toString()}, isRead: $isRead, readOn: $readOn, isMyMessage: $isMyMessage}';
}
ChatMessageModel.fromJson(Map<String, dynamic> json) {
@ -107,6 +107,11 @@ class ReqOffer {
requestOfferStatusEnum = ((json['offerStatus']) as int).toRequestOfferStatusEnum();
requestsTypeEnum = RequestsTypeEnum.serviceRequest;
}
@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}';
}
}
class OfferRequestCommentModel {

@ -22,12 +22,7 @@ abstract class AdsRepo {
Future<List<AdDetailsModel>> getAllAds({required bool isMyAds});
Future<List<AdDetailsModel>> getExploreAdsBasedOnFilters({
List<String>? cityIdsList,
List<String>? vehicleModelYearIdsList,
List<String>? vehicleBrandIdsList,
List<String>? createdByRolesIdsList,
});
Future<List<AdDetailsModel>> getExploreAdsBasedOnFilters({List<String>? cityIdsList, List<String>? vehicleModelYearIdsList, List<String>? vehicleBrandIdsList, List<String>? createdByRolesIdsList});
Future<List<AdDetailsModel>> getMyReservedAds();
@ -48,6 +43,8 @@ abstract class AdsRepo {
Future<GenericRespModel> uploadBankReceiptsOnReserveDealDone({required int adId, required String detailNote, required List<PdfReceiptModel> pdfReceiptsList});
Future<List<BuyersChatForAdsModel>> getChatBuyersForAds({required int adsID});
Future<GenericRespModel> createAdExtensionOrder({required int adID, required List<int> specialServiceIds, required int adsDurationId});
}
class AdsRepoImp implements AdsRepo {
@ -284,6 +281,25 @@ class AdsRepoImp implements AdsRepo {
return Future.value(adsGenericModel);
}
@override
Future<GenericRespModel> createAdExtensionOrder({required int adID, required List<int> specialServiceIds, required int adsDurationId}) async {
var postParams = {
"adsID": adID,
"adsDurationID": adsDurationId,
"specialServiceIDs": specialServiceIds,
};
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsExtendDurationCreate,
postParams,
token: token,
);
return Future.value(adsGenericModel);
}
@override
Future<GenericRespModel> deleteAd({required int adId}) async {
var postParams = {

@ -69,7 +69,7 @@ abstract class BranchRepo {
Future<GenericRespModel> getMatchedServices(int oldBranchId, int newBranchId, int categoryId);
Future<GenericRespModel> duplicateItems(Map<String, dynamic> map);
Future<GenericRespModel> duplicateItems({required String providerBranchID, required List<int> items});
Future<GenericRespModel> getAllProviderDealers(Map<String, dynamic> map);
@ -188,9 +188,7 @@ class BranchRepoImp implements BranchRepo {
};
String? token = AppState().getUser.data?.accessToken;
debugPrint(token);
return await injector
.get<ApiClient>()
.getJsonForObject((json) => Document.fromJson(json), ApiConsts.fetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
return await injector.get<ApiClient>().getJsonForObject((json) => Document.fromJson(json), ApiConsts.fetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
}
@override
@ -198,14 +196,7 @@ class BranchRepoImp implements BranchRepo {
List<Map<String, dynamic>> map = [];
for (int i = 0; i < documents!.length; i++) {
if (documents[i].document != null) {
var postParams = {
"id": documents[i].id,
"serviceProviderID": documents[i].serviceProviderId,
"documentID": documents[i].documentId,
"documentExt": documents[i].fileExt,
"documentImage": documents[i].document,
"isActive": true
};
var postParams = {"id": documents[i].id, "serviceProviderID": documents[i].serviceProviderId, "documentID": documents[i].documentId, "documentExt": documents[i].fileExt, "documentImage": documents[i].document, "isActive": true};
map.add(postParams);
}
}
@ -314,8 +305,12 @@ class BranchRepoImp implements BranchRepo {
}
@override
Future<GenericRespModel> duplicateItems(Map<String, dynamic> map) async {
Future<GenericRespModel> duplicateItems({required String providerBranchID, required List<int> items}) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, dynamic> map = {
"providerBranchID": providerBranchID,
"serviceItems": items,
};
return await apiClient.postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.duplicateItems, map, token: t);
}
@ -401,8 +396,7 @@ class BranchRepoImp implements BranchRepo {
@override
Future<ProviderProfileModel> getBranchAndServicesByProviderId(int providerId) async {
var postParams = {"serviceProviderID": providerId.toString()};
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
return ProviderProfileModel.fromJson(adsGenericModel.data);
}

@ -319,11 +319,11 @@ class AdVM extends BaseVM {
if (respModel.messageStatus != 1) {
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? "Something went wrong!");
Utils.showToast(respModel.message ?? LocaleKeys.somethingWrong.tr());
return;
}
Utils.hideLoading(context);
Utils.showToast("A has been marked as sold successfully!");
Utils.showToast(respModel.message ?? "A has been marked as sold successfully!");
updateIsExploreAds(false);
applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.sold); //pending for review
navigateReplaceWithName(context, AppRoutes.dashboard);
@ -335,7 +335,7 @@ class AdVM extends BaseVM {
if (respModel.messageStatus != 1) {
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? "Something went wrong!");
Utils.showToast(respModel.message ?? LocaleKeys.somethingWrong.tr());
return;
}
Utils.hideLoading(context);
@ -351,7 +351,7 @@ class AdVM extends BaseVM {
if (respModel.messageStatus != 1) {
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? "Something went wrong!");
Utils.showToast(respModel.message ?? LocaleKeys.somethingWrong.tr());
return;
}
Utils.hideLoading(context);
@ -367,7 +367,7 @@ class AdVM extends BaseVM {
if (respModel.messageStatus != 1) {
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? "Something went wrong!");
Utils.showToast(respModel.message ?? LocaleKeys.somethingWrong.tr());
return;
}
Utils.hideLoading(context);
@ -1674,18 +1674,36 @@ class AdVM extends BaseVM {
setState(ViewState.idle);
}
///// Edit Work Amir
void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd}) {
isAdEditEnabled = true;
previousAdDetails = previousDetails;
autoFillSelectedVehicleType();
autoFillSelectedVehicleAdsDuration();
navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [AppState().currentAppType == AppType.provider, isFromExtendAd]);
navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [AppState().currentAppType == AppType.provider, isFromExtendAd, previousDetails.id]);
}
autoFillSelectedVehicleType() async {
Future<bool> createAdExtensionOrder(BuildContext context, {required int adId, required int adsDurationId}) async {
try {
Utils.showLoading(context);
GenericRespModel respModel = await adsRepo.createAdExtensionOrder(adID: adId, adsDurationId: adsDurationId, specialServiceIds: []);
if (respModel.messageStatus != 1) {
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? LocaleKeys.somethingWrong.tr());
return false;
}
Utils.hideLoading(context);
return respModel.messageStatus == 1;
} catch (e) {
Utils.hideLoading(context);
Utils.showToast(e.toString());
return false;
}
return false;
}
void autoFillSelectedVehicleType() async {
if (vehicleTypes.isEmpty) {
await getVehicleTypes();
return;
@ -1701,7 +1719,7 @@ class AdVM extends BaseVM {
notifyListeners();
}
autoFillSelectedVehicleAdsDuration() async {
void autoFillSelectedVehicleAdsDuration() async {
if (vehicleAdsDurations.isEmpty) {
await getVehicleAdsDuration();
}
@ -1732,7 +1750,7 @@ class AdVM extends BaseVM {
notifyListeners();
}
autoFillSelectedVehicleAdsDetails() async {
void autoFillSelectedVehicleAdsDetails() async {
int index = vehicleBrands.indexWhere((element) => element.id == previousAdDetails!.vehicle!.model!.vehicleBrandID);
if (index != -1) {
await updateSelectionVehicleBrandId(SelectionModel(selectedId: vehicleBrands[index].id!, selectedOption: vehicleBrands[index].vehicleBrandDescription ?? ""));
@ -1750,14 +1768,13 @@ class AdVM extends BaseVM {
if (indexCountry != -1) {
updateSelectionVehicleCountryId(SelectionModel(selectedId: vehicleCountries[indexCountry].id!, selectedOption: vehicleCountries[indexCountry].countryName ?? ""));
}
updateSelectionVehicleCityId(SelectionModel(selectedId: previousAdDetails!.vehicle!.cityID!, selectedOption: previousAdDetails!.vehicle!.cityName ?? ""));
vehicleDemandAmount = previousAdDetails!.vehicle!.demandAmount!.toInt().toString();
vehicleVin = previousAdDetails!.vehicle!.vehicleVIN.toString();
vehicleTitle = previousAdDetails!.vehicle!.vehicleTitle.toString();
vehicleDescription = previousAdDetails!.vehicle!.vehicleDescription.toString();
financeAvailableStatus = previousAdDetails!.vehicle!.isFinanceAvailable ?? false;
pickedPostingImages.clear();
if (previousAdDetails!.vehicle!.image != null && previousAdDetails!.vehicle!.image!.isNotEmpty) {
for (var element in previousAdDetails!.vehicle!.image!) {

@ -49,7 +49,7 @@ class AppointmentsVM extends BaseVM {
AppointmentsVM({required this.commonServices, required this.appointmentRepo, required this.commonRepo, required this.branchRepo});
bool isUpcommingEnabled = true;
bool isUpcomingEnabled = true;
bool isFetchingLists = false;
int selectedBranch = 0;
int selectedAppointmentIndex = 0;
@ -229,10 +229,9 @@ class AppointmentsVM extends BaseVM {
}
void removeServiceInCurrentAppointment(int index) {
int serviceId = servicesInCurrentAppointment
.elementAt(index)
.serviceProviderServiceId ?? -1;
int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1;
allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId);
servicesInCurrentAppointment[index].serviceItems!.clear();
servicesInCurrentAppointment.removeAt(index);
notifyListeners();
}
@ -256,7 +255,7 @@ class AppointmentsVM extends BaseVM {
Future<void> populateAppointmentsFilterList() async {
if (appointmentsFilterOptions.isNotEmpty) return;
myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); // 13 is to get Appointments Filter Enums
myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.appointmentsFilterEnumId); // 13 is to get Appointments Filter Enums
for (int i = 0; i < myAppointmentsEnum.length; i++) {
appointmentsFilterOptions.add(FilterListModel(title: myAppointmentsEnum[i].enumValueStr, isSelected: false, id: myAppointmentsEnum[i].enumValue));
@ -352,8 +351,7 @@ class AppointmentsVM extends BaseVM {
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
// myFilteredAppointments = myAppointments;
myUpComingAppointments =
myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
setState(ViewState.idle);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners();
@ -414,6 +412,11 @@ class AppointmentsVM extends BaseVM {
}
}
bool isShowMergeButton() {
return myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.length > 1;
}
Future<GenericRespModel> createMergeAppointment(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
GenericRespModel genericRespModel = await appointmentRepo.createMergeAppointment(map);
@ -423,23 +426,20 @@ class AppointmentsVM extends BaseVM {
bool inNeedToEnableMergeButton = false;
updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected =
!(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
void updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []);
if (count > 1)
if (count > 1) {
inNeedToEnableMergeButton = true;
else
} else {
inNeedToEnableMergeButton = false;
}
notifyListeners();
}
int countSelected(List<AppointmentListModel> appointments) {
return appointments
.where((appointment) => appointment.isSelected == true)
.toList()
.length;
return appointments.where((appointment) => appointment.isSelected == true).toList().length;
}
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) {
@ -481,10 +481,7 @@ class AppointmentsVM extends BaseVM {
int selectedSubServicesCounter = 0;
void onItemUpdateOrSelected(int index, bool selected, int itemId) {
int serviceIndex = 0;
if (servicesInCurrentAppointment.isNotEmpty) {
serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
}
int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
log("index: $index");
log("selected: $selected");
@ -500,9 +497,10 @@ class AppointmentsVM extends BaseVM {
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
for (var element in allSelectedItemsInAppointments) {
if (!ifItemAlreadySelected(element.id!)) {
servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0");
if (serviceIndex != -1) {
servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0");
}
}
}
} else {
@ -512,10 +510,12 @@ class AppointmentsVM extends BaseVM {
log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
if (serviceIndex != -1) {
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
}
}
notifyListeners();
}
@ -613,14 +613,13 @@ class AppointmentsVM extends BaseVM {
Column(
children: List.generate(
selectedService.serviceItems!.length,
(index) =>
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true),
],
),
(index) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true),
],
),
),
),
Row(
@ -655,8 +654,7 @@ class AppointmentsVM extends BaseVM {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(selectedService.isHomeSelected ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" : "${selectedService
.currentTotalServicePrice}")
(selectedService.isHomeSelected ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" : "${selectedService.currentTotalServicePrice}")
.toText(fontSize: 29, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
@ -803,7 +801,7 @@ class AppointmentsVM extends BaseVM {
}
}
// BRANCHES RELATED
// BRANCHES RELATED
List<BranchDetailModel> nearbyBranches = [];
List<BranchDetailModel> myRecentBranches = [];
@ -912,7 +910,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Provider Filter
// Provider Filter
List<DropValue> branchFilterProviderSearchHistory = [];
void removeBranchFilterProviderSearchHistory({bool isClear = false, required int index}) {
@ -951,7 +949,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Category Filter
// Category Filter
List<DropValue> branchFilterCategorySearchHistory = [];
void removeBranchFilterCategorySearchHistory({bool isClear = false, required int index}) {
@ -990,7 +988,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Services Filter
// Services Filter
List<DropValue> branchFilterServicesSearchHistory = [];
void removeBranchFilterServicesSearchHistory({bool isClear = false, required int index}) {
@ -1043,7 +1041,7 @@ class AppointmentsVM extends BaseVM {
return false;
}
// Rating filter
// Rating filter
double branchFilterByRating = 4.0;
@ -1080,10 +1078,10 @@ class AppointmentsVM extends BaseVM {
DropValue(
element.id ?? 0,
((element.categoryName!.isEmpty
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
"N/A"),
""),
);
@ -1178,7 +1176,7 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.idle);
}
// Appointments Filter Screen
// Appointments Filter Screen
List<DropValue> branchesDropList = [];
@ -1207,7 +1205,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Provider Filter For Appointments
// Provider Filter For Appointments
List<DropValue> appointmentFilterProviderSearchHistory = [];
void removeAppointmentFilterProviderSearchHistory({bool isClear = false, required int index}) {
@ -1258,7 +1256,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Branches Filter For Appointments
// Branches Filter For Appointments
List<DropValue> appointmentFilterBranchSearchHistory = [];
@ -1297,7 +1295,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
// Category Filter For Appointments
// Category Filter For Appointments
List<DropValue> appointmentFilterCategorySearchHistory = [];
@ -1498,11 +1496,4 @@ class AppointmentsVM extends BaseVM {
}
setState(ViewState.idle);
}
bool isShowMergeButton() {
return myFilteredAppointments2[selectedAppointmentIndex]
.customerAppointmentList!
.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed);
}
}

@ -211,8 +211,6 @@ class PaymentVM extends ChangeNotifier {
navigateReplaceWithName(context, AppRoutes.dashboard);
}
onSubscriptionPaymentSuccess(BuildContext context) {
pop(context);

@ -76,7 +76,9 @@ class RequestsVM extends BaseVM {
Future<bool> getRequestsBasedOnFilters() async {
myFilteredRequests.clear();
setState(ViewState.busy);
int requestTypeIdApi = requestsTypeFilterOptions.firstWhere((element) => element.isSelected).id;
int requestTypeIdApi = requestsTypeFilterOptions
.firstWhere((element) => element.isSelected)
.id;
int requestCityIdApi = 0;
if (vehicleCityId.selectedId != -1) {

@ -487,8 +487,22 @@ class ServiceVM extends BaseVM {
notifyListeners();
}
Future<GenericRespModel> duplicateItems(Map<String, dynamic> map) async {
return await branchRepo.duplicateItems(map);
Future<void> duplicateItems({required String providerBranchID, required BuildContext context}) async {
List<int> items = [];
for (var element in matchedServices!) {
items.addAll(element.serviceItems!.where((e) => e.isUpdateOrSelected == true).map((e) => e.id ?? 0).toList());
}
try {
Utils.showLoading(context);
GenericRespModel genericRespModel = await branchRepo.duplicateItems(items: items, providerBranchID: providerBranchID);
Utils.hideLoading(context);
Utils.showToast(genericRespModel.message ?? "");
pop(context);
pop(context);
} catch (e, s) {
Utils.showToast(e.toString());
}
}
// Branch Users

@ -113,7 +113,7 @@ class _AdsDetailViewState extends State<AdsDetailView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label}".toText(fontSize: 16, maxLines: 2),
child: "${widget.adDetails.vehicle!.vehicleTitle} | ${widget.adDetails.vehicle!.color!.label}| ${widget.adDetails.id}".toText(fontSize: 16, maxLines: 2),
),
(widget.adDetails.vehicle!.cityName ?? "").toText(fontSize: 10, color: MyColors.lightTextColor),
],
@ -273,6 +273,17 @@ class _AdsDetailViewState extends State<AdsDetailView> {
@override
Widget build(BuildContext context) {
Widget actionWidget = const SizedBox();
if ((widget.adDetails.isMyAd ?? false) && (widget.adDetails.adPostStatus != AdPostStatus.reserved) && (widget.adDetails.adPostStatus != AdPostStatus.active)) {
actionWidget = IconButton(
icon: const Icon(Icons.delete_outline, color: MyColors.redColor),
onPressed: () {
return deleteAdBottomSheet(context);
},
);
} else {
actionWidget = IconButton(icon: const Icon(Icons.chat_outlined, color: Colors.black), onPressed: () => adVM.onMessagesButtonPressed(context: context, adDetailsModel: widget.adDetails));
}
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.vehicleDetails.tr(),
@ -280,15 +291,7 @@ class _AdsDetailViewState extends State<AdsDetailView> {
isRemoveBackButton: false,
isDrawerEnabled: false,
actions: [
((widget.adDetails.isMyAd ?? false) && (widget.adDetails.adPostStatus != AdPostStatus.reserved) && (widget.adDetails.adPostStatus != AdPostStatus.active)
? IconButton(
icon: const Icon(Icons.delete_outline, color: MyColors.redColor),
onPressed: () {
return deleteAdBottomSheet(context);
},
)
: IconButton(icon: const Icon(Icons.chat_outlined, color: Colors.black), onPressed: () => adVM.onMessagesButtonPressed(context: context, adDetailsModel: widget.adDetails)))
.toContainer(
actionWidget.toContainer(
margin: const EdgeInsets.fromLTRB(0, 8, 21, 8),
paddingAll: 0,
padding: const EdgeInsets.only(right: 21),
@ -297,7 +300,7 @@ class _AdsDetailViewState extends State<AdsDetailView> {
isEnabledBorder: true,
height: 40,
width: 42,
)
),
],
onTap: () {},
),

@ -885,7 +885,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
SelectionModel(selectedId: adDetailsModel.vehicle!.vehicleType!, selectedOption: (adDetailsModel.vehicle!.vehicleType!).toVehicleTypeString(), errorValue: ""),
);
showMyBottomSheet(context, child: const AdDurationSelectionSheet(isFromExtendAd: true, isUpdateAdSelected: false));
showMyBottomSheet(context, child: AdDurationSelectionSheet(isFromExtendAd: true, isUpdateAdSelected: false, adsID: adDetailsModel.id ?? -1));
},
),
),

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
@ -18,8 +20,14 @@ import 'package:easy_localization/easy_localization.dart';
class AdDurationSelectionSheet extends StatelessWidget {
final bool isFromExtendAd;
final bool isUpdateAdSelected;
final int adsID;
const AdDurationSelectionSheet({super.key, required this.isFromExtendAd, required this.isUpdateAdSelected});
const AdDurationSelectionSheet({
super.key,
required this.isFromExtendAd,
required this.isUpdateAdSelected,
required this.adsID,
});
@override
Widget build(BuildContext context) {
@ -118,15 +126,19 @@ class AdDurationSelectionSheet extends StatelessWidget {
title: adVM.isFetchingLists ? "" : LocaleKeys.select.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(21),
onPressed: () {
onPressed: () async {
if (adVM.isFetchingLists) {
return;
} else {
if (isFromExtendAd && !isUpdateAdSelected) {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.extendAds);
return;
bool status = await adVM.createAdExtensionOrder(context, adId: adsID, adsDurationId: adVM.vehicleAdDurationId.selectedId);
log("hereStatus: $status");
if (status) {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.extendAds);
}
} else {
navigateReplaceWithName(context, AppRoutes.createAdView);
}
navigateReplaceWithName(context, AppRoutes.createAdView);
}
},
).toContainer(paddingAll: 0, backgroundColor: Colors.white),

@ -37,7 +37,7 @@ class _DamagePicturesListState extends State<DamagePicturesList> {
return const Center(child: CircularProgressIndicator());
}
return appointmentsVM.serviceItemsFromApi.isEmpty
? const EmptyWidget(text: "No Items Found", isWrapedColumn: false,)
? EmptyWidget(text: LocaleKeys.noItemstoShow.tr(), isWrappedColumn: false)
: ListView.separated(
itemCount: appointmentsVM.serviceItemsFromApi.length,
itemBuilder: (BuildContext context, int index) {

@ -18,7 +18,7 @@ import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class SelectAdTypeView extends StatelessWidget {
final List<bool> arguments; // [0] isProviderOrCustomer [1] isFromExtendAd
final List<dynamic> arguments; // [0] isProviderOrCustomer [1] isFromExtendAd
const SelectAdTypeView({Key? key, required this.arguments}) : super(key: key);
@ -42,6 +42,10 @@ class SelectAdTypeView extends StatelessWidget {
Widget build(BuildContext context) {
bool isProvider = arguments[0];
bool isFromExtendAd = arguments[1];
int adsId = -1;
if (arguments.length > 2) {
adsId = arguments[2] ?? -1;
}
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.selectAdType.tr(),
@ -64,7 +68,7 @@ class SelectAdTypeView extends StatelessWidget {
adVM.autoFillSelectedVehicleAdsDetails();
}
log("isUpdateAdSelected: ${adVM.isAdEditEnabled}}");
showMyBottomSheet(context, child: AdDurationSelectionSheet(isUpdateAdSelected: adVM.isAdEditEnabled, isFromExtendAd: isFromExtendAd));
showMyBottomSheet(context, child: AdDurationSelectionSheet(isUpdateAdSelected: adVM.isAdEditEnabled, isFromExtendAd: isFromExtendAd, adsID: adsId));
},
child: SizedBox(
width: double.infinity,

@ -56,9 +56,7 @@ class BookAppointmentServicesView extends StatelessWidget {
children: [
Row(
children: [
Expanded(
child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true),
),
Expanded(child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true)),
IconButton(onPressed: () => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex), icon: const Icon(Icons.delete_outline, color: MyColors.redColor))
],
),

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
@ -25,7 +27,10 @@ class BookAppointmentsItemView extends StatelessWidget {
isRemoveBackButton: false,
isDrawerEnabled: false,
actions: [MyAssets.searchIcon.buildSvg().paddingOnly(right: 21)],
onBackButtonTapped: () => Navigator.pop(context),
onBackButtonTapped: () {
context.read<AppointmentsVM>().resetCategorySelectionBottomSheet();
Navigator.pop(context);
},
),
body: Consumer(
builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
@ -37,7 +42,7 @@ class BookAppointmentsItemView extends StatelessWidget {
width: double.infinity,
color: MyColors.darkTextColor,
alignment: Alignment.centerLeft,
child: ("${appointmentsVM.selectedSubServicesCounter} " + LocaleKeys.itemsSelected.tr()).toText(fontSize: 16, color: MyColors.white).horPaddingMain(),
child: ("${appointmentsVM.selectedSubServicesCounter} ${LocaleKeys.itemsSelected.tr()}").toText(fontSize: 16, color: MyColors.white).horPaddingMain(),
),
16.height,
Column(

@ -156,7 +156,7 @@ class ReviewAppointment extends StatelessWidget {
3.height,
Row(children: [
"${LocaleKeys.dateAndTime.tr()}: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${scheduleData.selectedCustomTimeDateSlotModel!.date!.date} at ${selectedTimeSlot}".toText(fontSize: 12, isBold: true),
"${scheduleData.selectedCustomTimeDateSlotModel!.date!.date} at $selectedTimeSlot".toText(fontSize: 12, isBold: true),
]),
Row(children: [
("${LocaleKeys.location.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
@ -181,7 +181,7 @@ class ReviewAppointment extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.serviceCharges.tr().toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true),
"${scheduleData.amountTotal.toString()} SAR".toText(fontSize: 16, isBold: true),
"${scheduleData.amountTotal.toString()} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
],
),
if (scheduleData.appointmentType == 1) ...[
@ -200,7 +200,7 @@ class ReviewAppointment extends StatelessWidget {
],
);
},
separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2),
separatorBuilder: (BuildContext context, int index) => const Divider(thickness: 2),
).paddingOnly(bottom: 10),
],
),

@ -84,15 +84,7 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
],
if (appointmentsVM.branchSelectedServiceId.selectedId != -1 && !appointmentsVM.isFetchingServices) ...[
16.height,
Row(
children: [
"Select Service Location".toText(
fontSize: 16,
isBold: true,
color: MyColors.black,
),
],
),
Row(children: [LocaleKeys.selectServiceLocation.tr().toText(fontSize: 16, isBold: true, color: MyColors.black)]),
8.height,
Row(
children: [

@ -136,7 +136,7 @@ class AdsFragment extends StatelessWidget {
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [injector.get<AppState>().currentAppType == AppType.provider, false]);
navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [injector.get<AppState>().currentAppType == AppType.provider, false, -1]);
},
backgroundColor: MyColors.darkPrimaryColor,
child: const Icon(Icons.add, color: MyColors.white),

@ -9,7 +9,6 @@ import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/components/ads_images_corousel_widget.dart';
import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart';
import 'package:mc_common_app/views/requests/request_bottomsheets.dart';
@ -25,7 +24,7 @@ class RequestDetailPage extends StatelessWidget {
const RequestDetailPage({Key? key, required this.requestDetailPageArguments}) : super(key: key);
Widget buildRequestDetailActionFooter({required int requestId, required RequestStatusEnum requestStatus, required RequestsTypeEnum requestTypeEnum, required String statusText, required BuildContext context}) {
final requestsVM = context.read<RequestsVM>();
// final requestsVM = context.read<RequestsVM>();
switch (requestStatus) {
case RequestStatusEnum.submitted:
return ShowFillButton(

@ -142,13 +142,16 @@ class _ForgetPasswordPageState extends State<ForgetPasswordPage> {
);
return Padding(
padding: const EdgeInsets.all(2.0),
child: DropdownField( dropdownValue: tempCountry ,(DropValue value) {
countryCode = value.subValue;
tempCountry = value;
setState(() {
});
}, list: dropList, hint: LocaleKeys.selectCountryCode.tr()),
child: DropdownField(
dropdownValue: tempCountry,
(DropValue value) {
countryCode = value.subValue;
tempCountry = value;
setState(() {});
},
list: dropList,
hint: LocaleKeys.selectCountryCode.tr(),
),
);
} else {
return const Center(

@ -40,6 +40,8 @@ class _LoginWithPasswordState extends State<LoginWithPassword> {
String countryCode = "";
Country? _country;
DropValue? tempCountry;
late UserVM userVM;
@override
@ -78,7 +80,7 @@ class _LoginWithPasswordState extends State<LoginWithPassword> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomAppBar(isRemoveBackButton: true, title: ""),
appBar: const CustomAppBar(isRemoveBackButton: true, title: ""),
body: Container(
width: double.infinity,
height: double.infinity,
@ -169,11 +171,18 @@ class _LoginWithPasswordState extends State<LoginWithPassword> {
if (_country != null) {
List<DropValue> dropList = [];
_country!.data?.forEach((element) {
dropList.add(DropValue(element.id ?? 0, (element.countryName ?? "") + " " + (element.countryCode ?? ""), element.countryCode ?? ""));
dropList.add(DropValue(element.id ?? 0, "${element.countryName ?? ""} ${element.countryCode ?? ""}", element.countryCode ?? ""));
});
return DropdownField((DropValue value) {
countryCode = value.subValue;
}, list: dropList, hint: LocaleKeys.selectCountryCode.tr());
return DropdownField(
dropdownValue: tempCountry,
(DropValue value) {
countryCode = value.subValue;
tempCountry = value;
setState(() {});
},
list: dropList,
hint: LocaleKeys.selectCountryCode.tr(),
);
} else {
return const Center(
child: CircularProgressIndicator(),

@ -5,16 +5,18 @@ import 'package:mc_common_app/theme/colors.dart';
class EmptyWidget extends StatelessWidget {
final String text;
final bool isWrapedColumn;
final bool isWrappedColumn;
final Widget? spacerWidget;
const EmptyWidget({Key? key, required this.text, this.isWrapedColumn = true}) : super(key: key);
const EmptyWidget({Key? key, required this.text, this.isWrappedColumn = true, this.spacerWidget}) : super(key: key);
@override
Widget build(BuildContext context) {
if (isWrapedColumn) {
if (isWrappedColumn) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
spacerWidget ?? const SizedBox(),
text.toText(fontSize: 16, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium),
],
);

Loading…
Cancel
Save