bug fixing

faiz_development_common
Faiz Hashmi 1 day ago
parent 9c4df54156
commit 9bdb105212

@ -0,0 +1,63 @@
# View-Only Mode: CustomerID Parameter Exclusion
## Summary
Updated all API calls to exclude `customerID` parameter when `AppState().getIsViewOnly` is `true`.
## Files Modified
### 1. **request_repo.dart**
- ✅ `createRequest()` - Excludes customerID in view-only mode
- ✅ `getRequests()` - Excludes customerID for customer app type in view-only mode
- ✅ `getRequestBasedOnFilters()` - Excludes customerID for customer app type in view-only mode
- ✅ `getOffersFromProvidersByRequest()` - Excludes customerID in view-only mode
### 2. **ads_repo.dart**
- ✅ `cancelMyAdReservation()` - Excludes customerID in view-only mode
- ✅ `createReserveAd()` - Excludes customerID in view-only mode
- ✅ `uploadBankReceiptsOnReserveDealDone()` - Excludes customerID in view-only mode
### 3. **appointment_repo.dart**
- ✅ `createAppointmentsMulti()` - Excludes customerID in view-only mode
- ✅ `getMyAppointmentsForCustomersByFilters()` - Excludes customerID in view-only mode
### 4. **branch_repo.dart**
- ✅ `submitBranchRatings()` - Excludes customerID in view-only mode
- ✅ `addProviderToFavourite()` - Excludes customerID in view-only mode
- ✅ `getMyFavoriteProviders()` - Excludes customerID in view-only mode
### 5. **setting_options_repo.dart**
- ✅ `appInvitationCreate()` - Excludes customerID for customer app type in view-only mode
## How It Works
When `AppState().getIsViewOnly` is `true`, the application is in demonstration/view-only mode. In this mode:
1. **API parameters are conditionally added**: Instead of always including `customerID`, we check the view-only flag first
2. **Pattern used**:
```dart
var params = {
"otherParam": value,
};
if (!appState.getIsViewOnly) {
params["customerID"] = customerId;
}
```
3. **App types considered**: The changes properly handle both customer and provider app types
## Testing Recommendations
1. Test in normal mode (getIsViewOnly = false):
- All APIs should include customerID as before
- All existing functionality should work
2. Test in view-only mode (getIsViewOnly = true):
- APIs should NOT include customerID parameter
- Read-only operations should work
- Write operations should be blocked by view-only mode
## Note
The `createComplainFromProvider()` method in `common_repo.dart` was NOT modified because the `customerID` in that API represents the target customer being complained about, not the authenticated user making the request.

@ -413,6 +413,13 @@
"deleteAdConfirmationMessage": "سيتم حذف إعلانك نهائيًا ولا يمكنك التراجع عن هذا الإجراء", "deleteAdConfirmationMessage": "سيتم حذف إعلانك نهائيًا ولا يمكنك التراجع عن هذا الإجراء",
"mileage": "المسافة المقطوعة", "mileage": "المسافة المقطوعة",
"transmission": "ناقل الحركة", "transmission": "ناقل الحركة",
"odometer": "عداد المسافات",
"accidentFree": "خالية من الحوادث",
"brandNew": "جديدة",
"used": "مستعملة",
"hasYourCarHadAccident": "هل تعرضت سيارتك لأي حادث؟",
"odometerReading": "قراءة عداد المسافات (كم)",
"currentlyInUse": "قيد الاستخدام حاليًا",
"demand": "الطلب", "demand": "الطلب",
"adDurationExpired": "انتهت مدة عرض الإعلان الخاص بك", "adDurationExpired": "انتهت مدة عرض الإعلان الخاص بك",
"bankDetails": "تفاصيل البنك", "bankDetails": "تفاصيل البنك",
@ -720,6 +727,8 @@
"ownerInformation": "معلومات المالك", "ownerInformation": "معلومات المالك",
"acceptedRequests": "الطلبات المقبولة", "acceptedRequests": "الطلبات المقبولة",
"specialRequestChat": "دردشة الطلب الخاص", "specialRequestChat": "دردشة الطلب الخاص",
"sparePartRequestChat": "دردشة طلب قطع الغيار",
"specialCarRequestChat": "دردشة طلب السيارة الخاصة",
"companyName": "اسم الشركة", "companyName": "اسم الشركة",
"noAvailableItems": "لا توجد عناصر متاحة.", "noAvailableItems": "لا توجد عناصر متاحة.",
"serviceDeliveryType": "نوع تقديم الخدمة", "serviceDeliveryType": "نوع تقديم الخدمة",
@ -814,5 +823,7 @@
"selfPickupStatus": "حالة الالتقاط الذاتي", "selfPickupStatus": "حالة الالتقاط الذاتي",
"myDraftAds": "مسودتي للإعلانات", "myDraftAds": "مسودتي للإعلانات",
"scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح", "scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح",
"addValidAddress": "رجى إضافة عنوان صالح" "addValidAddress": "رجى إضافة عنوان صالح",
"termsPrivacyPolicy": "الشروط وسياسة الخصوصية"
} }

@ -414,6 +414,13 @@
"deleteAdConfirmationMessage": "Your ad will be permanently deleted and you cannot undo this action", "deleteAdConfirmationMessage": "Your ad will be permanently deleted and you cannot undo this action",
"mileage": "Mileage", "mileage": "Mileage",
"transmission": "Transmission", "transmission": "Transmission",
"odometer": "Odometer",
"accidentFree": "Accident Free",
"brandNew": "Brand New",
"used": "Used",
"hasYourCarHadAccident": "Has your car had any accident?",
"odometerReading": "Odometer Reading (Km)",
"currentlyInUse": "Currently in Use",
"demand": "Demand", "demand": "Demand",
"adDurationExpired": "Your Ad Duration time is over", "adDurationExpired": "Your Ad Duration time is over",
"bankDetails": "Bank Details", "bankDetails": "Bank Details",
@ -715,6 +722,8 @@
"noItemsToShow": "There are no Items no show.", "noItemsToShow": "There are no Items no show.",
"acceptedRequests": "Accepted Requests", "acceptedRequests": "Accepted Requests",
"specialRequestChat": "Special Request Chat", "specialRequestChat": "Special Request Chat",
"sparePartRequestChat": "Spare Part Request Chat",
"specialCarRequestChat": "Special Car Request Chat",
"companyName": "Company Name", "companyName": "Company Name",
"noAvailableItems": "There are no available items.", "noAvailableItems": "There are no available items.",
"serviceDeliveryType": "Service Delivery Type", "serviceDeliveryType": "Service Delivery Type",
@ -812,5 +821,6 @@
"selfPickupStatus": "Self Pickup Status", "selfPickupStatus": "Self Pickup Status",
"myDraftAds": "My Draft Ads", "myDraftAds": "My Draft Ads",
"scheduleDeletedSuccessfully": "The schedule has been deleted successfully", "scheduleDeletedSuccessfully": "The schedule has been deleted successfully",
"addValidAddress": "Please add a valid address" "addValidAddress": "Please add a valid address",
"termsPrivacyPolicy": "Terms & Privacy Policy"
} }

