Fixing JIRA Issues

aamir_dev
Faiz Hashmi 11 months ago
parent c7446a91b3
commit 892f52ced8

@ -722,5 +722,15 @@
"noImagesToShow": "لا توجد صور للعرض",
"updateGroupServices": "تحديث خدمات المجموعة",
"addCommentsHere": "أضف التعليقات هنا",
"waitForBranchVerification": "يرجى الانتظار حتى يتم التحقق من الفرع."
"waitForBranchVerification": "يرجى الانتظار حتى يتم التحقق من الفرع.",
"reportComplaint": "تقديم شكوى",
"descriptionCannotBeEmpty": "وصف لا يمكن أن يكون فارغًا.",
"adMarkedAsSold": "تم وسم الإعلان كـ 'مباع' بنجاح!",
"chargesAndServiceRangeGreaterThanZero": "يجب أن تكون الرسوم ونطاق الخدمة أكبر من الصفر.",
"cannotSelectAllDaysAsOff": "لا يمكنك اختيار جميع الأيام كأيام عطلة.",
"endDateAfterStartDate": "يجب أن تكون تاريخ النهاية بعد تاريخ البدء.",
"pleaseEnterStartDateFirst": "من فضلك أدخل تاريخ البدء أولاً.",
"endTimeAfterStartTime": "يجب أن يكون وقت الانتهاء بعد وقت البدء.",
"pickedLocationNotice": "سيتم استخدام هذا الموقع لجميع الخدمات المنزلية في هذه الموعد",
"serviceNotProvided": "لسوء الحظ، هذه الخدمة غير متوفرة في الفرع الذي اخترته في هذا الموقع المحدد"
}

@ -646,7 +646,7 @@
"customerCarePrompt": "Got any question? We are here to service. Click here to talk to our customer care right now.",
"callNow": "Call Now",
"condition": "Condition",
"servicesNotAvailableHomeLocation": "Some services are not available on home location.",
"servicesNotAvailableHomeLocation": "This location will be same for all services",
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary.",
"selectServiceLocation": "Select Service Location",
"apptOn": "Appt On",
@ -720,6 +720,15 @@
"noImagesToShow": "No Images to Show",
"updateGroupServices": "Update Group Services",
"addCommentsHere": "Add comments here",
"waitForBranchVerification": "Please wait for the branch verification."
"waitForBranchVerification": "Please wait for the branch verification.",
"reportComplaint": "Report a complaint",
"descriptionCannotBeEmpty": "Description cannot be empty.",
"adMarkedAsSold": "Ad has been marked as sold successfully!",
"chargesAndServiceRangeGreaterThanZero": "Charges and Service range should be greater than zero.",
"cannotSelectAllDaysAsOff": "You cannot select all days as Off days.",
"endDateAfterStartDate": "End Date should be after start date.",
"pleaseEnterStartDateFirst": "Please enter start date first.",
"endTimeAfterStartTime": "End Time should be after start time.",
"pickedLocationNotice": "This picked location will be used for all home-based services in this appointment",
"serviceNotProvided": "Unfortunately, this service is not provided by your selected branch in this picked location."
}

@ -17,28 +17,29 @@ class ApiConsts {
static String signalRUrl = "${baseUrl}McHub";
//User
static String Login_V1 = "${baseUrlServices}api/Account/Login_V1";
static String Login_V2_OTP = "${baseUrlServices}api/Account/Login_V2_OTP";
static String Login_V2_OTPVerify = "${baseUrlServices}api/Account/Login_V2_OTPVerify";
static String loginV1 = "${baseUrlServices}api/Account/Login_V1";
static String loginV2OTP = "${baseUrlServices}api/Account/Login_V2_OTP";
static String loginV2OTPVerify = "${baseUrlServices}api/Account/Login_V2_OTPVerify";
static String user = "${baseUrlServices}api/User/";
static String GetAllCountry = "${baseUrlServices}api/Master/Country_Get";
static String GetProviderRoles = "${baseUrlServices}api/Master/RoleServiceProvider_Get";
static String GetAllCities = "${baseUrlServices}api/Master/City_Get";
static String ForgetPasswordOTPRequest = "${baseUrlServices}api/Account/ForgetPasswordOTPRequest";
static String ForgetPasswordOTPCompare = "${baseUrlServices}api/Account/ForgetPasswordOTPCompare";
static String ForgetPassword = "${baseUrlServices}api/Account/ForgetPassword";
static String Login_Email_OTP = "${baseUrlServices}api/Account/EmailVerify";
static String Login_Email_OTPVerify = "${baseUrlServices}api/Account/EmailVerifyOTPVerify";
static String ChangePassword = "${baseUrlServices}api/Account/ChangePassword";
static String ChangeMobileNoOTPRequest = "${baseUrlServices}api/Account/ChangeMobileNoOTPRequest";
static String ChangeMobileNo = "${baseUrlServices}api/Account/ChangeMobileNo";
static String ChangeEmailOTPRequest = "${baseUrlServices}api/Account/ChangeEmailOTPRequest";
static String ChangeEmail = "${baseUrlServices}api/Account/ChangeEmail";
static String EmailVerify = "${baseUrlServices}api/Account/EmailVerify";
static String EmailVerifyOTPVerify = "${baseUrlServices}api/Account/EmailVerifyOTPVerify";
static String LogoutUser = "${baseUrlServices}api/Account/Logout";
static String UpdateUserImage = "${baseUrlServices}api/User_UpdateProfileImage";
static String GetUserImage = "${baseUrlServices}api/ProfileImage";
static String getAllCountry = "${baseUrlServices}api/Master/Country_Get";
static String getProviderRoles = "${baseUrlServices}api/Master/RoleServiceProvider_Get";
static String getAllCities = "${baseUrlServices}api/Master/City_Get";
static String forgetPasswordOTPRequest = "${baseUrlServices}api/Account/ForgetPasswordOTPRequest";
static String forgetPasswordOTPCompare = "${baseUrlServices}api/Account/ForgetPasswordOTPCompare";
static String forgetPassword = "${baseUrlServices}api/Account/ForgetPassword";
static String loginEmailOTP = "${baseUrlServices}api/Account/EmailVerify";
static String loginEmailOTPVerify = "${baseUrlServices}api/Account/EmailVerifyOTPVerify";
static String changePassword = "${baseUrlServices}api/Account/ChangePassword";
static String changeMobileNoOTPRequest = "${baseUrlServices}api/Account/ChangeMobileNoOTPRequest";
static String changeMobileNo = "${baseUrlServices}api/Account/ChangeMobileNo";
static String changeEmailOTPRequest = "${baseUrlServices}api/Account/ChangeEmailOTPRequest";
static String changeEmail = "${baseUrlServices}api/Account/ChangeEmail";
static String emailVerify = "${baseUrlServices}api/Account/EmailVerify";
static String emailVerifyOTPVerify = "${baseUrlServices}api/Account/EmailVerifyOTPVerify";
static String logoutUser = "${baseUrlServices}api/Account/Logout";
static String updateUserImage = "${baseUrlServices}api/User_UpdateProfileImage";
static String getUserImage = "${baseUrlServices}api/ProfileImage";
static String providerComplaintCreate = "${baseUrlServices}api/ServiceProviders/ProviderComplaint_Create";
//Profile
static String fetProviderDocument = "${baseUrlServices}api/ServiceProviders/ServiceProviderDocument_Get";
@ -151,7 +152,6 @@ class ApiConsts {
//Branch Users
static String getAllProviderDealers = "${baseUrlServices}api/ServiceProviders/DealershipUserBranchWise_Get";
static String getBranchUser = "${baseUrlServices}api/ServiceProviders/BranchUser_Get";
static String assignDealerToBranch = "${baseUrlServices}api/ServiceProviders/BranchUser_Create";
static String removeDealerFromBranch = "${baseUrlServices}api/ServiceProviders/BranchUser_Update";

@ -240,6 +240,8 @@ extension AdPostEnum on int {
return AdPostStatus.reserveCancel;
} else if (this == 12) {
return AdPostStatus.deActive;
} else if (this == 13) {
return AdPostStatus.pendingForActive;
} else if (this == 0) {
return AdPostStatus.allAds;
} else {
@ -488,6 +490,9 @@ extension AdPostStatusToInt on AdPostStatus {
case AdPostStatus.deActive:
return 12;
case AdPostStatus.pendingForActive:
return 13;
default:
return 0;

@ -738,7 +738,17 @@ class CodegenLoader extends AssetLoader{
"noImagesToShow": "لا توجد صور للعرض",
"updateGroupServices": "تحديث خدمات المجموعة",
"addCommentsHere": "أضف التعليقات هنا",
"waitForBranchVerification": "يرجى الانتظار حتى يتم التحقق من الفرع."
"waitForBranchVerification": "يرجى الانتظار حتى يتم التحقق من الفرع.",
"reportComplaint": "تقديم شكوى",
"descriptionCannotBeEmpty": "وصف لا يمكن أن يكون فارغًا.",
"adMarkedAsSold": "تم وسم الإعلان كـ 'مباع' بنجاح!",
"chargesAndServiceRangeGreaterThanZero": "يجب أن تكون الرسوم ونطاق الخدمة أكبر من الصفر.",
"cannotSelectAllDaysAsOff": "لا يمكنك اختيار جميع الأيام كأيام عطلة.",
"endDateAfterStartDate": "يجب أن تكون تاريخ النهاية بعد تاريخ البدء.",
"pleaseEnterStartDateFirst": "من فضلك أدخل تاريخ البدء أولاً.",
"endTimeAfterStartTime": "يجب أن يكون وقت الانتهاء بعد وقت البدء.",
"pickedLocationNotice": "سيتم استخدام هذا الموقع لجميع الخدمات المنزلية في هذه الموعد",
"serviceNotProvided": "لسوء الحظ، هذه الخدمة غير متوفرة في الفرع الذي اخترته في هذا الموقع المحدد"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1388,7 +1398,7 @@ static const Map<String,dynamic> en_US = {
"customerCarePrompt": "Got any question? We are here to service. Click here to talk to our customer care right now.",
"callNow": "Call Now",
"condition": "Condition",
"servicesNotAvailableHomeLocation": "Some services are not available on home location.",
"servicesNotAvailableHomeLocation": "This location will be same for all services",
"additionalChargesNotice": "These charges are additional to the actual service charges. For heavy items the charges may vary.",
"selectServiceLocation": "Select Service Location",
"apptOn": "Appt On",
@ -1462,7 +1472,17 @@ static const Map<String,dynamic> en_US = {
"noImagesToShow": "No Images to Show",
"updateGroupServices": "Update Group Services",
"addCommentsHere": "Add comments here",
"waitForBranchVerification": "Please wait for the branch verification."
"waitForBranchVerification": "Please wait for the branch verification.",
"reportComplaint": "Report a complaint",
"descriptionCannotBeEmpty": "Description cannot be empty.",
"adMarkedAsSold": "Ad has been marked as sold successfully!",
"chargesAndServiceRangeGreaterThanZero": "Charges and Service range should be greater than zero.",
"cannotSelectAllDaysAsOff": "You cannot select all days as Off days.",
"endDateAfterStartDate": "End Date should be after start date.",
"pleaseEnterStartDateFirst": "Please enter start date first.",
"endTimeAfterStartTime": "End Time should be after start time.",
"pickedLocationNotice": "This picked location will be used for all home-based services in this appointment",
"serviceNotProvided": "Unfortunately, this service is not provided by your selected branch in this picked location."
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -702,5 +702,15 @@ abstract class LocaleKeys {
static const updateGroupServices = 'updateGroupServices';
static const addCommentsHere = 'addCommentsHere';
static const waitForBranchVerification = 'waitForBranchVerification';
static const reportComplaint = 'reportComplaint';
static const descriptionCannotBeEmpty = 'descriptionCannotBeEmpty';
static const adMarkedAsSold = 'adMarkedAsSold';
static const chargesAndServiceRangeGreaterThanZero = 'chargesAndServiceRangeGreaterThanZero';
static const cannotSelectAllDaysAsOff = 'cannotSelectAllDaysAsOff';
static const endDateAfterStartDate = 'endDateAfterStartDate';
static const pleaseEnterStartDateFirst = 'pleaseEnterStartDateFirst';
static const endTimeAfterStartTime = 'endTimeAfterStartTime';
static const pickedLocationNotice = 'pickedLocationNotice';
static const serviceNotProvided = 'serviceNotProvided';
}

@ -12,3 +12,4 @@ bool disableThingsForQA = true;
// todo terminal command to genertate translation keys
// flutter pub run easy_localization:generate --source-dir ./assets/langs -f keys -o locale_keys.g.dart
// command to generate languages data from json

@ -21,6 +21,7 @@ class ServiceModel {
String providerServiceName;
bool isHomeSelected;
String homeLocation;
double distanceToHomeInKms;
double currentTotalServicePrice;
ServiceModel({
@ -41,6 +42,7 @@ class ServiceModel {
this.serviceItems,
this.isHomeSelected = false,
this.homeLocation = "",
this.distanceToHomeInKms = 0.0,
this.currentTotalServicePrice = 0.0,
required this.isExpandedOrSelected,
required this.providerServiceId,
@ -74,6 +76,7 @@ class ServiceModel {
providerServiceName: "",
isHomeSelected: false,
homeLocation: "",
distanceToHomeInKms: 0.0,
);
Map<String, dynamic> toJson() => {

@ -34,7 +34,7 @@ class User {
Map<String, dynamic> toJson() => {
"totalItemsCount": totalItemsCount,
"data": data == null ? null : data!.toJson(),
"data": data?.toJson(),
"messageStatus": messageStatus,
"message": message,
};
@ -63,8 +63,8 @@ class UserData {
Map<String, dynamic> toJson() => {
"accessToken": accessToken,
"refreshToken": refreshToken,
"expiryDate": expiryDate == null ? null : expiryDate!.toIso8601String(),
"userInfo": userInfo == null ? null : userInfo!.toJson(),
"expiryDate": expiryDate?.toIso8601String(),
"userInfo": userInfo?.toJson(),
};
}
@ -88,6 +88,8 @@ class UserInfo {
this.isDealershipUser,
this.providerId,
this.customerId,
this.countryId,
this.cityId,
this.dealershipId,
this.userLocalImage});
@ -109,6 +111,8 @@ class UserInfo {
bool? isDealershipUser;
dynamic providerId;
int? customerId;
int? cityId;
int? countryId;
dynamic dealershipId;
File? userLocalImage;
@ -140,6 +144,8 @@ class UserInfo {
isDealershipUser = json["isDealershipUser"];
providerId = json["providerID"];
customerId = json["customerID"];
countryId = json["countryId"] ?? 1;
cityId = json["cityId"] ?? 1;
dealershipId = json["dealershipID"];
userLocalImage = null;
}

@ -16,7 +16,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/enums.dart';
abstract class AdsRepo {
Future<List<AdsDurationModel>> getAdsDuration();
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId});
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType});
@ -54,10 +54,14 @@ class AdsRepoImp implements AdsRepo {
AppState appState = injector.get<AppState>();
@override
Future<List<AdsDurationModel>> getAdsDuration() async {
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId}) async {
var param = {
"CountryID": countryId.toString() ?? "0",
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
queryParameters: param,
ApiConsts.vehicleAdsDurationGet,
);
List<AdsDurationModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => AdsDurationModel.fromJson(adsGenericModel.data[index]));
@ -70,7 +74,7 @@ class AdsRepoImp implements AdsRepo {
"SpecialServiceType": specialServiceType.toString(),
};
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params);
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params);
List<SpecialServiceModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index]));
return vehicleAdsDuration;
}
@ -145,7 +149,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
isCreateNew ? ApiConsts.vehicleAdsSingleStepCreate : ApiConsts.vehicleAdsSingleStepUpdate,
postParams,
token: token,
@ -179,7 +183,7 @@ class AdsRepoImp implements AdsRepo {
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet,
queryParameters: isMyAds ? onlyMyAdsParams : allAdsParams,
);
@ -207,7 +211,7 @@ class AdsRepoImp implements AdsRepo {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet,
queryParameters: parameters,
);
@ -223,7 +227,7 @@ class AdsRepoImp implements AdsRepo {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.myAdsReserveGet,
queryParameters: params,
);
@ -245,7 +249,7 @@ class AdsRepoImp implements AdsRepo {
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
queryParameters: params,
ApiConsts.vehicleAdsGet,
);
@ -267,7 +271,7 @@ class AdsRepoImp implements AdsRepo {
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
queryParameters: params,
ApiConsts.vehicleAdsGet,
);
@ -283,7 +287,7 @@ class AdsRepoImp implements AdsRepo {
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
queryParameters: params,
ApiConsts.adsMCBankAccountAdGet,
);
@ -305,7 +309,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsUpdateStatus,
postParams,
token: token,
@ -324,7 +328,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsExtendDurationCreate,
postParams,
token: token,
@ -341,7 +345,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.deleteAd,
postParams,
token: token,
@ -363,7 +367,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.deleteAd,
postParams,
token: token,
@ -384,7 +388,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsReserveCreate,
postParams,
token: token,
@ -412,7 +416,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsPhotoOfficeAppointmentCreate,
postParams,
token: token,
@ -445,7 +449,7 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsPhotoOfficeAppointmentCreate,
postParams,
token: token,
@ -458,7 +462,7 @@ class AdsRepoImp implements AdsRepo {
Future<List<BuyersChatForAdsModel>> getChatBuyersForAds({required int adsID}) async {
var queryParameters = {"AdsID": adsID.toString()};
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getChatBuyersForAds,
queryParameters: queryParameters,
token: appState.getUser.data!.accessToken,

@ -54,6 +54,8 @@ abstract class CommonRepo {
Future<VehicleDetailsModel> getVehicleDetails({int? vehicleTypeId, int? vehicleBrandId});
Future<List<EnumsModel>> getEnumTypeValues({int? enumTypeID, String? enumTypeName});
Future<GenericRespModel> createComplainFromProvider({required int customerId, required String comment, required int complainType});
}
class CommonRepoImp implements CommonRepo {
@ -62,7 +64,7 @@ class CommonRepoImp implements CommonRepo {
@override
Future<Country> getAllCountries() async {
return await apiClient.getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry);
return await apiClient.getJsonForObject((json) => Country.fromJson(json), ApiConsts.getAllCountry);
}
@override
@ -70,12 +72,12 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"CountryID": countryId,
};
return await apiClient.getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams);
return await apiClient.getJsonForObject((json) => Cities.fromJson(json), ApiConsts.getAllCities, queryParameters: postParams);
}
@override
Future<Role> getRoles() async {
return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles);
return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.getProviderRoles);
}
@override
@ -166,7 +168,8 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"VehicleType": vehicleTypeId.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCategoryGet, queryParameters: postParams);
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCategoryGet, queryParameters: postParams);
List<VehicleCategoryModel> vehicleCategories = List.generate(adsGenericModel.data.length, (index) => VehicleCategoryModel.fromJson(adsGenericModel.data[index]));
return vehicleCategories;
}
@ -176,7 +179,8 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"CountryID": countryId.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCityGet, queryParameters: countryId != -1 ? postParams : null);
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCityGet, queryParameters: countryId != -1 ? postParams : null);
List<VehicleCityModel> vehicleCities = List.generate(adsGenericModel.data.length, (index) => VehicleCityModel.fromJson(adsGenericModel.data[index]));
return vehicleCities;
}
@ -186,7 +190,8 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"VehicleType": vehicleTypeId.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleColorGet, queryParameters: postParams);
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleColorGet, queryParameters: postParams);
List<VehicleColorModel> vehicleColors = List.generate(adsGenericModel.data.length, (index) => VehicleColorModel.fromJson(adsGenericModel.data[index]));
return vehicleColors;
}
@ -196,7 +201,8 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"VehicleType": vehicleTypeId.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleConditionGet, queryParameters: postParams);
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleConditionGet, queryParameters: postParams);
List<VehicleConditionModel> vehicleConditions = List.generate(adsGenericModel.data.length, (index) => VehicleConditionModel.fromJson(adsGenericModel.data[index]));
return vehicleConditions;
}
@ -217,7 +223,8 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"VehicleType": vehicleTypeId.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleMileageGet, queryParameters: postParams);
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleMileageGet, queryParameters: postParams);
List<VehicleMileageModel> vehicleMileages = List.generate(adsGenericModel.data.length, (index) => VehicleMileageModel.fromJson(adsGenericModel.data[index]));
return vehicleMileages;
}
@ -338,22 +345,21 @@ class CommonRepoImp implements CommonRepo {
return vehicleParts;
}
//
// @override
// Future<List<ProviderCategoryModel>> getProviderServiceCategories() async {
// GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet);
// List<ProviderCategoryModel> providerCategories = List.generate(adsGenericModel.data.length, (index) => ProviderCategoryModel.fromJson(adsGenericModel.data[index]));
// return providerCategories;
// }
// @override
// Future<List<ProviderServiceModel>> getProviderServices({required int categoryId}) async {
// var postParams = {
// "ServiceCategoryID": categoryId.toString(),
// };
// GenericRespModel adsGenericModel =
// await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet, queryParameters: postParams);
// List<ProviderServiceModel> providerServices = List.generate(adsGenericModel.data.length, (index) => ProviderServiceModel.fromJson(adsGenericModel.data[index]));
// return providerServices;
// }
@override
Future<GenericRespModel> createComplainFromProvider({required int customerId, required String comment, required int complainType}) async {
final providerId = appState.getUser.data!.userInfo!.providerId;
final parameters = {
"serviceProviderID": providerId,
"customerID": customerId,
"detail": comment,
"complaintType": complainType,
};
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.providerComplaintCreate,
parameters,
token: appState.getUser.data!.accessToken,
);
return adsGenericModel;
}
}