@ -1,6 +1,6 @@
// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart
// ignore_for_file: prefer_single_quotes, avoid_renaming_method_parameters // ignore_for_file: prefer_single_quotes, avoid_renaming_method_parameters, constant_identifier_names
import 'dart:ui'; import 'dart:ui';
@ -14,7 +14,7 @@ class CodegenLoader extends AssetLoader{
return Future.value(mapLocales[locale.toString()]); return Future.value(mapLocales[locale.toString()]);
} }
static const Map<String,dynamic> ar_SA = { static const Map<String,dynamic> _ar_SA = {
"firstTimeLogIn": "تسجيل الدخول لأول مره", "firstTimeLogIn": "تسجيل الدخول لأول مره",
"signUp": "التسجيل", "signUp": "التسجيل",
"changeMobile": "تغيير رقم الجوال", "changeMobile": "تغيير رقم الجوال",
@ -429,6 +429,13 @@ class CodegenLoader extends AssetLoader{
"deleteAdConfirmationMessage": "سيتم حذف إعلانك نهائيًا ولا يمكنك التراجع عن هذا الإجراء", "deleteAdConfirmationMessage": "سيتم حذف إعلانك نهائيًا ولا يمكنك التراجع عن هذا الإجراء",
"mileage": "المسافة المقطوعة", "mileage": "المسافة المقطوعة",
"transmission": "ناقل الحركة", "transmission": "ناقل الحركة",
"odometer": "عداد المسافات",
"accidentFree": "خالية من الحوادث",
"brandNew": "جديدة",
"used": "مستعملة",
"hasYourCarHadAccident": "هل تعرضت سيارتك لأي حادث؟",
"odometerReading": "قراءة عداد المسافات (كم)",
"currentlyInUse": "قيد الاستخدام حاليًا",
"demand": "الطلب", "demand": "الطلب",
"adDurationExpired": "انتهت مدة عرض الإعلان الخاص بك", "adDurationExpired": "انتهت مدة عرض الإعلان الخاص بك",
"bankDetails": "تفاصيل البنك", "bankDetails": "تفاصيل البنك",
@ -736,6 +743,8 @@ class CodegenLoader extends AssetLoader{
"ownerInformation": "معلومات المالك", "ownerInformation": "معلومات المالك",
"acceptedRequests": "الطلبات المقبولة", "acceptedRequests": "الطلبات المقبولة",
"specialRequestChat": "دردشة الطلب الخاص", "specialRequestChat": "دردشة الطلب الخاص",
"sparePartRequestChat": "دردشة طلب قطع الغيار",
"specialCarRequestChat": "دردشة طلب السيارة الخاصة",
"companyName": "اسم الشركة", "companyName": "اسم الشركة",
"noAvailableItems": "لا توجد عناصر متاحة.", "noAvailableItems": "لا توجد عناصر متاحة.",
"serviceDeliveryType": "نوع تقديم الخدمة", "serviceDeliveryType": "نوع تقديم الخدمة",
@ -830,9 +839,10 @@ class CodegenLoader extends AssetLoader{
"selfPickupStatus": "حالة الالتقاط الذاتي", "selfPickupStatus": "حالة الالتقاط الذاتي",
"myDraftAds": "مسودتي للإعلانات", "myDraftAds": "مسودتي للإعلانات",
"scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح", "scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح",
"addValidAddress": "رجى إضافة عنوان صالح" "addValidAddress": "رجى إضافة عنوان صالح",
"termsPrivacyPolicy": "الشروط وسياسة الخصوصية"
}; };
static const Map<String,dynamic> en_US = { static const Map<String,dynamic> _en_US = {
"firstTimeLogIn": "First Time Log In", "firstTimeLogIn": "First Time Log In",
"signUp": "Sign Up", "signUp": "Sign Up",
"changeMobile": "Change Mobile", "changeMobile": "Change Mobile",
@ -1248,6 +1258,13 @@ static const Map<String,dynamic> en_US = {
"deleteAdConfirmationMessage": "Your ad will be permanently deleted and you cannot undo this action", "deleteAdConfirmationMessage": "Your ad will be permanently deleted and you cannot undo this action",
"mileage": "Mileage", "mileage": "Mileage",
"transmission": "Transmission", "transmission": "Transmission",
"odometer": "Odometer",
"accidentFree": "Accident Free",
"brandNew": "Brand New",
"used": "Used",
"hasYourCarHadAccident": "Has your car had any accident?",
"odometerReading": "Odometer Reading (Km)",
"currentlyInUse": "Currently in Use",
"demand": "Demand", "demand": "Demand",
"adDurationExpired": "Your Ad Duration time is over", "adDurationExpired": "Your Ad Duration time is over",
"bankDetails": "Bank Details", "bankDetails": "Bank Details",
@ -1549,6 +1566,8 @@ static const Map<String,dynamic> en_US = {
"noItemsToShow": "There are no Items no show.", "noItemsToShow": "There are no Items no show.",
"acceptedRequests": "Accepted Requests", "acceptedRequests": "Accepted Requests",
"specialRequestChat": "Special Request Chat", "specialRequestChat": "Special Request Chat",
"sparePartRequestChat": "Spare Part Request Chat",
"specialCarRequestChat": "Special Car Request Chat",
"companyName": "Company Name", "companyName": "Company Name",
"noAvailableItems": "There are no available items.", "noAvailableItems": "There are no available items.",
"serviceDeliveryType": "Service Delivery Type", "serviceDeliveryType": "Service Delivery Type",
@ -1646,7 +1665,8 @@ static const Map<String,dynamic> en_US = {
"selfPickupStatus": "Self Pickup Status", "selfPickupStatus": "Self Pickup Status",
"myDraftAds": "My Draft Ads", "myDraftAds": "My Draft Ads",
"scheduleDeletedSuccessfully": "The schedule has been deleted successfully", "scheduleDeletedSuccessfully": "The schedule has been deleted successfully",
"addValidAddress": "Please add a valid address" "addValidAddress": "Please add a valid address",
"termsPrivacyPolicy": "Terms & Privacy Policy"
}; };
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US};
} }

@ -1,5 +1,7 @@
// DO NOT EDIT. This is code generated via package:easy_localization/generate.dart // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart
// ignore_for_file: constant_identifier_names
abstract class LocaleKeys { abstract class LocaleKeys {
static const firstTimeLogIn = 'firstTimeLogIn'; static const firstTimeLogIn = 'firstTimeLogIn';
static const signUp = 'signUp'; static const signUp = 'signUp';
@ -392,6 +394,13 @@ abstract class LocaleKeys {
static const deleteAdConfirmationMessage = 'deleteAdConfirmationMessage'; static const deleteAdConfirmationMessage = 'deleteAdConfirmationMessage';
static const mileage = 'mileage'; static const mileage = 'mileage';
static const transmission = 'transmission'; static const transmission = 'transmission';
static const odometer = 'odometer';
static const accidentFree = 'accidentFree';
static const brandNew = 'brandNew';
static const used = 'used';
static const hasYourCarHadAccident = 'hasYourCarHadAccident';
static const odometerReading = 'odometerReading';
static const currentlyInUse = 'currentlyInUse';
static const demand = 'demand'; static const demand = 'demand';
static const adDurationExpired = 'adDurationExpired'; static const adDurationExpired = 'adDurationExpired';
static const bankDetails = 'bankDetails'; static const bankDetails = 'bankDetails';
@ -699,6 +708,8 @@ abstract class LocaleKeys {
static const ownerInformation = 'ownerInformation'; static const ownerInformation = 'ownerInformation';
static const acceptedRequests = 'acceptedRequests'; static const acceptedRequests = 'acceptedRequests';
static const specialRequestChat = 'specialRequestChat'; static const specialRequestChat = 'specialRequestChat';
static const sparePartRequestChat = 'sparePartRequestChat';
static const specialCarRequestChat = 'specialCarRequestChat';
static const companyName = 'companyName'; static const companyName = 'companyName';
static const noAvailableItems = 'noAvailableItems'; static const noAvailableItems = 'noAvailableItems';
static const serviceDeliveryType = 'serviceDeliveryType'; static const serviceDeliveryType = 'serviceDeliveryType';
@ -794,5 +805,6 @@ abstract class LocaleKeys {
static const myDraftAds = 'myDraftAds'; static const myDraftAds = 'myDraftAds';
static const scheduleDeletedSuccessfully = 'scheduleDeletedSuccessfully'; static const scheduleDeletedSuccessfully = 'scheduleDeletedSuccessfully';
static const addValidAddress = 'addValidAddress'; static const addValidAddress = 'addValidAddress';
static const termsPrivacyPolicy = 'termsPrivacyPolicy';
} }

@ -190,7 +190,11 @@ class Vehicle {
int? vehicleType; int? vehicleType;
String? vehicleVIN; String? vehicleVIN;
int? countryID; int? countryID;
String? countryName;
String? currency; String? currency;
int? odometer;
int? isInUsed;
bool? isAccidentFree;
Vehicle( Vehicle(
{this.id, {this.id,
@ -217,7 +221,11 @@ class Vehicle {
this.vehicleType, this.vehicleType,
this.vehicleVIN, this.vehicleVIN,
this.countryID, this.countryID,
this.currency}); this.countryName,
this.currency,
this.odometer,
this.isInUsed,
this.isAccidentFree});
Vehicle.fromJson(Map<String, dynamic> json) { Vehicle.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
@ -254,7 +262,11 @@ class Vehicle {
vehicleType = json['vehicleType']; vehicleType = json['vehicleType'];
vehicleVIN = json['vehicleVIN']; vehicleVIN = json['vehicleVIN'];
countryID = json['countryID']; countryID = json['countryID'];
countryName = json['duration'] != null && json['duration']['country'] != null ? json['duration']['country']['label'] : null;
currency = json['currency']; currency = json['currency'];
odometer = json['odometer'];
isInUsed = json['isInUsed'];
isAccidentFree = json['isAccidentFree'];
} }
} }

@ -124,6 +124,9 @@ class VehiclePosting {
List<VehiclePostingDamageParts>? vehiclePostingDamageParts; List<VehiclePostingDamageParts>? vehiclePostingDamageParts;
String? phoneNo; String? phoneNo;
String? whatsAppNo; String? whatsAppNo;
int? odometer;
int? isInUsed;
bool? isAccidentFree;
VehiclePosting({ VehiclePosting({
this.id, this.id,
@ -151,6 +154,9 @@ class VehiclePosting {
this.whatsAppNo, this.whatsAppNo,
this.vehiclePostingImages, this.vehiclePostingImages,
this.vehiclePostingDamageParts, this.vehiclePostingDamageParts,
this.odometer,
this.isInUsed,
this.isAccidentFree,
}); });
VehiclePosting.fromJson(Map<String, dynamic> json) { VehiclePosting.fromJson(Map<String, dynamic> json) {
@ -177,6 +183,9 @@ class VehiclePosting {
adStatus = json['adStatus']; adStatus = json['adStatus'];
phoneNo = json['phoneNo']; phoneNo = json['phoneNo'];
whatsAppNo = json['whatsAppNo']; whatsAppNo = json['whatsAppNo'];
odometer = json['odometer'];
isInUsed = json['isInUsed'];
isAccidentFree = json['isAccidentFree'];
if (json['vehiclePostingImages'] != null) { if (json['vehiclePostingImages'] != null) {
vehiclePostingImages = <VehiclePostingImages>[]; vehiclePostingImages = <VehiclePostingImages>[];
json['vehiclePostingImages'].forEach((v) { json['vehiclePostingImages'].forEach((v) {
@ -193,7 +202,7 @@ class VehiclePosting {
@override @override
String toString() { String toString() {
return 'VehiclePosting{id: $id, userID: $userID, vehicleType: $vehicleType, vehicleModelID: $vehicleModelID, vehicleModelYearID: $vehicleModelYearID, vehicleColorID: $vehicleColorID, vehicleCategoryID: $vehicleCategoryID, vehicleConditionID: $vehicleConditionID, vehicleMileageID: $vehicleMileageID, vehicleTransmissionID: $vehicleTransmissionID, vehicleSellerTypeID: $vehicleSellerTypeID, cityID: $cityID, price: $price, vehicleVIN: $vehicleVIN, vehicleDescription: $vehicleDescription, vehicleTitle: $vehicleTitle, vehicleDescriptionN: $vehicleDescriptionN, isFinanceAvailable: $isFinanceAvailable, warantyYears: $warantyYears, demandAmount: $demandAmount, adStatus: $adStatus, vehiclePostingImages: $vehiclePostingImages, vehiclePostingDamageParts: $vehiclePostingDamageParts, phoneNo: $phoneNo, whatsAppNo: $whatsAppNo}'; return 'VehiclePosting{id: $id, userID: $userID, vehicleType: $vehicleType, vehicleModelID: $vehicleModelID, vehicleModelYearID: $vehicleModelYearID, vehicleColorID: $vehicleColorID, vehicleCategoryID: $vehicleCategoryID, vehicleConditionID: $vehicleConditionID, vehicleMileageID: $vehicleMileageID, vehicleTransmissionID: $vehicleTransmissionID, vehicleSellerTypeID: $vehicleSellerTypeID, cityID: $cityID, price: $price, vehicleVIN: $vehicleVIN, vehicleDescription: $vehicleDescription, vehicleTitle: $vehicleTitle, vehicleDescriptionN: $vehicleDescriptionN, isFinanceAvailable: $isFinanceAvailable, warantyYears: $warantyYears, demandAmount: $demandAmount, adStatus: $adStatus, vehiclePostingImages: $vehiclePostingImages, vehiclePostingDamageParts: $vehiclePostingDamageParts, phoneNo: $phoneNo, whatsAppNo: $whatsAppNo, odometer: $odometer, isInUsed: $isInUsed, isAccidentFree: $isAccidentFree}';
} }
} }

@ -199,6 +199,9 @@ class AdsRepoImp implements AdsRepo {
"vehiclePostingDamageParts": vehiclePostingDamageParts, "vehiclePostingDamageParts": vehiclePostingDamageParts,
"mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo, "mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo,
"whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo, "whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo,
"odometer": adsCreationPayloadModel.vehiclePosting!.odometer,
"isInUsed": adsCreationPayloadModel.vehiclePosting!.isInUsed,
"isAccidentFree": adsCreationPayloadModel.vehiclePosting!.isAccidentFree,
} }
}; };
@ -290,6 +293,9 @@ class AdsRepoImp implements AdsRepo {
"vehiclePostingDamagePartsDraft": vehiclePostingDamageParts, "vehiclePostingDamagePartsDraft": vehiclePostingDamageParts,
"mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo, "mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo,
"whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo, "whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo,
"odometer": adsCreationPayloadModel.vehiclePosting!.odometer,
"isInUsed": adsCreationPayloadModel.vehiclePosting!.isInUsed,
"isAccidentFree": adsCreationPayloadModel.vehiclePosting!.isAccidentFree,
// "adStatus": 1, // "adStatus": 1,
}, },
"stepNo": stepNo.toIntFromStepsEnum(), "stepNo": stepNo.toIntFromStepsEnum(),
@ -585,11 +591,14 @@ class AdsRepoImp implements AdsRepo {
var postParams = { var postParams = {
"adsID": adId, "adsID": adId,
"customerID": customerID,
"adsReserveStatus": adsReserveStatus, "adsReserveStatus": adsReserveStatus,
"comment": reason, "comment": reason,
}; };
if (!AppState().getIsViewOnly) {
postParams["customerID"] = customerID;
}
String token = appState.getUser.data!.accessToken ?? ""; String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject( GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
@ -607,10 +616,13 @@ class AdsRepoImp implements AdsRepo {
var postParams = { var postParams = {
"adsID": adId, "adsID": adId,
"customerID": customerID,
"adsReserveStatus": 0, "adsReserveStatus": 0,
}; };
if (!AppState().getIsViewOnly) {
postParams["customerID"] = customerID;
}
String token = appState.getUser.data!.accessToken ?? ""; String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject( GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
@ -667,11 +679,14 @@ class AdsRepoImp implements AdsRepo {
var postParams = { var postParams = {
"adsID": adId, "adsID": adId,
"customerID": customerId,
"detailNote": detailNote, "detailNote": detailNote,
"receiptImages": receiptImages, "receiptImages": receiptImages,
}; };
if (!AppState().getIsViewOnly) {
postParams["customerID"] = customerId;
}
String token = appState.getUser.data!.accessToken ?? ""; String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject( GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),

@ -174,16 +174,21 @@ class AppointmentRepoImp implements AppointmentRepo {
slotId = schedule.selectedCustomTimeDateSlotModel!.availableSlots![index].slotId; slotId = schedule.selectedCustomTimeDateSlotModel!.availableSlots![index].slotId;
mapList.add({ Map<String, dynamic> appointmentMap = {
"serviceSlotID": slotId, "serviceSlotID": slotId,
"serviceProviderID": serviceProviderID, "serviceProviderID": serviceProviderID,
"customerID": customerId,
"serviceItemID": serviceItemIds, "serviceItemID": serviceItemIds,
"amountCustomerLocation": schedule.totalLocationCharges.toString(), "amountCustomerLocation": schedule.totalLocationCharges.toString(),
"customerLocLat": (schedule.locationInfoModel!.latitude).toString(), "customerLocLat": (schedule.locationInfoModel!.latitude).toString(),
"customerLocLong": (schedule.locationInfoModel!.longitude).toString(), "customerLocLong": (schedule.locationInfoModel!.longitude).toString(),
"customerLocAddress": (schedule.locationInfoModel!.address).toString(), "customerLocAddress": (schedule.locationInfoModel!.address).toString(),
}); };
if (!appState.getIsViewOnly) {
appointmentMap["customerID"] = customerId;
}
mapList.add(appointmentMap);
} }
log("maplist: ${mapList.toString()}"); log("maplist: ${mapList.toString()}");
@ -278,8 +283,7 @@ class AppointmentRepoImp implements AppointmentRepo {
List<String>? branchIdsList, List<String>? branchIdsList,
AppointmentStatusEnum? appointmentStatusEnum, AppointmentStatusEnum? appointmentStatusEnum,
}) async { }) async {
var params = { var params = <String, dynamic>{
"customerID": appState.getUser.data!.userInfo!.customerId.toString(),
"ServiceProviderIDs": providerIdsList ?? [], "ServiceProviderIDs": providerIdsList ?? [],
"ProviderBranchIDs": branchIdsList ?? [], "ProviderBranchIDs": branchIdsList ?? [],
"ServiceIDs": serviceIdsList ?? [], "ServiceIDs": serviceIdsList ?? [],
@ -287,8 +291,12 @@ class AppointmentRepoImp implements AppointmentRepo {
"CategoryIDs": categoryIdsList ?? [], "CategoryIDs": categoryIdsList ?? [],
}; };
if (!appState.getIsViewOnly) {
params["customerID"] = appState.getUser.data!.userInfo!.customerId.toString();
}
if (appointmentStatusEnum != null) { if (appointmentStatusEnum != null) {
params.addAll({"AppointmentStatusID": appointmentStatusEnum.getIdFromAppointmentStatusEnum().toString()}); params["AppointmentStatusID"] = appointmentStatusEnum.getIdFromAppointmentStatusEnum().toString();
} }
GenericRespModel genericRespModel = await apiClient.getJsonForObject( GenericRespModel genericRespModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,

@ -587,7 +587,11 @@ class BranchRepoImp implements BranchRepo {
@override @override
Future<GenericRespModel> submitBranchRatings({required int serviceProviderBranchID, required String title, required String review, required double ratingNo}) async { Future<GenericRespModel> submitBranchRatings({required int serviceProviderBranchID, required String title, required String review, required double ratingNo}) async {
final customerID = appState.getUser.data!.userInfo!.customerId; final customerID = appState.getUser.data!.userInfo!.customerId;
final parameters = {"title": title, "review": review, "ratNo": ratingNo, "serviceProviderBranchID": serviceProviderBranchID, "customerID": "$customerID"}; final parameters = {"title": title, "review": review, "ratNo": ratingNo, "serviceProviderBranchID": serviceProviderBranchID};
if (!appState.getIsViewOnly) {
parameters["customerID"] = "$customerID";
}
GenericRespModel adsGenericModel = await apiClient.postJsonForObject( GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.createBranchRatings, ApiConsts.createBranchRatings,
@ -602,8 +606,12 @@ class BranchRepoImp implements BranchRepo {
final customerID = appState.getUser.data!.userInfo!.customerId; final customerID = appState.getUser.data!.userInfo!.customerId;
final parameters = { final parameters = {
"providerID": providerID.toString(), "providerID": providerID.toString(),
"customerID": customerID.toString(),
}; };
if (!appState.getIsViewOnly) {
parameters["customerID"] = customerID.toString();
}
GenericRespModel adsGenericModel = await apiClient.postJsonForObject( GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.favouriteServiceProviderCreate, ApiConsts.favouriteServiceProviderCreate,
@ -629,13 +637,17 @@ class BranchRepoImp implements BranchRepo {
Future<List<ProviderProfileModel>> getMyFavoriteProviders() async { Future<List<ProviderProfileModel>> getMyFavoriteProviders() async {
final customerID = appState.getUser.data!.userInfo!.customerId; final customerID = appState.getUser.data!.userInfo!.customerId;
var postParams = {"customerID": customerID.toString()}; var postParams = <String, dynamic>{};
if (!appState.getIsViewOnly) {
postParams["customerID"] = customerID.toString();
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.favouriteServiceProviderGet, ApiConsts.favouriteServiceProviderGet,
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,
queryParameters: postParams, queryParameters: postParams.isNotEmpty ? postParams : null,
); );
List<ProviderProfileModel> favProviders = List.generate(adsGenericModel.data.length, (index) => ProviderProfileModel.fromJson(adsGenericModel.data[index])); List<ProviderProfileModel> favProviders = List.generate(adsGenericModel.data.length, (index) => ProviderProfileModel.fromJson(adsGenericModel.data[index]));
return favProviders; return favProviders;

@ -98,7 +98,6 @@ class RequestRepoImp implements RequestRepo {
required List requestImages, required List requestImages,
}) async { }) async {
Map<String, dynamic> postParams = { Map<String, dynamic> postParams = {
"customerID": appState.getUser.data!.userInfo!.customerId ?? 0,
"requestType": requestTypeId, "requestType": requestTypeId,
"vehicleTypeID": vehicleTypeId, "vehicleTypeID": vehicleTypeId,
"brand": brand, "brand": brand,
@ -113,6 +112,10 @@ class RequestRepoImp implements RequestRepo {
"isSpecialServiceNeeded": false, "isSpecialServiceNeeded": false,
"requestImages": requestImages, "requestImages": requestImages,
}; };
if (!appState.getIsViewOnly) {
postParams["customerID"] = appState.getUser.data!.userInfo!.customerId ?? 0;
}
GenericRespModel enumGenericModel = await apiClient.postJsonForObject( GenericRespModel enumGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.createRequest, ApiConsts.createRequest,
@ -132,7 +135,9 @@ class RequestRepoImp implements RequestRepo {
if (appState.currentAppType == AppType.provider) { if (appState.currentAppType == AppType.provider) {
paramsForGetRequests.addEntries([MapEntry("providerID", providerOrCustomerID)]); paramsForGetRequests.addEntries([MapEntry("providerID", providerOrCustomerID)]);
} else { } else {
paramsForGetRequests.addEntries([MapEntry("customerID", providerOrCustomerID)]); if (!appState.getIsViewOnly) {
paramsForGetRequests.addEntries([MapEntry("customerID", providerOrCustomerID)]);
}
} }
GenericRespModel enumGenericModel = await apiClient.postJsonForObject( GenericRespModel enumGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
@ -180,7 +185,9 @@ class RequestRepoImp implements RequestRepo {
}; };
if (appState.currentAppType == AppType.customer) { if (appState.currentAppType == AppType.customer) {
paramsForGetRequests.addEntries([MapEntry("customerID", appState.getUser.data!.userInfo!.customerId ?? 0)]); if (!appState.getIsViewOnly) {
paramsForGetRequests.addEntries([MapEntry("customerID", appState.getUser.data!.userInfo!.customerId ?? 0)]);
}
} else { } else {
paramsForGetRequests.addEntries([MapEntry("providerID", appState.getUser.data!.userInfo!.providerId.toString())]); paramsForGetRequests.addEntries([MapEntry("providerID", appState.getUser.data!.userInfo!.providerId.toString())]);
} }
@ -322,9 +329,12 @@ class RequestRepoImp implements RequestRepo {
Future<ProviderOffersModel> getOffersFromProvidersByRequest({required int requestId}) async { Future<ProviderOffersModel> getOffersFromProvidersByRequest({required int requestId}) async {
final customerId = appState.getUser.data!.userInfo!.customerId; final customerId = appState.getUser.data!.userInfo!.customerId;
var queryParameters = { var queryParameters = {
"customerID": customerId.toString(),
"requestID": requestId.toString(), "requestID": requestId.toString(),
}; };
if (!appState.getIsViewOnly) {
queryParameters["customerID"] = customerId.toString();
}
GenericRespModel genericRespModel = await apiClient.postJsonForObject( GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.requestOffersSpsGet, ApiConsts.requestOffersSpsGet,

@ -166,10 +166,16 @@ class SettingOptionsRepoImp extends SettingOptionsRepo {
}; };
if (AppState().currentAppType == AppType.customer) { if (AppState().currentAppType == AppType.customer) {
params.addAll({ if (!appState.getIsViewOnly) {
"customerID": (appState.getUser.data!.userInfo!.customerId ?? "0").toString(), params.addAll({
"channelID": "3", "customerID": (appState.getUser.data!.userInfo!.customerId ?? "0").toString(),
}); "channelID": "3",
});
} else {
params.addAll({
"channelID": "3",
});
}
} else { } else {
params.addAll({ params.addAll({
"providerID": (appState.getUser.data!.userInfo!.providerId ?? "0").toString(), "providerID": (appState.getUser.data!.userInfo!.providerId ?? "0").toString(),

@ -729,6 +729,29 @@ class AdVM extends BaseVM {
vehicleDemandAmount = amount; vehicleDemandAmount = amount;
} }
String odometer = "";
void updateOdometer(String value) {
odometer = value;
notifyListeners();
}
int isInUsed = 0;
void updateIsInUsed(int value) {
isInUsed = value;
notifyListeners();
}
bool isAccidentFree = false;
bool isAccidentFreeSet = false;
void updateIsAccidentFree(bool value) {
isAccidentFree = value;
isAccidentFreeSet = true;
notifyListeners();
}
String reservationCancelReason = ""; String reservationCancelReason = "";
String reservationCancelError = ""; String reservationCancelError = "";
@ -1310,6 +1333,9 @@ class AdVM extends BaseVM {
vehiclePostingDamageParts: vehicleDamageImages, vehiclePostingDamageParts: vehicleDamageImages,
phoneNo: isPhoneNumberShown ? adPhoneNumberDialCode + adPhoneNumber : null, phoneNo: isPhoneNumberShown ? adPhoneNumberDialCode + adPhoneNumber : null,
whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp) ? adPhoneNumberDialCode + adPhoneNumber : null, whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp) ? adPhoneNumberDialCode + adPhoneNumber : null,
odometer: odometer.isNotEmpty ? int.tryParse(odometer) : 0,
isInUsed: isInUsed,
isAccidentFree: isAccidentFree,
); );
AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting); AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting);
@ -1437,7 +1463,7 @@ class AdVM extends BaseVM {
// Added By Aamir // Added By Aamir
if (pickedPostingImages.length > GlobalConsts.maxFileCount) { if (pickedPostingImages.length > GlobalConsts.maxFileCount) {
pickedPostingImages = pickedPostingImages.sublist(0, GlobalConsts.maxFileCount); pickedPostingImages = pickedPostingImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
if (pickedPostingImages.isNotEmpty) vehicleImageError = ""; if (pickedPostingImages.isNotEmpty) vehicleImageError = "";
@ -1485,7 +1511,7 @@ class AdVM extends BaseVM {
// Added By Aamir // Added By Aamir
if (vehicleDamageCards[index].partImages!.length > GlobalConsts.maxFileCount) { if (vehicleDamageCards[index].partImages!.length > GlobalConsts.maxFileCount) {
vehicleDamageCards[index].partImages = vehicleDamageCards[index].partImages!.sublist(0, GlobalConsts.maxFileCount); vehicleDamageCards[index].partImages = vehicleDamageCards[index].partImages!.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
} }
@ -1541,7 +1567,7 @@ class AdVM extends BaseVM {
if (pickedDamageImages.length > GlobalConsts.maxFileCount) { if (pickedDamageImages.length > GlobalConsts.maxFileCount) {
pickedDamageImages = pickedDamageImages.sublist(0, GlobalConsts.maxFileCount); pickedDamageImages = pickedDamageImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
if (pickedDamageImages.isNotEmpty) vehicleDamageImageError = ""; if (pickedDamageImages.isNotEmpty) vehicleDamageImageError = "";
notifyListeners(); notifyListeners();
@ -1577,6 +1603,10 @@ class AdVM extends BaseVM {
isNumberOnWhatsApp = false; isNumberOnWhatsApp = false;
adPhoneNumberDialCode = ""; adPhoneNumberDialCode = "";
adPhoneNumber = ""; adPhoneNumber = "";
odometer = "";
isInUsed = 0;
isAccidentFree = false;
isAccidentFreeSet = false;
clearSpecialServiceCard(); clearSpecialServiceCard();
updateFinanceAvailableStatus(false); updateFinanceAvailableStatus(false);
notifyListeners(); notifyListeners();
@ -1792,6 +1822,9 @@ class AdVM extends BaseVM {
vehiclePostingDamageParts: vehicleDamageImages, vehiclePostingDamageParts: vehicleDamageImages,
phoneNo: isPhoneNumberShown ? adPhoneNumberDialCode + adPhoneNumber : null, phoneNo: isPhoneNumberShown ? adPhoneNumberDialCode + adPhoneNumber : null,
whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp) ? adPhoneNumberDialCode + adPhoneNumber : null, whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp) ? adPhoneNumberDialCode + adPhoneNumber : null,
odometer: odometer.isNotEmpty ? int.tryParse(odometer) : 0,
isInUsed: isInUsed,
isAccidentFree: isAccidentFree,
); );
AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting); AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting);
@ -2455,6 +2488,10 @@ class AdVM extends BaseVM {
vehicleTitle = previousAdDetails!.vehicle!.vehicleTitle.toString(); vehicleTitle = previousAdDetails!.vehicle!.vehicleTitle.toString();
vehicleDescription = previousAdDetails!.vehicle!.vehicleDescription.toString(); vehicleDescription = previousAdDetails!.vehicle!.vehicleDescription.toString();
financeAvailableStatus = previousAdDetails!.vehicle!.isFinanceAvailable ?? false; financeAvailableStatus = previousAdDetails!.vehicle!.isFinanceAvailable ?? false;
odometer = previousAdDetails!.vehicle!.odometer != null ? previousAdDetails!.vehicle!.odometer.toString() : "0";
isInUsed = previousAdDetails!.vehicle!.isInUsed ?? 0;
isAccidentFree = previousAdDetails!.vehicle!.isAccidentFree ?? false;
isAccidentFreeSet = true;
pickedPostingImages.clear(); pickedPostingImages.clear();
if (previousAdDetails!.vehicle!.image != null && previousAdDetails!.vehicle!.image!.isNotEmpty) { if (previousAdDetails!.vehicle!.image != null && previousAdDetails!.vehicle!.image!.isNotEmpty) {
for (var element in previousAdDetails!.vehicle!.image!) { for (var element in previousAdDetails!.vehicle!.image!) {

@ -447,7 +447,7 @@ class ChatVM extends BaseVM {
pickedImagesForMessage.addAll(imageModels); pickedImagesForMessage.addAll(imageModels);
if (pickedImagesForMessage.length > GlobalConsts.maxFileCount) { if (pickedImagesForMessage.length > GlobalConsts.maxFileCount) {
pickedImagesForMessage = pickedImagesForMessage.sublist(0, GlobalConsts.maxFileCount); pickedImagesForMessage = pickedImagesForMessage.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
notifyListeners(); notifyListeners();

@ -294,7 +294,7 @@ class RequestsVM extends BaseVM {
pickedVehicleImages.addAll(imageModels); pickedVehicleImages.addAll(imageModels);
if (pickedVehicleImages.length > GlobalConsts.maxFileCount) { if (pickedVehicleImages.length > GlobalConsts.maxFileCount) {
pickedVehicleImages = pickedVehicleImages.sublist(0, GlobalConsts.maxFileCount); pickedVehicleImages = pickedVehicleImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
if (pickedVehicleImages.isNotEmpty) vehicleImageError = ""; if (pickedVehicleImages.isNotEmpty) vehicleImageError = "";

@ -142,7 +142,7 @@ class ServiceVM extends BaseVM {
pickedBranchImages.addAll(imageModels); pickedBranchImages.addAll(imageModels);
if (pickedBranchImages.length > GlobalConsts.maxFileCount) { if (pickedBranchImages.length > GlobalConsts.maxFileCount) {
pickedBranchImages = pickedBranchImages.sublist(0, GlobalConsts.maxFileCount); pickedBranchImages = pickedBranchImages.sublist(0, GlobalConsts.maxFileCount);
Utils.showToast(LocaleKeys.maxFileSelection); Utils.showToast(LocaleKeys.maxFileSelection.tr());
} }
if (pickedBranchImages.isNotEmpty) branchImageError = ""; if (pickedBranchImages.isNotEmpty) branchImageError = "";
notifyListeners(); notifyListeners();

@ -78,6 +78,10 @@ class VehicleDetailsReview extends StatelessWidget {
16.height, 16.height,
SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: LocaleKeys.vehicleCity.tr()), SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: LocaleKeys.vehicleCity.tr()),
16.height, 16.height,
SingleDetailWidget(text: adVM.isAccidentFree ? LocaleKeys.yes.tr() : LocaleKeys.no.tr(), type: LocaleKeys.accidentFree.tr()),
16.height,
SingleDetailWidget(text: "${adVM.odometer} Km", type: LocaleKeys.odometer.tr()),
16.height,
SingleDetailWidget(text: adVM.vehicleVin, type: LocaleKeys.vehicleVIN.tr()), SingleDetailWidget(text: adVM.vehicleVin, type: LocaleKeys.vehicleVIN.tr()),
16.height, 16.height,
SingleDetailWidget(text: ("${adVM.warrantyDuration} ${LocaleKeys.years.tr()}"), type: LocaleKeys.warrantyAvailable.tr()), SingleDetailWidget(text: ("${adVM.warrantyDuration} ${LocaleKeys.years.tr()}"), type: LocaleKeys.warrantyAvailable.tr()),
@ -104,7 +108,9 @@ class VehicleDetailsReview extends StatelessWidget {
16.height, 16.height,
SingleDetailWidget(text: adVM.vehicleTitle, type: LocaleKeys.vehicleTitle.tr()), SingleDetailWidget(text: adVM.vehicleTitle, type: LocaleKeys.vehicleTitle.tr()),
16.height, 16.height,
SingleDetailWidget(text: adVM.financeAvailableStatus ? "Yes" : "No", type: LocaleKeys.financeAvailable.tr()), SingleDetailWidget(text: adVM.financeAvailableStatus ? LocaleKeys.yes.tr() : LocaleKeys.no.tr(), type: LocaleKeys.financeAvailable.tr()),
16.height,
SingleDetailWidget(text: adVM.isInUsed == 1 ? LocaleKeys.yes.tr() : LocaleKeys.no.tr(), type: LocaleKeys.currentlyInUse.tr()),
16.height, 16.height,
], ],
), ),

@ -237,6 +237,28 @@ class VehicleDetails extends StatelessWidget {
errorValue: adVM.vehicleCityId.errorValue, errorValue: adVM.vehicleCityId.errorValue,
); );
}), }),
8.height,
Builder(builder: (context) {
List<DropValue> accidentFreeDrop = [
DropValue(1, LocaleKeys.yes.tr(), ""),
DropValue(0, LocaleKeys.no.tr(), ""),
];
return DropdownField(
(DropValue value) => adVM.updateIsAccidentFree(value.id == 1),
list: accidentFreeDrop,
dropdownValue: adVM.isAccidentFreeSet ? DropValue(adVM.isAccidentFree ? 1 : 0, adVM.isAccidentFree ? LocaleKeys.yes.tr() : LocaleKeys.no.tr(), "") : null,
hint: LocaleKeys.hasYourCarHadAccident.tr(),
errorValue: "",
);
}),
8.height,
TxtField(
value: adVM.odometer,
keyboardType: TextInputType.number,
numbersOnly: true,
hint: LocaleKeys.odometerReading.tr(),
onChanged: (v) => adVM.updateOdometer(v),
),
], ],
], ],
8.height, 8.height,
@ -282,28 +304,71 @@ class VehicleDetails extends StatelessWidget {
onChanged: (v) => adVM.updateVehicleDescription(v), onChanged: (v) => adVM.updateVehicleDescription(v),
), ),
22.height, 22.height,
LocaleKeys.financeAvailable.tr().toText(fontSize: 16), Row(
8.height, mainAxisAlignment: MainAxisAlignment.spaceBetween,
Container( children: [
width: 50, Expanded(
height: 30, child: Column(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.start,
color: adVM.financeAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white, children: [
borderRadius: BorderRadius.circular(25.0), LocaleKeys.financeAvailable.tr().toText(fontSize: 16),
border: Border.all(color: MyColors.black, width: 1), 8.height,
), Container(
child: Transform.scale( width: 50,
scale: 0.8, height: 30,
child: CupertinoSwitch( decoration: BoxDecoration(
activeColor: MyColors.darkPrimaryColor, color: adVM.financeAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white,
trackColor: MyColors.white, borderRadius: BorderRadius.circular(25.0),
thumbColor: MyColors.grey98Color, border: Border.all(color: MyColors.black, width: 1),
value: adVM.financeAvailableStatus, ),
onChanged: (value) { child: Transform.scale(
adVM.updateFinanceAvailableStatus(value); scale: 0.8,
}, child: CupertinoSwitch(
activeColor: MyColors.darkPrimaryColor,
trackColor: MyColors.white,
thumbColor: MyColors.grey98Color,
value: adVM.financeAvailableStatus,
onChanged: (value) {
adVM.updateFinanceAvailableStatus(value);
},
),
),
),
],
),
), ),
), 8.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.currentlyInUse.tr().toText(fontSize: 16),
8.height,
Container(
width: 50,
height: 30,
decoration: BoxDecoration(
color: adVM.isInUsed == 1 ? MyColors.darkPrimaryColor : MyColors.white,
borderRadius: BorderRadius.circular(25.0),
border: Border.all(color: MyColors.black, width: 1),
),
child: Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
activeColor: MyColors.darkPrimaryColor,
trackColor: MyColors.white,
thumbColor: MyColors.grey98Color,
value: adVM.isInUsed == 1,
onChanged: (value) {
adVM.updateIsInUsed(value ? 1 : 0);
},
),
),
),
],
),
),
],
), ),
28.height, 28.height,
LocaleKeys.vehiclePictures.tr().toText(fontSize: 18, isBold: true), LocaleKeys.vehiclePictures.tr().toText(fontSize: 18, isBold: true),

@ -1,7 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
@ -106,13 +104,20 @@ class _AdsDetailViewState extends State<AdsDetailView> {
children: [ children: [
Row( Row(
children: [ children: [
("${LocaleKeys.model.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.vehicleModel.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
"${widget.adDetails.vehicle!.modelyear!.label}".toText(fontSize: 12), "${widget.adDetails.vehicle!.model!.label}".toText(fontSize: 12),
], ],
), ),
"${widget.adDetails.vehicle!.countryID}".toText(fontSize: 10, color: MyColors.lightTextColor), (widget.adDetails.vehicle!.countryName ?? '').toText(fontSize: 10, color: MyColors.lightTextColor),
], ],
), ),
Row(
children: [
("${LocaleKeys.vehicleModelYear.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
"${widget.adDetails.vehicle!.modelyear!.label}".toText(fontSize: 12),
],
),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -131,6 +136,24 @@ class _AdsDetailViewState extends State<AdsDetailView> {
"${widget.adDetails.vehicle!.transmission!.label}".toText(fontSize: 12), "${widget.adDetails.vehicle!.transmission!.label}".toText(fontSize: 12),
], ],
), ),
Row(
children: [
("${LocaleKeys.odometer.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
"${widget.adDetails.vehicle!.odometer ?? 0} Km".toText(fontSize: 12),
],
),
Row(
children: [
("${LocaleKeys.vehicleCondition.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
(widget.adDetails.vehicle!.isInUsed == 0 ? LocaleKeys.brandNew.tr() : LocaleKeys.used.tr()).toText(fontSize: 12),
],
),
Row(
children: [
("${LocaleKeys.accidentFree.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
((widget.adDetails.vehicle!.isAccidentFree ?? false) ? LocaleKeys.yes.tr() : LocaleKeys.no.tr()).toText(fontSize: 12),
],
),
Row( Row(
children: [ children: [
("${LocaleKeys.financeAvailable.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.financeAvailable.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
@ -390,7 +413,7 @@ class _AdsDetailViewState extends State<AdsDetailView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Flexible(child: ("${widget.adDetails.specialservice![index].name}").toText(fontSize: 14, color: MyColors.lightTextColor)), Flexible(child: ("${widget.adDetails.specialservice![index].name}").toText(fontSize: 14, color: MyColors.lightTextColor)),
("${widget.adDetails.specialservice![index].price} ${LocaleKeys.sar.tr()} ").toText(fontSize: 14, color: MyColors.lightTextColor), ("${widget.adDetails.specialservice![index].price} ${widget.adDetails.vehicle!.currency ?? LocaleKeys.sar.tr()} ").toText(fontSize: 14, color: MyColors.lightTextColor),
], ],
)), )),
), ),

@ -56,7 +56,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
children: [ children: [
"${adDetailsModel.reservePrice}".toText(fontSize: 19, isBold: true), "${adDetailsModel.reservePrice}".toText(fontSize: 19, isBold: true),
2.width, 2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), (adDetailsModel.vehicle!.currency ?? LocaleKeys.sar.tr()).toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3),
], ],
) )
], ],
@ -73,7 +73,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
children: [ children: [
"${adDetailsModel.vehicle!.demandAmount ?? 0.0}".toText(fontSize: 19, isBold: true), "${adDetailsModel.vehicle!.demandAmount ?? 0.0}".toText(fontSize: 19, isBold: true),
2.width, 2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), (adDetailsModel.vehicle!.currency ?? LocaleKeys.sar.tr()).toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3),
], ],
) )
], ],
@ -123,7 +123,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
children: [ children: [
"${(adDetailsModel.vehicle!.demandAmount ?? 0.0)}".toText(fontSize: 19, isBold: true), "${(adDetailsModel.vehicle!.demandAmount ?? 0.0)}".toText(fontSize: 19, isBold: true),
2.width, 2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), (adDetailsModel.vehicle!.currency ?? LocaleKeys.sar.tr()).toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3),
], ],
) )
], ],

@ -349,6 +349,7 @@ class _AdsFilterViewState extends State<AdsFilterView> {
title: LocaleKeys.search.tr(), title: LocaleKeys.search.tr(),
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
adVM.updateIsExploreAds(true);
adVM.getAdsBasedOnFilters(isFromLazyLoad: false, pageIndex: 0); adVM.getAdsBasedOnFilters(isFromLazyLoad: false, pageIndex: 0);
}, },
backgroundColor: MyColors.darkPrimaryColor, backgroundColor: MyColors.darkPrimaryColor,
@ -360,7 +361,10 @@ class _AdsFilterViewState extends State<AdsFilterView> {
), ),
8.height, 8.height,
InkWell( InkWell(
onTap: () => adVM.clearAdsFilters(), onTap: () {
adVM.updateIsExploreAds(true);
adVM.clearAdsFilters();
},
child: LocaleKeys.clearFilters.tr().toText( child: LocaleKeys.clearFilters.tr().toText(
fontSize: 14, fontSize: 14,
isBold: true, isBold: true,

@ -36,17 +36,21 @@ class _AdDamagePartPicturesSheetState extends State<AdDamagePartPicturesSheet> {
void populateDamagePartPictures() { void populateDamagePartPictures() {
List<dynamic> adDamageReportList = widget.adDamageReportList; // Assuming this is your data source. List<dynamic> adDamageReportList = widget.adDamageReportList; // Assuming this is your data source.
Map<String, VehicleDamageCard> groupedDamageCards = {};
Map<int, VehicleDamageCard> groupedDamageCards = {};
for (var element in adDamageReportList) { for (var element in adDamageReportList) {
int partId = element.vehicleDamagePartID ?? 0;
String partName = element.partName ?? "Unknown"; String partName = element.partName ?? "Unknown";
ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true);
if (groupedDamageCards.containsKey(partName)) {
groupedDamageCards[partName]!.partImages!.add(imageModel); if (groupedDamageCards.containsKey(partId)) {
groupedDamageCards[partId]!.partImages!.add(imageModel);
} else { } else {
groupedDamageCards[partName] = VehicleDamageCard( groupedDamageCards[partId] = VehicleDamageCard(
partSelectedId: SelectionModel( partSelectedId: SelectionModel(
selectedId: element.vehicleDamagePartID!, selectedId: partId,
selectedOption: partName, selectedOption: partName,
), ),
damagePartDescription: element.comment ?? "", damagePartDescription: element.comment ?? "",

@ -39,11 +39,30 @@ class AdsListWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final adVM = context.watch<AdVM>();
if (isAdsFragment && adsList.isEmpty) { if (isAdsFragment && adsList.isEmpty) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
LocaleKeys.noAdsShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium), const SizedBox(height: 25),
(adVM.adsFiltersCounter > 0 ? "No Ads that matches your search" : LocaleKeys.noAdsShow.tr()).toText(fontSize: 16, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium),
if (adVM.adsFiltersCounter > 0) ...[
const SizedBox(height: 16),
GestureDetector(
onTap: () {
adVM.clearAdsFilters();
},
child: Text(
LocaleKeys.clearFilters.tr(),
style: const TextStyle(
color: MyColors.darkPrimaryColor,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
],
], ],
); );
} }

@ -328,7 +328,16 @@ class AppointmentDetailView extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
((service.currentTotalServicePrice).toString()).toText(fontSize: 19, isBold: true), if (service.isHomeSelected) ...[
Builder(builder: (context) {
double totalKms = double.parse(service.servicelocationInfo.distanceToBranch.toStringAsFixed(2));
double pricePerKm = double.parse(service.servicelocationInfo.homeChargesInCurrentService.toStringAsFixed(2));
return ((service.currentTotalServicePrice + (pricePerKm * totalKms)).toStringAsFixed(2))
.toText(fontSize: 19, isBold: true);
}),
] else ...[
((service.currentTotalServicePrice).toString()).toText(fontSize: 19, isBold: true),
],
2.width, 2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 5), LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 5),
const Icon(Icons.arrow_drop_down, size: 25) const Icon(Icons.arrow_drop_down, size: 25)

@ -102,11 +102,12 @@ class BookAppointmentSchedulesView extends StatelessWidget {
Column( Column(
children: [ children: [
CustomCalenderAppointmentWidget( CustomCalenderAppointmentWidget(
customTimeDateSlotList: scheduleData.customTimeDateSlotList ?? [], customTimeDateSlotList: scheduleData.customTimeDateSlotList ?? [],
onDateSelected: (int dateIndex) { onDateSelected: (int dateIndex) {
appointmentsVM.updateSelectedAppointmentDate(scheduleIndex: scheduleIndex, dateIndex: dateIndex); appointmentsVM.updateSelectedAppointmentDate(scheduleIndex: scheduleIndex, dateIndex: dateIndex);
}, },
selectedCustomTimeDateSlotModel: scheduleData.selectedCustomTimeDateSlotModel), selectedCustomTimeDateSlotModel: scheduleData.selectedCustomTimeDateSlotModel,
),
if (appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex != null) ...[ if (appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex != null) ...[
5.height, 5.height,
Row( Row(

@ -107,8 +107,12 @@ class BookAppointmentServicesView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
if (serviceData.isHomeSelected) ...[ if (serviceData.isHomeSelected) ...[
((serviceData.currentTotalServicePrice + (serviceData.servicelocationInfo.distanceToBranch * double.parse(serviceData.rangePricePerKm!))).toStringAsFixed(2)) Builder(builder: (context) {
.toText(fontSize: 32, isBold: true), double totalKms = double.parse(serviceData.servicelocationInfo.distanceToBranch.toStringAsFixed(2));
double pricePerKm = double.parse(serviceData.servicelocationInfo.homeChargesInCurrentService.toStringAsFixed(2));
return ((serviceData.currentTotalServicePrice + (pricePerKm * totalKms)).toStringAsFixed(2))
.toText(fontSize: 32, isBold: true);
}),
] else ...[ ] else ...[
((serviceData.currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true), ((serviceData.currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true),
], ],

@ -75,6 +75,8 @@ void dealCompletedConsentBottomSheet({
requestVM.myFilteredRequests[index].requestStatus = requestStatusEnum; requestVM.myFilteredRequests[index].requestStatus = requestStatusEnum;
} }
chatVM.updateAcknowledgePaymentToMowaterStatus(false); chatVM.updateAcknowledgePaymentToMowaterStatus(false);
// Refresh requests list before navigating
await requestVM.getRequestsBasedOnFilters();
mainContext.read<DashboardVmCustomer>().onNavbarTapped(4); mainContext.read<DashboardVmCustomer>().onNavbarTapped(4);
navigateReplaceWithNameUntilRoute(mainContext, AppRoutes.dashboard); navigateReplaceWithNameUntilRoute(mainContext, AppRoutes.dashboard);
} }
@ -93,6 +95,8 @@ void dealCompletedConsentBottomSheet({
requestVM.myFilteredRequests[index].requestStatus = requestStatusEnum; requestVM.myFilteredRequests[index].requestStatus = requestStatusEnum;
} }
chatVM.updateAcknowledgePaymentToMowaterStatus(false); chatVM.updateAcknowledgePaymentToMowaterStatus(false);
// Refresh requests list before navigating
await requestVM.getRequestsBasedOnFilters();
mainContext.read<DashboardVmCustomer>().onNavbarTapped(4); mainContext.read<DashboardVmCustomer>().onNavbarTapped(4);
navigateReplaceWithNameUntilRoute(mainContext, AppRoutes.dashboard); navigateReplaceWithNameUntilRoute(mainContext, AppRoutes.dashboard);
} }

@ -148,6 +148,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
} }
setState(() {}); setState(() {});
chatVM.updateRejectOfferDescription(''); chatVM.updateRejectOfferDescription('');
// Refresh requests list
await requestVM.getRequestsBasedOnFilters();
Utils.showToast(LocaleKeys.offerRejected.tr()); Utils.showToast(LocaleKeys.offerRejected.tr());
// navigateReplaceWithName(context, AppRoutes.dashboard); // navigateReplaceWithName(context, AppRoutes.dashboard);
} }
@ -250,6 +252,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum; chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
} }
setState(() {}); setState(() {});
// Refresh requests list
await requestVM.getRequestsBasedOnFilters();
Utils.showToast(LocaleKeys.offerAccepted.tr()); Utils.showToast(LocaleKeys.offerAccepted.tr());
return true; return true;
} else { } else {
@ -399,6 +403,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
setState(() {}); setState(() {});
// Navigator.pop(context); // Navigator.pop(context);
chatVM.updateRejectOfferDescription(''); chatVM.updateRejectOfferDescription('');
// Refresh requests list
await requestVM.getRequestsBasedOnFilters();
Utils.showToast("Offer ${requestOfferStatusEnum == RequestOfferStatusEnum.rejected ? "Rejected" : "Cancelled"}"); Utils.showToast("Offer ${requestOfferStatusEnum == RequestOfferStatusEnum.rejected ? "Rejected" : "Cancelled"}");
// navigateReplaceWithName(context, AppRoutes.dashboard); // navigateReplaceWithName(context, AppRoutes.dashboard);
} }
@ -459,6 +465,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
} }
setState(() {}); setState(() {});
// Navigator.pop(context); // Navigator.pop(context);
// Refresh requests list
await requestVM.getRequestsBasedOnFilters();
Utils.showToast(LocaleKeys.offerAccepted.tr()); Utils.showToast(LocaleKeys.offerAccepted.tr());
// navigateReplaceWithName(context, AppRoutes.dashboard); // navigateReplaceWithName(context, AppRoutes.dashboard);
} }

@ -141,11 +141,15 @@ class RequestDetailPage extends StatelessWidget {
}) { }) {
switch (requestStatus) { switch (requestStatus) {
case RequestStatusEnum.submitted: case RequestStatusEnum.submitted:
String chatButtonText = requestTypeEnum == RequestsTypeEnum.specialCarRequest
? LocaleKeys.specialCarRequestChat.tr()
: LocaleKeys.sparePartRequestChat.tr();
return ShowFillButton( return ShowFillButton(
maxWidth: double.infinity, maxWidth: double.infinity,
margin: const EdgeInsets.all(15), margin: const EdgeInsets.all(15),
maxHeight: 55, maxHeight: 55,
title: LocaleKeys.specialRequestChat.tr(), title: chatButtonText,
isBold: false, isBold: false,
onPressed: () => onViewChatTapped(context), onPressed: () => onViewChatTapped(context),
); );

@ -127,12 +127,12 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.locationInformation.tr().toText(fontSize: 18), LocaleKeys.serviceDeliveryType.tr().toText(fontSize: 18),
// Row( // Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [ // children: [
// LocaleKeys.locationInformation.tr().toText(fontSize: 18), // LocaleKeys.serviceDeliveryType.tr().toText(fontSize: 18),
// MyAssets.icEdit.buildSvg().onPress(() => buildLocationInformationEditBottomSheet(context, requestVM)), // MyAssets.icEdit.buildSvg().onPress(() => buildLocationInformationEditBottomSheet(context, requestVM)),
// ], // ],
// ), // ),
@ -207,7 +207,7 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
} }
Widget buildServiceInformation(BuildContext context) { Widget buildServiceInformation(BuildContext context) {
final requestVM = context.read<RequestsVM>(); final requestVM = context.watch<RequestsVM>();
String manufacturedOnFormattedDate = ""; String manufacturedOnFormattedDate = "";
if (requestVM.acceptedRequestOffer!.manufacturedOn != null) { if (requestVM.acceptedRequestOffer!.manufacturedOn != null) {
@ -217,6 +217,23 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
if (requestVM.currentSelectedRequest!.createdOn != null) { if (requestVM.currentSelectedRequest!.createdOn != null) {
requestCreatedOn = DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(requestVM.currentSelectedRequest!.createdOn.toString() ?? ""))); requestCreatedOn = DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(requestVM.currentSelectedRequest!.createdOn.toString() ?? "")));
} }
// Get selected delivery type
String selectedDeliveryType = "-";
String deliveryAddress = "";
bool showMapButton = false;
if (requestVM.selectedDeliveryOptionEnum != null) {
selectedDeliveryType = requestVM.selectedDeliveryOptionEnum!.getStringFromRequestDeliveryOptionEnum();
if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.delivery) {
deliveryAddress = requestVM.currentSelectedRequest!.address;
} else if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.selfPickup) {
deliveryAddress = requestVM.currentSelectedOffer!.providerAddress ?? "";
showMapButton = true;
}
}
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -237,6 +254,8 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SingleDetailWidget(text: requestVM.currentSelectedRequest!.requestTypeName, type: LocaleKeys.serviceCategory.tr()),
16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.vehicleTypeName, type: LocaleKeys.vehicleType.tr()), SingleDetailWidget(text: requestVM.currentSelectedRequest!.vehicleTypeName, type: LocaleKeys.vehicleType.tr()),
16.height, 16.height,
SingleDetailWidget(text: '${requestVM.currentSelectedRequest!.model} ${requestVM.currentSelectedRequest!.year}', type: LocaleKeys.model.tr()), SingleDetailWidget(text: '${requestVM.currentSelectedRequest!.model} ${requestVM.currentSelectedRequest!.year}', type: LocaleKeys.model.tr()),
@ -244,11 +263,8 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
16.height, 16.height,
SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedByName ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()), SingleDetailWidget(text: (requestVM.acceptedRequestOffer!.manufacturedByName ?? "").toString(), type: LocaleKeys.manufacturedBy.tr()),
], ],
// 16.height,
// SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()),
16.height, 16.height,
SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()), SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()),
16.height, 16.height,
SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()), SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()),
], ],
@ -260,6 +276,8 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
SingleDetailWidget(text: selectedDeliveryType, type: LocaleKeys.serviceDeliveryType.tr()),
16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.brand, type: LocaleKeys.vehicleBrand.tr()), SingleDetailWidget(text: requestVM.currentSelectedRequest!.brand, type: LocaleKeys.vehicleBrand.tr()),
16.height, 16.height,
SingleDetailWidget(text: requestVM.acceptedRequestOffer!.serviceItemName ?? "", type: LocaleKeys.serviceName.tr()), SingleDetailWidget(text: requestVM.acceptedRequestOffer!.serviceItemName ?? "", type: LocaleKeys.serviceName.tr()),
@ -280,6 +298,52 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
), ),
16.height, 16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()), SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
if (requestVM.selectedDeliveryOptionEnum != null && deliveryAddress.isNotEmpty) ...[
16.height,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: SingleDetailWidget(text: deliveryAddress, type: LocaleKeys.location.tr()),
),
if (showMapButton) ...[
8.width,
Row(
children: [
LocaleKeys.openMapLocation.tr().toText(
fontSize: 12,
isBold: true,
color: MyColors.primaryColor,
isUnderLine: true,
),
4.width,
Image.asset(
MyAssets.icRightUpPng,
height: 6,
width: 6,
color: MyColors.primaryColor,
),
],
).onPress(() async {
double latitude, longitude = 0.0;
latitude = double.parse(requestVM.currentSelectedOffer!.providerLatitude ?? "0.0");
longitude = double.parse(requestVM.currentSelectedOffer!.providerLongitude ?? "0.0");
await Utils.openLocationInMaps(latitude: latitude, longitude: longitude);
}),
],
],
),
if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.delivery && requestVM.additionalAddressSparePartRequestDelivery.isNotEmpty) ...[
8.height,
SingleDetailWidget(text: requestVM.additionalAddressSparePartRequestDelivery, type: LocaleKeys.additionalAddressDetails.tr()),
],
],
),
],
], ],
); );
} }