@ -125,7 +125,7 @@ class UserRepoImp implements UserRepo {
"mobileorEmail": phoneNo,
"password": password,
};
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.Login_V1, postParams);
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.loginV1, postParams);
//return await injector.get<ApiClient>().postJsonForObject((json) => BasicOtp.fromJson(json), ApiConsts.Login_V1, postParams);
}
@ -136,7 +136,7 @@ class UserRepoImp implements UserRepo {
"loginType": loginType,
};
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.Login_V2_OTP, postParams);
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.loginV2OTP, postParams);
LoginPasswordRespModel user = LoginPasswordRespModel.fromJson(jsonDecode(response.body));
return user;
}
@ -149,7 +149,7 @@ class UserRepoImp implements UserRepo {
String deviceToken,
) async {
var postParams = {"userToken": userToken, "userOTP": otp, "deviceType": deviceType, "deviceToken": deviceToken};
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.Login_V2_OTPVerify, postParams);
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.loginV2OTPVerify, postParams);
}
@override
@ -161,7 +161,7 @@ class UserRepoImp implements UserRepo {
@override
Future<Country> getAllCountries() async {
return await injector.get<ApiClient>().getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry);
return await injector.get<ApiClient>().getJsonForObject((json) => Country.fromJson(json), ApiConsts.getAllCountry);
}
@override
@ -169,12 +169,12 @@ class UserRepoImp implements UserRepo {
var postParams = {
"CountryID": countryId,
};
return await injector.get<ApiClient>().getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams);
return await injector.get<ApiClient>().getJsonForObject((json) => Cities.fromJson(json), ApiConsts.getAllCities, queryParameters: postParams);
}
@override
Future<Role> getRoles() async {
return await injector.get<ApiClient>().getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles);
return await injector.get<ApiClient>().getJsonForObject((json) => Role.fromJson(json), ApiConsts.getProviderRoles);
}
@override
@ -183,14 +183,14 @@ class UserRepoImp implements UserRepo {
"userName": userName,
"otpType": 1,
};
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ForgetPasswordOTPRequest, postParams);
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.forgetPasswordOTPRequest, postParams);
//return await injector.get<ApiClient>().postJsonForObject((json) => PasswordOTPRequest.fromJson(json), ApiConsts.ForgetPasswordOTPRequest, postParams);
}
@override
Future<PasswordOTPCompareResModel> forgetPasswordOTPCompare(String userToken, String userOTP) async {
var postParams = {"userToken": userToken, "userOTP": userOTP};
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ForgetPasswordOTPCompare, postParams);
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.forgetPasswordOTPCompare, postParams);
PasswordOTPCompareResModel otpCompare = PasswordOTPCompareResModel.fromJson(jsonDecode(response.body));
return otpCompare;
@ -203,7 +203,7 @@ class UserRepoImp implements UserRepo {
"newPassword": newPassword,
};
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ForgetPassword, postParams);
Response response = await injector.get<ApiClient>().postJsonForResponse(ApiConsts.forgetPassword, postParams);
ConfirmPasswordRespModel data = ConfirmPasswordRespModel.fromJson(jsonDecode(response.body));
return data;
@ -220,14 +220,14 @@ class UserRepoImp implements UserRepo {
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.ChangePassword, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.changePassword, postParams, token: t);
}
@override
Future<ChangeMobileRespModel> changeMobileNoOTPRequest(countryID, String mobileNo, String password) async {
var postParams = {"countryID": 1, "mobileNo": mobileNo, "password": password};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => ChangeMobileRespModel.fromJson(json), ApiConsts.ChangeMobileNoOTPRequest, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => ChangeMobileRespModel.fromJson(json), ApiConsts.changeMobileNoOTPRequest, postParams, token: t);
}
@override
@ -237,21 +237,21 @@ class UserRepoImp implements UserRepo {
"userOTP": userOTP,
};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => ConfirmMobileRespModel.fromJson(json), ApiConsts.ChangeMobileNo, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => ConfirmMobileRespModel.fromJson(json), ApiConsts.changeMobileNo, postParams, token: t);
}
@override
Future<ChanEmailRespModel> changeEmailOTPRequest(String email, String password) async {
var postParams = {"email": email, "password": password};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => ChanEmailRespModel.fromJson(json), ApiConsts.ChangeEmailOTPRequest, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => ChanEmailRespModel.fromJson(json), ApiConsts.changeEmailOTPRequest, postParams, token: t);
}
@override
Future<ConfirmEmailRespModel> changeEmail(String userToken, String userOTP) async {
var postParams = {"userToken": userToken, "userOTP": userOTP};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => ConfirmEmailRespModel.fromJson(json), ApiConsts.ChangeEmail, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => ConfirmEmailRespModel.fromJson(json), ApiConsts.changeEmail, postParams, token: t);
}
@override
@ -264,7 +264,7 @@ class UserRepoImp implements UserRepo {
};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => VerifyEmailRespModel.fromJson(json), ApiConsts.EmailVerify, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => VerifyEmailRespModel.fromJson(json), ApiConsts.emailVerify, postParams, token: t);
}
@override
@ -272,7 +272,7 @@ class UserRepoImp implements UserRepo {
var postParams = {"userToken": userToken, "userOTP": userOTP};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.EmailVerifyOTPVerify, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.emailVerifyOTPVerify, postParams, token: t);
}
@override
@ -284,7 +284,7 @@ class UserRepoImp implements UserRepo {
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject(
(json) => ImageResponse.fromJson(json),
ApiConsts.UpdateUserImage,
ApiConsts.updateUserImage,
postParams,
token: t,
);
@ -297,7 +297,7 @@ class UserRepoImp implements UserRepo {
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.updateUserImage, postParams, token: t);
}
@override
@ -319,6 +319,6 @@ class UserRepoImp implements UserRepo {
Future<Response> logoutUser() async {
String t = AppState().getUser.data!.accessToken ?? "";
var postParams = {"token": AppState().getUser.data!.accessToken ?? ""};
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.LogoutUser, postParams, token: t);
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.logoutUser, postParams, token: t);
}
}