@ -48,10 +48,21 @@ class RequestItem extends StatelessWidget {
], ],
6.height, 6.height,
"${request.brand} ${request.model} | ${request.id}".toText(fontSize: 16, letterSpacing: -0.64), "${request.brand} ${request.model} | ${request.id}".toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.year.tr()}:", "${request.year}"),
if (request.customerName.isNotEmpty) ...[ if (request.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}:", request.customerName), showItem("${LocaleKeys.customerName.tr()}:", request.customerName),
], ],
if (request.brand.isNotEmpty) ...[
showItem("${LocaleKeys.brand.tr()}:", request.brand),
],
if (request.model.isNotEmpty) ...[
showItem("${LocaleKeys.model.tr()}:", request.model),
],
if (request.year > 0) ...[
showItem("${LocaleKeys.year.tr()}:", "${request.year}"),
],
if (request.vehicleTypeName.isNotEmpty) ...[
showItem("${LocaleKeys.vehicleType.tr()}:", request.vehicleTypeName),
],
showItem("${LocaleKeys.description.tr()}:", request.description), showItem("${LocaleKeys.description.tr()}:", request.description),
], ],
), ),

@ -55,7 +55,7 @@ class SettingOptionsHelp extends StatelessWidget {
size: 20, size: 20,
color: MyColors.greyColor, color: MyColors.greyColor,
), ),
titleText: LocaleKeys.termPrivacy.tr(), titleText: LocaleKeys.termsPrivacyPolicy.tr(),
needBorderBelow: true, needBorderBelow: true,
onTap: () => navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions), onTap: () => navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions),
), ),

@ -60,7 +60,7 @@ class _SettingOptionsTermsAndConditionsState extends State<SettingOptionsTermsAn
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: CustomAppBar( appBar: CustomAppBar(
title: LocaleKeys.termPrivacy.tr(), title: LocaleKeys.termsPrivacyPolicy.tr(),
isRemoveBackButton: false, isRemoveBackButton: false,
isDrawerEnabled: false, isDrawerEnabled: false,
onBackButtonTapped: () => Navigator.pop(context), onBackButtonTapped: () => Navigator.pop(context),

@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
@ -20,7 +19,7 @@ import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AddPhoneNumWidget extends StatefulWidget { class AddPhoneNumWidget extends StatefulWidget {
const AddPhoneNumWidget({Key? key}) : super(key: key); const AddPhoneNumWidget({super.key});
@override @override
State<AddPhoneNumWidget> createState() => _AddPhoneNumWidgetState(); State<AddPhoneNumWidget> createState() => _AddPhoneNumWidgetState();
@ -82,11 +81,34 @@ class _AddPhoneNumWidgetState extends State<AddPhoneNumWidget> {
8.height, 8.height,
TxtField( TxtField(
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
hint: "546758594", hint: "Phone without country code ",
value: phoneNum, value: phoneNum,
isSidePaddingZero: true, isSidePaddingZero: true,
onChanged: (v) { onChanged: (v) {
phoneNum = v; // Remove country code if user enters it
String cleanedPhone = v.trim();
// If country code is selected and phone starts with it, remove it
if (countryCode.isNotEmpty && cleanedPhone.startsWith(countryCode)) {
cleanedPhone = cleanedPhone.substring(countryCode.length).trim();
}
// Also handle cases where user adds + before country code
if (countryCode.isNotEmpty && cleanedPhone.startsWith('+$countryCode')) {
cleanedPhone = cleanedPhone.substring(countryCode.length + 1).trim();
}
// Handle case where user just types + followed by digits matching country code
if (countryCode.isNotEmpty && cleanedPhone.startsWith('+')) {
String codeWithoutPlus = countryCode.replaceAll('+', '');
if (cleanedPhone.substring(1).startsWith(codeWithoutPlus)) {
cleanedPhone = cleanedPhone.substring(codeWithoutPlus.length + 1).trim();
}
}
setState(() {
phoneNum = cleanedPhone;
});
}, },
), ),
16.height, 16.height,
@ -161,10 +183,10 @@ class CustomBottomPicker extends StatelessWidget {
final void Function(DropValue selectedItem) onItemSelected; final void Function(DropValue selectedItem) onItemSelected;
const CustomBottomPicker({ const CustomBottomPicker({
Key? key, super.key,
required this.items, required this.items,
required this.onItemSelected, required this.onItemSelected,
}) : super(key: key); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

@ -58,6 +58,7 @@ class _DropdownFieldState extends State<DropdownField> {
dropdownValue = widget.dropdownValue; dropdownValue = widget.dropdownValue;
return Column( return Column(
children: [ children: [
// Always show hint as label when provided
if (widget.hint != null) ...[ if (widget.hint != null) ...[
Row( Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@ -71,19 +72,41 @@ class _DropdownFieldState extends State<DropdownField> {
), ),
4.height, 4.height,
], ],
IgnorePointer( // Show disabled text field when not selectable
ignoring: !widget.isSelectAble, if (!widget.isSelectAble)
child: Container( Container(
decoration: decoration: Utils.containerColorRadiusBorderWidth(
widget.showAppointmentPickerVariant ? null : Utils.containerColorRadiusBorderWidth(MyColors.white, 0, widget.isSelectAble ? MyColors.darkPrimaryColor : MyColors.greyACColor, 2), MyColors.greyShadowColor,
0,
MyColors.greyACColor,
2
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
width: double.infinity,
child: (dropdownValue?.value ?? "").toText(
color: MyColors.darkTextColor,
fontSize: 15,
fontWeight: MyFonts.Medium,
),
)
else
// Show normal dropdown when selectable
Container(
decoration: widget.showAppointmentPickerVariant
? null
: Utils.containerColorRadiusBorderWidth(
MyColors.white,
0,
MyColors.darkPrimaryColor,
2
),
margin: const EdgeInsets.all(0), margin: const EdgeInsets.all(0),
padding: const EdgeInsets.only(left: 8, right: 8), padding: const EdgeInsets.only(left: 8, right: 8),
width: widget.showAppointmentPickerVariant ? 170 : null, width: widget.showAppointmentPickerVariant ? 170 : null,
child: DropdownButton<DropValue>( child: DropdownButton<DropValue>(
value: dropdownValue, value: dropdownValue,
icon: Icon( icon: const Icon(
Icons.keyboard_arrow_down_sharp, Icons.keyboard_arrow_down_sharp,
color: !widget.isSelectAble ? Colors.transparent : null,
size: 21, size: 21,
), ),
elevation: 16, elevation: 16,
@ -95,7 +118,6 @@ class _DropdownFieldState extends State<DropdownField> {
color: borderColor, color: borderColor,
fontSize: 15, fontSize: 15,
), ),
// hint: (widget.hint ?? "").toText(color: borderColor, fontSize: 15, fontWeight: MyFonts.Medium),
underline: Container(height: 0), underline: Container(height: 0),
onChanged: (DropValue? newValue) { onChanged: (DropValue? newValue) {
setState(() { setState(() {
@ -105,17 +127,20 @@ class _DropdownFieldState extends State<DropdownField> {
}, },
onTap: widget.onTap, onTap: widget.onTap,
items: (widget.list ?? defaultV).map<DropdownMenuItem<DropValue>>( items: (widget.list ?? defaultV).map<DropdownMenuItem<DropValue>>(
(DropValue value) { (DropValue value) {
return DropdownMenuItem<DropValue>( return DropdownMenuItem<DropValue>(
value: value, value: value,
enabled: value.isEnabled ?? true, enabled: value.isEnabled ?? true,
child: value.value.toText(fontSize: 15, color: value.isEnabled == false ? MyColors.darkTextColor : null, fontWeight: MyFonts.Medium), child: value.value.toText(
fontSize: 15,
color: value.isEnabled == false ? MyColors.darkTextColor : null,
fontWeight: MyFonts.Medium
),
); );
}, },
).toList(), ).toList(),
), ),
), ),
),
if (widget.errorValue != "") if (widget.errorValue != "")
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,

Loading…
Cancel
Save