@ -103,7 +103,7 @@ class CommonServicesImp implements CommonAppServices {
destLongitude,
);
return distance ?? 0.0;
return (distance / 1000) ?? 0.0;
} catch (e) {
logger.e(e.toString());
return 0.0;

@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class DateHelper {
@ -50,3 +51,44 @@ class DateHelper {
return formatter.format(date);
}
}
extension TimeOfDayUtils on TimeOfDay {
bool isAfter(TimeOfDay other) {
final thisTime = DateTime(0, 1, 1, hour, minute);
final otherTime = DateTime(0, 1, 1, other.hour, other.minute);
return thisTime.isAfter(otherTime);
}
bool isBefore(TimeOfDay other) {
final thisTime = DateTime(0, 1, 1, hour, minute);
final otherTime = DateTime(0, 1, 1, other.hour, other.minute);
return thisTime.isBefore(otherTime);
}
static TimeOfDay convertStringToTimeOfDay(String timeString) {
bool is12HourFormat = timeString.contains(RegExp(r'AM|PM', caseSensitive: false));
int hour;
int minute;
if (is12HourFormat) {
List<String> parts = timeString.split(' '); // Split time and AM/PM part
List<String> timeParts = parts[0].split(':'); // Split hours and minutes
hour = int.parse(timeParts[0]);
minute = int.parse(timeParts[1]);
if (parts[1].toUpperCase() == 'PM' && hour != 12) {
hour += 12;
} else if (parts[1].toUpperCase() == 'AM' && hour == 12) {
hour = 0;
}
} else {
List<String> timeParts = timeString.split(':');
hour = int.parse(timeParts[0]);
minute = int.parse(timeParts[1]);
}
return TimeOfDay(hour: hour, minute: minute);
}
}

@ -63,6 +63,7 @@ enum AdPostStatus {
buyingService,
reserveCancel,
deActive,
pendingForActive,
allAds,
}

@ -30,13 +30,7 @@ class Utils {
static void showToast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 2,
backgroundColor: Colors.black54,
textColor: Colors.white,
fontSize: 16.0);
msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
}
static Future<void> openNumberViaCaller({required String phoneNumber}) async {
@ -69,10 +63,10 @@ class Utils {
await launchUrlString(url, mode: LaunchMode.externalApplication);
}
static Future<String> pickDateFromDatePicker(BuildContext context, {DateTime? firstDate, DateTime? lastDate}) async {
static Future<String> pickDateFromDatePicker(BuildContext context, {DateTime? initial, DateTime? firstDate, DateTime? lastDate}) async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(), //get today's date
initialDate: initial ?? DateTime.now(), //get today's date
firstDate: firstDate ?? DateTime.now(), //DateTime.now() - not to allow to choose before today.
lastDate: lastDate ?? DateTime(2101));
@ -85,17 +79,16 @@ class Utils {
}
static Future<String> pickTime(BuildContext context, {TimeOfDay? initialTime}) async {
TimeOfDay? timeOfDay = await showTimePicker(context: context, initialTime: initialTime ?? TimeOfDay.now());
TimeOfDay? timeOfDay = await showTimePicker(
context: context,
initialTime: initialTime ?? TimeOfDay.now(),
);
if (timeOfDay == null) {
return "";
}
return ("${timeOfDay.hour
.toString()
.length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute
.toString()
.length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
return ("${timeOfDay.hour.toString().length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute.toString().length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
}
static dynamic getNotNullValue(List<dynamic> list, int index) {
@ -231,6 +224,7 @@ class Utils {
return MyColors.adCancelledStatusColor;
case AdPostStatus.pendingForPost:
case AdPostStatus.pendingForActive:
return MyColors.inProgressColor;
case AdPostStatus.active:
@ -546,7 +540,7 @@ class Utils {
border: Border.all(
width: w, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -569,7 +563,7 @@ class Utils {
border: Border.all(
width: 1, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -587,8 +581,7 @@ class Utils {
}
static String getAdsPaymentBrowserForm({required int paymentId, required int adId}) {
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts
.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
}
// BOTTOM SHEETS

@ -297,7 +297,8 @@ class AdVM extends BaseVM {
}
Future<void> getVehicleAdsDuration() async {
vehicleAdsDurations = await adsRepo.getAdsDuration();
final countryId = AppState().getUser.data!.userInfo!.countryId;
vehicleAdsDurations = await adsRepo.getAdsDuration(countryId: countryId);
notifyListeners();
}
@ -329,7 +330,7 @@ class AdVM extends BaseVM {
return;
}
Utils.hideLoading(context);
Utils.showToast(respModel.message ?? "Ad has been marked as sold successfully!");
Utils.showToast(respModel.message ?? LocaleKeys.adMarkedAsSold.tr());
updateIsExploreAds(false);
applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.sold); //pending for review
navigateReplaceWithName(context, AppRoutes.dashboard);
@ -723,7 +724,6 @@ class AdVM extends BaseVM {
SelectionModel vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateVehicleAdDurationId(SelectionModel id) {
log("vehicleAdDurationId is updated: ${vehicleAdDurationId.selectedId}");
vehicleAdDurationId = id;
notifyListeners();
}

@ -38,9 +38,11 @@ import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/views/appointments/book_appointment_schedules_view.dart';
import 'package:mc_common_app/views/appointments/widgets/appointment_service_pick_bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.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:easy_localization/easy_localization.dart';
@ -81,6 +83,7 @@ class AppointmentsVM extends BaseVM {
bool ifItemAlreadySelected(int id) {
int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id);
log("already selected at: $indexFound");
if (indexFound != -1) {
return true;
}
@ -101,6 +104,7 @@ class AppointmentsVM extends BaseVM {
}
resetCategorySelectionBottomSheet();
notifyListeners();
}
}
@ -248,16 +252,16 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
String pickedHomeLocation = "";
void updatePickedHomeLocation(String value) {
pickedHomeLocation = value;
pickHomeLocationError = "";
if (currentServiceSelection != null) {
currentServiceSelection!.homeLocation = value;
}
notifyListeners();
}
// String pickedHomeLocation = "";
//
// void updatePickedHomeLocation(String value) {
// pickedHomeLocation = value;
// pickHomeLocationError = "";
// if (currentServiceSelection != null) {
// currentServiceSelection!.homeLocation = value;
// }
// notifyListeners();
// }
SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
@ -272,10 +276,23 @@ class AppointmentsVM extends BaseVM {
List<ServiceModel> servicesInCurrentAppointment = [];
ServiceModel? currentServiceSelection;
CurrentLocationInfoModel? currentLocationInfoModel;
void updateCurrentLocationInfoModel(CurrentLocationInfoModel? value) {
currentLocationInfoModel = value;
pickHomeLocationError = "";
if (currentServiceSelection != null && value != null) {
currentServiceSelection!.homeLocation = value.address;
}
notifyListeners();
}
void updateBranchServiceId(SelectionModel id) async {
branchSelectedServiceId = id;
currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId);
if (currentLocationInfoModel != null) {
currentLocationInfoModel!.homeChargesInCurrentService = double.parse(currentServiceSelection!.rangePricePerKm ?? "0.0");
}
log("currentServiceSelection isAllowAppointmentHome: ${currentServiceSelection!.isAllowAppointmentHome}");
log("currentServiceSelection serviceDescription: ${currentServiceSelection!.serviceDescription}");
notifyListeners();
@ -308,6 +325,7 @@ class AppointmentsVM extends BaseVM {
}
servicesInCurrentAppointment.clear();
servicesInCurrentAppointment = [];
currentLocationInfoModel = null;
log("here servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
}
@ -547,6 +565,7 @@ class AppointmentsVM extends BaseVM {
double amountToPayForAppointment = 0.0;
double totalAmount = 0.0;
double totalLocationCharges = 0.0;
List<ItemData> serviceItemsFromApi = [];
@ -557,42 +576,35 @@ class AppointmentsVM extends BaseVM {
void onItemUpdateOrSelected(int index, bool selected, int itemId) {
int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
// log("currentServiceSelection!.allSelectedItemsInAppointments: ${allSelectedItemsInAppointments.length}");
// log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
// log("index: $index");
// log("selected: $selected");
// log("itemId: $itemId");
// log("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
serviceItemsFromApi[index].isUpdateOrSelected = selected;
serviceItemsFromApi[index].isHomeSelected = isHomeTapped;
log(" serviceItemsFromApi[index].isHomeSelected: ${serviceItemsFromApi[index].isHomeSelected}");
log(" serviceIndex: $serviceIndex");
if (selected) {
selectedSubServicesCounter = selectedSubServicesCounter + 1;
selectSubServicesError = "";
currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]);
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
// for (var element in allSelectedItemsInAppointments) {
if (!ifItemAlreadySelected(serviceItemsFromApi[index].id!)) {
currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]);
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
log("Here with: ${serviceItemsFromApi[index].description}");
if (serviceIndex != -1) {
servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
// servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0");
}
}
// }
} else {
// log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
selectedSubServicesCounter = selectedSubServicesCounter - 1;
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
// log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
allSelectedItemsInAppointments.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);
if (servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice < 0.0) {
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice * -1;
}
// servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
}
}
@ -614,9 +626,11 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.busy);
serviceItemsFromApi.clear();
serviceItemsFromApi = await branchRepo.getServiceItems(serviceId);
selectedSubServicesCounter = 0;
for (var item in serviceItemsFromApi) {
if (ifItemAlreadySelected(item.id!)) {
item.isUpdateOrSelected = true;
selectedSubServicesCounter++;
}
}
setState(ViewState.idle);
@ -639,7 +653,7 @@ class AppointmentsVM extends BaseVM {
}
if (isHomeTapped) {
if (pickedHomeLocation == "") {
if (currentLocationInfoModel == null || currentLocationInfoModel!.address == "") {
updatePickHomeLocationError(GlobalConsts.homeLocationEmptyError);
return false;
}
@ -683,8 +697,7 @@ class AppointmentsVM extends BaseVM {
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
// TODO: It should be calculated from API
double totalKms = 15.3;
double totalKms = double.parse(selectedService.distanceToHomeInKms.toStringAsFixed(2));
return InfoBottomSheet(
title: LocaleKeys.chargesBreakdown.tr().toText(fontSize: 24, isBold: true),
description: Column(
@ -723,7 +736,7 @@ class AppointmentsVM extends BaseVM {
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${(double.parse(selectedService.rangePricePerKm!)) * totalKms} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
"${((double.parse(selectedService.rangePricePerKm!)) * totalKms).toStringAsFixed(2)} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
],
),
],
@ -736,7 +749,7 @@ class AppointmentsVM extends BaseVM {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(selectedService.isHomeSelected
? "${(selectedService.currentTotalServicePrice) + ((double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms))}"
? ((selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)).toStringAsFixed(2)
: "${selectedService.currentTotalServicePrice}")
.toText(fontSize: 29, isBold: true),
2.width,
@ -813,10 +826,20 @@ class AppointmentsVM extends BaseVM {
return;
}
totalAmount = 0.0;
totalLocationCharges = 0.0;
amountToPayForAppointment = 0.0;
for (var schedule in serviceAppointmentScheduleList) {
amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0);
totalAmount = totalAmount + (schedule.amountTotal ?? 0.0);
for (var service in schedule.servicesListInAppointment!) {
int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceProviderServiceId == service.serviceProviderServiceId);
if (index != -1) {
if (servicesInCurrentAppointment[index].isHomeSelected) {
totalAmount = totalAmount + ((servicesInCurrentAppointment[index].distanceToHomeInKms) * double.parse(servicesInCurrentAppointment[index].rangePricePerKm!));
totalLocationCharges = totalLocationCharges + (servicesInCurrentAppointment[index].distanceToHomeInKms * double.parse(servicesInCurrentAppointment[index].rangePricePerKm!));
}
}
}
}
Utils.hideLoading(context);
@ -890,7 +913,90 @@ class AppointmentsVM extends BaseVM {
}
}
// BRANCHES RELATED
// REPORT A COMPLAINT
String complaintDescription = "";
String complaintDescriptionError = "";
void updateComplaintDescription(String value) {
complaintDescription = value;
if (value.isNotEmpty) {
complaintDescriptionError = "";
}
}
Future buildComplaintBottomSheet({required int customerID, required int complainType, required String customerName, required BuildContext context}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
title: LocaleKeys.reportComplaint.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (customerName.isNotEmpty) ...[
("${LocaleKeys.customerName.tr()}: $customerName").toText(fontSize: 15, color: MyColors.lightTextColor),
],
10.height,
TxtField(
maxLines: 5,
value: complaintDescription,
errorValue: complaintDescriptionError,
keyboardType: TextInputType.text,
hint: LocaleKeys.description.tr(),
onChanged: (v) => updateComplaintDescription(v),
),
25.height,
ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () async {
if (complaintDescription.isEmpty) {
Utils.showToast(LocaleKeys.descriptionCannotBeEmpty.tr());
return;
}
final status = await reportComplaintAgainstCustomer(
customerID: customerID,
comment: complaintDescription,
complaintType: complainType, // 1 for Appointment and 2 for Requests
context: context,
);
if (status) {
updateComplaintDescription("");
pop(context);
}
},
maxWidth: double.infinity,
),
19.height,
],
),
),
);
},
);
}
Future<bool> reportComplaintAgainstCustomer({required int customerID, required String comment, required int complaintType, required BuildContext context}) async {
Utils.showLoading(context);
try {
GenericRespModel genericRespModel = await commonRepo.createComplainFromProvider(customerId: customerID, comment: comment, complainType: complaintType);
Utils.showToast(genericRespModel.message.toString());
Utils.hideLoading(context);
return genericRespModel.messageStatus == 1;
} catch (e, s) {
logger.e(s);
Utils.hideLoading(context);
Utils.showToast(e.toString());
return false;
}
}
// BRANCHES RELATED
List<BranchDetailModel> nearbyBranches = [];
List<BranchDetailModel> myRecentBranches = [];
@ -960,7 +1066,6 @@ class AppointmentsVM extends BaseVM {
Future<void> getBranchServices({required int categoryId}) async {
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
pickedHomeLocation = "";
pickHomeLocationError = "";
if (categoryId != -1) {
isFetchingServices = true;
@ -1643,3 +1748,19 @@ class AppointmentsVM extends BaseVM {
// }
}
}
class CurrentLocationInfoModel {
final String address;
final double latitude;
final double longitude;
final double distanceFromCurrent;
double homeChargesInCurrentService;
CurrentLocationInfoModel({
required this.address,
required this.latitude,
required this.longitude,
required this.distanceFromCurrent,
required this.homeChargesInCurrentService,
});
}

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/main.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/utils/enums.dart';
class BaseVM extends ChangeNotifier {

@ -1047,6 +1047,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
case AdPostStatus.cancelled:
return pendingForReviewAction(pendingText: LocaleKeys.cancelledByOwner.tr());
case AdPostStatus.pendingForPost:
case AdPostStatus.pendingForActive:
return pendingForReviewAction(pendingText: LocaleKeys.waitingAdminPost.tr());
case AdPostStatus.pendingForReview:

@ -2,12 +2,15 @@ import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
@ -60,7 +63,25 @@ class BookAppointmentServicesView extends StatelessWidget {
Row(
children: [
Expanded(child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true)),
MyAssets.closeWithOrangeBg.buildSvg(height: 30, width: 30).onPress(() => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex))
Row(
children: [
MyAssets.icEdit.buildSvg(height: 17, width: 17).onPress(() {
log("serviceId: ${serviceData.serviceProviderServiceId}");
appointmentsVM.updateBranchServiceId(
SelectionModel(
selectedId: serviceData.serviceProviderServiceId!,
selectedOption: serviceData.serviceDescription ?? "",
itemPrice: "",
),
);
appointmentsVM.getServiceItems(serviceData.serviceProviderServiceId!);
navigateWithName(context, AppRoutes.bookAppointmentsItemView);
}),
10.width,
MyAssets.closeWithOrangeBg.buildSvg(height: 30, width: 30).onPress(() => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex)),
],
),
],
),
if (true) ...[
@ -89,7 +110,12 @@ class BookAppointmentServicesView extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
((serviceData.currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true),
if (serviceData.isHomeSelected) ...[
((serviceData.currentTotalServicePrice + (serviceData.distanceToHomeInKms * double.parse(serviceData.rangePricePerKm!))).toStringAsFixed(2))
.toText(fontSize: 32, isBold: true),
] else ...[
((serviceData.currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true),
],
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
const Icon(Icons.arrow_drop_down, size: 30)

@ -65,9 +65,9 @@ class BookAppointmentsItemView extends StatelessWidget {
],
).horPaddingMain(),
appointmentsVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
? const Expanded(child: Center(child: CircularProgressIndicator()))
: appointmentsVM.serviceItemsFromApi.isEmpty
? Expanded(child: Center(child: LocaleKeys.noAvailableItems.toText(fontSize: 16, color: MyColors.lightTextColor)))
? Expanded(child: Center(child: LocaleKeys.noAvailableItems.tr().toText(fontSize: 16, color: MyColors.lightTextColor)))
: ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: appointmentsVM.serviceItemsFromApi.length,

@ -206,6 +206,7 @@ class ReviewAppointment extends StatelessWidget {
AppointmentsVM appointmentsVM = context.read<AppointmentsVM>();
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: appointmentsVM.serviceAppointmentScheduleList.length,
itemBuilder: (BuildContext context, int scheduleIndex) {
ServiceAppointmentScheduleModel scheduleData = appointmentsVM.serviceAppointmentScheduleList[scheduleIndex];
@ -223,7 +224,7 @@ class ReviewAppointment extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListView.separated(
// physics: const NeverScrollableScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: scheduleData.servicesListInAppointment!.length,
itemBuilder: (BuildContext context, int serviceIndex) {
@ -295,10 +296,14 @@ class ReviewAppointment extends StatelessWidget {
10.height,
const Divider(thickness: 0.7),
Builder(builder: (BuildContext context) {
//TODO: THIS SHOULD BE FINALIZED FROM API
double totalServicePrice = 0.0;
double totalKms = 15.3;
double rangePricePerKm = 5;
double totalKms = 0.0;
double rangePricePerKm = 0;
if (appointmentsVM.currentLocationInfoModel != null) {
totalKms = appointmentsVM.currentLocationInfoModel!.distanceFromCurrent;
rangePricePerKm = appointmentsVM.currentLocationInfoModel!.homeChargesInCurrentService;
}
totalServicePrice = rangePricePerKm * totalKms;
return Column(
@ -316,8 +321,9 @@ class ReviewAppointment extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${LocaleKeys.locationCharges.tr()} ($rangePricePerKm x $totalKms )").toText(fontSize: 14, color: MyColors.lightTextColor),
("${totalServicePrice.toString()} ${LocaleKeys.sar.tr()}").toText(fontSize: 16, isBold: true),
("${LocaleKeys.locationCharges.tr()} (${rangePricePerKm.toStringAsFixed(2)} x ${totalKms.toStringAsFixed(2)} )")
.toText(fontSize: 14, color: MyColors.lightTextColor),
("${totalServicePrice.toStringAsFixed(2)} ${LocaleKeys.sar.tr()}").toText(fontSize: 16, isBold: true),
],
),
],
@ -369,7 +375,7 @@ class ReviewAppointment extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(appointmentsVM.totalAmount - appointmentsVM.amountToPayForAppointment).toString().toText(fontSize: 16, isBold: true),
(appointmentsVM.totalAmount - appointmentsVM.amountToPayForAppointment).toStringAsFixed(2).toText(fontSize: 16, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 2),
],
@ -384,7 +390,7 @@ class ReviewAppointment extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
appointmentsVM.totalAmount.toString().toText(fontSize: 29, isBold: true),
appointmentsVM.totalAmount.toStringAsFixed(2).toText(fontSize: 29, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
],
@ -436,6 +442,7 @@ class ReviewAppointment extends StatelessWidget {
buildServicesInfoCard(context: context),
10.height,
buildPersonalInformationCard(context: context),
20.height,
],
).expand(),
buildNextButtonFooter(context: context),

@ -1,10 +1,15 @@
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/config/dependency_injection.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
@ -18,7 +23,7 @@ import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class AppointmentServicePickBottomSheet extends StatelessWidget {
const AppointmentServicePickBottomSheet({Key? key}) : super(key: key);
const AppointmentServicePickBottomSheet({super.key});
@override
Widget build(BuildContext context) {
@ -50,7 +55,9 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
(DropValue value) => appointmentsVM.updateProviderCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
list: appointmentsVM.branchCategories,
hint: LocaleKeys.selectCategory.tr(),
dropdownValue: appointmentsVM.branchSelectedCategoryId.selectedId != -1 ? DropValue(appointmentsVM.branchSelectedCategoryId.selectedId, appointmentsVM.branchSelectedCategoryId.selectedOption, "") : null,
dropdownValue: appointmentsVM.branchSelectedCategoryId.selectedId != -1
? DropValue(appointmentsVM.branchSelectedCategoryId.selectedId, appointmentsVM.branchSelectedCategoryId.selectedOption, "")
: null,
);
},
),
@ -78,7 +85,9 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
(DropValue value) => appointmentsVM.updateBranchServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
list: serviceCategories,
hint: LocaleKeys.selectService.tr(),
dropdownValue: appointmentsVM.branchSelectedServiceId.selectedId != -1 ? DropValue(appointmentsVM.branchSelectedServiceId.selectedId, appointmentsVM.branchSelectedServiceId.selectedOption, "") : null,
dropdownValue: appointmentsVM.branchSelectedServiceId.selectedId != -1
? DropValue(appointmentsVM.branchSelectedServiceId.selectedId, appointmentsVM.branchSelectedServiceId.selectedOption, "")
: null,
);
},
),
@ -91,6 +100,10 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
children: [
Expanded(
child: ShowFillButton(
borderColor: !(appointmentsVM.currentServiceSelection != null && (appointmentsVM.currentServiceSelection!.isAllowAppointmentHome ?? false))
? Colors.transparent
: MyColors.darkPrimaryColor,
isDisabled: !(appointmentsVM.currentServiceSelection != null && (appointmentsVM.currentServiceSelection!.isAllowAppointmentHome ?? false)),
isFilled: appointmentsVM.isHomeTapped,
maxHeight: 48,
title: LocaleKeys.home.tr(),
@ -117,11 +130,11 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
],
),
if (appointmentsVM.isHomeTapped) ...[
8.height,
12.height,
TxtField(
hint: LocaleKeys.pickLocation.tr(),
errorValue: appointmentsVM.pickHomeLocationError,
value: appointmentsVM.pickedHomeLocation,
value: appointmentsVM.currentLocationInfoModel == null ? "" : appointmentsVM.currentLocationInfoModel!.address,
isNeedClickAll: true,
postfixData: Icons.add_location_outlined,
postFixDataColor: MyColors.darkPrimaryColor,
@ -129,9 +142,35 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
navigateTo(
context,
PickLocationPage(
onPickAddress: (double latitude, double longitude, String address) {
appointmentsVM.updatePickedHomeLocation(address);
onPickAddress: (double latitude, double longitude, String address) async {
appointmentsVM.setState(ViewState.idle);
double distance = injector.get<CommonAppServices>().getDistanceBetween(
curLatitude: double.parse(appointmentsVM.selectedBranchModel!.latitude!),
curLongitude: double.parse(appointmentsVM.selectedBranchModel!.longitude!),
destLatitude: latitude,
destLongitude: longitude,
);
if (distance > (appointmentsVM.currentServiceSelection!.customerLocationRange ?? 0)) {
Utils.showToast(LocaleKeys.serviceNotProvided.tr());
appointmentsVM.updateCurrentLocationInfoModel(null);
return;
}
log("distance: $distance");
log("customerLocationRange : ${appointmentsVM.currentServiceSelection!.customerLocationRange}");
if (appointmentsVM.currentServiceSelection != null) {
appointmentsVM.currentServiceSelection!.distanceToHomeInKms = distance;
}
CurrentLocationInfoModel temp = CurrentLocationInfoModel(
address: address,
latitude: latitude,
longitude: longitude,
distanceFromCurrent: distance,
homeChargesInCurrentService: double.parse(appointmentsVM.currentServiceSelection!.rangePricePerKm ?? "0.0"),
);
appointmentsVM.updateCurrentLocationInfoModel(temp);
},
),
);
@ -139,11 +178,11 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
),
14.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Icon(Icons.warning, color: MyColors.adPendingStatusColor, size: 19).paddingOnly(bottom: 2),
3.width,
LocaleKeys.servicesNotAvailableHomeLocation.tr().toText(color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true),
Flexible(child: LocaleKeys.pickedLocationNotice.tr().toText(color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true)),
],
),
]
@ -155,14 +194,28 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
width: double.infinity,
child: Column(
children: [
if (appointmentsVM.isHomeTapped && !appointmentsVM.isFetchingServices && appointmentsVM.currentServiceSelection != null && (appointmentsVM.currentServiceSelection!.isAllowAppointmentHome ?? false)) ...[
if (appointmentsVM.isHomeTapped &&
!appointmentsVM.isFetchingServices &&
appointmentsVM.currentServiceSelection != null &&
(appointmentsVM.currentServiceSelection!.isAllowAppointmentHome ?? false)) ...[
const Divider(thickness: 1, height: 1),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// TODO: This Price will be decided according to the service selected, We will calculate the KMs and multiple it with price per KMs
appointmentsVM.currentServiceSelection!.rangePricePerKm.toString().toText(fontSize: 30, isBold: true),
"${LocaleKeys.sar.tr()}/km".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
if (appointmentsVM.currentLocationInfoModel == null) ...[
appointmentsVM.currentServiceSelection!.rangePricePerKm.toString().toText(fontSize: 30, isBold: true),
"${LocaleKeys.sar.tr()}/km".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
] else ...[
(appointmentsVM.currentLocationInfoModel!.homeChargesInCurrentService * appointmentsVM.currentLocationInfoModel!.distanceFromCurrent).toStringAsFixed(2).toText(
fontSize: 30,
isBold: true,
),
LocaleKeys.sar.tr().toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
10.width,
("(${(appointmentsVM.currentLocationInfoModel!.homeChargesInCurrentService).toStringAsFixed(2)} ${LocaleKeys.sar.tr()} x ${appointmentsVM.currentLocationInfoModel!.distanceFromCurrent.toStringAsFixed(2)} KMs )")
.toText(fontSize: 13, color: MyColors.lightTextColor)
.paddingOnly(bottom: 5),
],
],
),
LocaleKeys.additionalChargesNotice.tr().toText(fontSize: 12, color: MyColors.lightTextColor),

@ -155,7 +155,12 @@ class MyRequestsFragment extends StatelessWidget {
cancelRequestBottomSheet(context, requestsVM.myFilteredRequests[index].id);
return;
},
child: RequestItem(request: requestsVM.myFilteredRequests[index], appType: AppState().currentAppType, requestIndex: index),
child: RequestItem(
request: requestsVM.myFilteredRequests[index],
appType: AppState().currentAppType,
requestIndex: index,
shouldShowStatuses: AppState().currentAppType == AppType.customer,
),
);
},
separatorBuilder: (context, index) {

@ -8,6 +8,7 @@ import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.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';
@ -24,9 +25,13 @@ class RequestDetailPage extends StatelessWidget {
const RequestDetailPage({super.key, required this.requestDetailPageArguments});
Widget buildRequestDetailActionFooter(
{required int requestId, required RequestStatusEnum requestStatus, required RequestsTypeEnum requestTypeEnum, required String statusText, required BuildContext context}) {
// final requestsVM = context.read<RequestsVM>();
Widget buildRequestDetailActionFooter({
required int requestId,
required RequestStatusEnum requestStatus,
required RequestsTypeEnum requestTypeEnum,
required String statusText,
required BuildContext context,
}) {
switch (requestStatus) {
case RequestStatusEnum.submitted:
return ShowFillButton(
@ -213,6 +218,30 @@ class RequestDetailPage extends StatelessWidget {
],
showItem("${LocaleKeys.description.tr()}: ", requestDetail.description),
16.height,
if (AppState().currentAppType == AppType.provider &&
(requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.inProgress || requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.submitted)) ...[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
("${LocaleKeys.reportComplaint.tr()}?").toText(fontSize: 14, color: MyColors.darkTextColor),
],
).onPress(
() {
int customerID = requestDetailPageArguments.requestModel.customerId;
int complainType = 2;
String customerName = requestDetailPageArguments.requestModel.customerName;
context.read<AppointmentsVM>().buildComplaintBottomSheet(
customerID: customerID,
customerName: customerName,
complainType: complainType,
context: context,
);
},
),
],
// showItem("${LocaleKeys.priceRange.tr()}:", ""),
// Row(
// children: [

@ -20,28 +20,44 @@ class RequestItem extends StatelessWidget {
final RequestModel request;
final AppType appType;
final int requestIndex;
final bool shouldShowStatuses;
const RequestItem({super.key, required this.request, required this.appType, required this.requestIndex});
const RequestItem({super.key, required this.request, required this.appType, required this.requestIndex, this.shouldShowStatuses = true});
@override
Widget build(BuildContext context) {
String imageUrl = "";
if (request.requestImages != null && request.requestImages!.isNotEmpty) {
imageUrl = request.requestImages!.first.imageUrl ?? "";
}
return Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
imageUrl.buildNetworkImage(
width: 80,
height: 80,
fit: BoxFit.cover,
),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(text: request.requestStatusName.toLowerCase() == "InProgress".toLowerCase() ? "In Progress" : request.requestStatusName, chipColor: Utils.getChipColorByRequestStatus(request.requestStatus)),
if (shouldShowStatuses) ...[
Utils.statusContainerChip(
text: request.requestStatusName.toLowerCase() == "InProgress".toLowerCase() ? "In Progress" : request.requestStatusName,
chipColor: Utils.getChipColorByRequestStatus(request.requestStatus)),
],
6.height,
"${request.brand} ${request.model} | ${request.id}".toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.year.tr()}:", "${request.year}"),
if (request.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}:", request.customerName),
],
showItem("${LocaleKeys.description.tr()}:", request.description),
],
),
),
@ -72,7 +88,6 @@ class RequestItem extends StatelessWidget {
)
],
),
showItem("${LocaleKeys.description.tr()}:", request.description),
// showItem("${LocaleKeys.priceRange.tr()}: ", ""),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,

Loading…
Cancel
Save