fixing jira bugs

faiz_development_common
Faiz Hashmi 2 days ago
parent e6fc99839f
commit b88aee4632

@ -1,63 +0,0 @@
# 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.

@ -249,7 +249,7 @@ class ApiClientImp implements ApiClient {
logger.i(url);
logger.i("$queryParameters");
}
var response = await _get(Uri.parse(url), headers: headers0).timeout(const Duration(seconds: 60));
var response = await _get(Uri.parse(url), headers: headers0).timeout(const Duration(seconds: 120));
if (!kReleaseMode) {
logger.i(jsonDecode(response.body));

@ -560,7 +560,8 @@ class AdsRepoImp implements AdsRepo {
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.adsExtendDurationCreate,
ApiConsts.
adsExtendDurationCreate,
postParams,
token: token,
);

@ -27,12 +27,15 @@ import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/repositories/ads_repo.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.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/base_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:provider/provider.dart';
@ -1243,26 +1246,153 @@ class AdVM extends BaseVM {
void onBackButtonPressed(BuildContext context) {
switch (currentProgressStep) {
case AdCreationStepsEnum.vehicleDetails:
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
// Check if user has entered any data
bool hasData = vehicleTypeId.selectedId != -1 ||
vehicleBrandId.selectedId != -1 ||
vehicleModelId.selectedId != -1 ||
vehicleModelYearId.selectedId != -1 ||
vehicleColorId.selectedId != -1 ||
vehicleCategoryId.selectedId != -1 ||
vehicleConditionId.selectedId != -1 ||
vehicleMileageId.selectedId != -1 ||
vehicleTransmissionId.selectedId != -1 ||
vehicleCountryId.selectedId != -1 ||
vehicleCityId.selectedId != -1 ||
vehicleDemandAmount.isNotEmpty ||
vehicleVin.isNotEmpty ||
vehicleTitle.isNotEmpty ||
warrantyDuration.isNotEmpty ||
vehicleDescription.isNotEmpty ||
pickedPostingImages.isNotEmpty;
if (hasData) {
// Show confirmation dialog if user has entered data
showSaveAsDraftConfirmationDialog(
context,
onYes: () async {
Navigator.pop(context);
await saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.vehicleDetails, bypassValidation: true);
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
},
onNo: () {
Navigator.pop(context);
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
},
);
} else {
// No data entered, go back directly
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
}
break;
case AdCreationStepsEnum.damageParts:
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
notifyListeners();
showSaveAsDraftConfirmationDialog(
context,
onYes: () async {
Navigator.pop(context);
await saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.damageParts, bypassValidation: true);
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
},
onNo: () {
Navigator.pop(context);
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
notifyListeners();
},
);
break;
case AdCreationStepsEnum.adDuration:
currentProgressStep = AdCreationStepsEnum.damageParts;
notifyListeners();
showSaveAsDraftConfirmationDialog(
context,
onYes: () async {
Navigator.pop(context);
await saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.adDuration, bypassValidation: true);
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
},
onNo: () {
Navigator.pop(context);
currentProgressStep = AdCreationStepsEnum.damageParts;
notifyListeners();
},
);
break;
case AdCreationStepsEnum.reviewAd:
currentProgressStep = AdCreationStepsEnum.adDuration;
notifyListeners();
showSaveAsDraftConfirmationDialog(
context,
onYes: () async {
Navigator.pop(context);
await saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.reviewAd, bypassValidation: true);
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
},
onNo: () {
Navigator.pop(context);
currentProgressStep = AdCreationStepsEnum.adDuration;
notifyListeners();
},
);
break;
}
}
void showSaveAsDraftConfirmationDialog(BuildContext context, {required VoidCallback onYes, required VoidCallback onNo}) {
actionConfirmationBottomSheet(
context: context,
title: "Save As Draft".toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: "Your ad will be saved as draft and you can continue later from where you left off. Do you want to save and go back?",
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.yes.tr(),
fontSize: 15,
onPressed: onYes,
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: LocaleKeys.no.tr(),
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: onNo,
),
),
);
}
Future<int> saveAdVehicleDetailsDraft({required bool isNew, required BuildContext context, required AdCreationStepsEnum stepNoEnum}) async {
AppState appState = injector.get<AppState>();
@ -1354,6 +1484,99 @@ class AdVM extends BaseVM {
}
}
Future<void> saveAdAsDraft({required BuildContext context, required AdCreationStepsEnum stepNoEnum, bool bypassValidation = false}) async {
AppState appState = injector.get<AppState>();
List<int> adsSelectedServices = [];
for (var value in specialServiceCards) {
adsSelectedServices.add(value.serviceSelectedId!.selectedId);
}
Utils.showLoading(context);
try {
Ads ads = Ads(
id: (previousAdDetails != null && previousAdDetails!.id != null) ? previousAdDetails!.id : 0,
adsDurationID: vehicleAdDurationId.selectedId == -1 ? 0 : vehicleAdDurationId.selectedId,
startDate: selectionDurationStartDate.isNotEmpty ? selectionDurationStartDate : null,
countryId: vehicleCountryId.selectedId != -1 ? vehicleCountryId.selectedId : null,
specialServiceIDs: adsSelectedServices,
showContactDetail: isPhoneNumberShown,
isOnWhatsApp: isNumberOnWhatsApp,
);
List<VehiclePostingImages> vehicleImages = [];
for (var image in pickedPostingImages) {
vehicleImages.add(await convertFileToVehiclePostingImages(imageModel: image));
}
List<VehiclePostingDamageParts> vehicleDamageImages = [];
for (var card in vehicleDamageCards) {
if (card.partImages != null && card.partImages!.isNotEmpty) {
for (var image in card.partImages!) {
VehiclePostingDamageParts stringImage = await convertFileToVehiclePostingDamageParts(
imageModel: image,
damagePartId: card.partSelectedId!.selectedId,
commentParam: card.damagePartDescription ?? "",
);
vehicleDamageImages.add(stringImage);
}
}
}
VehiclePosting vehiclePosting = VehiclePosting(
id: (previousAdDetails != null && previousAdDetails!.vehiclePostingID != null) ? previousAdDetails!.vehiclePostingID : null,
userID: appState.getUser.data!.userInfo!.userId,
vehicleType: vehicleTypeId.selectedId != -1 ? vehicleTypeId.selectedId : null,
vehicleModelID: vehicleModelId.selectedId != -1 ? vehicleModelId.selectedId : null,
vehicleModelYearID: vehicleModelYearId.selectedId != -1 ? vehicleModelYearId.selectedId : null,
vehicleColorID: vehicleColorId.selectedId != -1 ? vehicleColorId.selectedId : null,
vehicleCategoryID: vehicleCategoryId.selectedId != -1 ? vehicleCategoryId.selectedId : null,
vehicleConditionID: vehicleConditionId.selectedId != -1 ? vehicleConditionId.selectedId : null,
vehicleMileageID: vehicleMileageId.selectedId != -1 ? vehicleMileageId.selectedId : null,
vehicleTransmissionID: vehicleTransmissionId.selectedId != -1 ? vehicleTransmissionId.selectedId : null,
vehicleSellerTypeID: vehicleSellerTypeId.selectedId == -1 ? 1 : vehicleSellerTypeId.selectedId,
cityID: vehicleCityId.selectedId != -1 ? vehicleCityId.selectedId : null,
price: vehicleDemandAmount.isNotEmpty ? int.tryParse(vehicleDemandAmount) : null,
vehicleVIN: vehicleVin.isNotEmpty ? vehicleVin : null,
vehicleDescription: vehicleDescription.isNotEmpty ? vehicleDescription : null,
vehicleTitle: vehicleTitle.isNotEmpty ? vehicleTitle : null,
vehicleDescriptionN: vehicleDescription.isNotEmpty ? vehicleDescription : null,
isFinanceAvailable: financeAvailableStatus,
warantyYears: warrantyDuration.isNotEmpty ? int.tryParse(warrantyDuration) : null,
demandAmount: vehicleDemandAmount.isNotEmpty ? int.tryParse(vehicleDemandAmount) : null,
vehiclePostingImages: vehicleImages,
vehiclePostingDamageParts: vehicleDamageImages,
phoneNo: (isPhoneNumberShown && adPhoneNumber.isNotEmpty) ? adPhoneNumberDialCode + adPhoneNumber : null,
whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp && adPhoneNumber.isNotEmpty) ? adPhoneNumberDialCode + adPhoneNumber : null,
odometer: odometer.isNotEmpty ? int.tryParse(odometer) : 0,
isInUsed: isInUsed,
isAccidentFree: isAccidentFree,
);
AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting);
GenericRespModel respModel = await adsRepo.createOrUpdateDraftAd(
adsCreationPayloadModel: adsCreationPayloadModel,
isCreateNew: previousAdDetails == null || previousAdDetails!.id == null,
stepNo: stepNoEnum,
);
Utils.hideLoading(context);
if (respModel.messageStatus == 1) {
Utils.showToast('Saved as Draft');
getMyDraftAds();
} else {
Utils.showToast(respModel.message ?? "Failed to save draft");
}
} catch (e) {
Utils.hideLoading(context);
logger.e(e.toString());
Utils.showToast("Error saving draft: ${e.toString()}");
}
}
Future saveAdDamagePartDetailsDraft() async {}
Future saveAdDurationsDraft() async {}

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
@ -7,7 +5,6 @@ import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_duration_container.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_review_containers.dart';
@ -80,14 +77,39 @@ class BuildFooterButton extends StatelessWidget {
builder: (BuildContext context, AdVM adVm, Widget? child) {
switch (adVm.currentProgressStep) {
case AdCreationStepsEnum.vehicleDetails:
return SizedBox(
width: double.infinity,
child: ShowFillButton(
title: LocaleKeys.next.tr(),
onPressed: () {
adVm.updateCurrentStep(context);
},
),
return Row(
children: [
Expanded(
child: ShowFillButton(
txtColor: MyColors.black,
maxHeight: 55,
title: "Save As Draft",
onPressed: () async {
await adVm.saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.vehicleDetails, bypassValidation: true);
adVm.isDraftEditEnabled = false;
adVm.isAdEditEnabled = false;
adVm.currentProgressStep = AdCreationStepsEnum.vehicleDetails;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
},
backgroundColor: MyColors.greyButtonColor,
),
),
12.width,
Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.next.tr(),
onPressed: () {
adVm.updateCurrentStep(context);
},
backgroundColor: MyColors.darkPrimaryColor,
),
),
],
);
case AdCreationStepsEnum.damageParts:
return Row(
@ -96,16 +118,17 @@ class BuildFooterButton extends StatelessWidget {
child: ShowFillButton(
txtColor: MyColors.black,
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
title: "Save As Draft",
onPressed: () async {
await adVm.saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.damageParts, bypassValidation: true);
adVm.isDraftEditEnabled = false;
adVm.isAdEditEnabled = false;
adVm.currentProgressStep = AdCreationStepsEnum.vehicleDetails;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),
@ -130,17 +153,17 @@ class BuildFooterButton extends StatelessWidget {
child: ShowFillButton(
txtColor: MyColors.black,
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
title: "Save As Draft",
onPressed: () async {
await adVm.saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.adDuration, bypassValidation: true);
adVm.isDraftEditEnabled = false;
adVm.isAdEditEnabled = false;
adVm.currentProgressStep = AdCreationStepsEnum.vehicleDetails;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),
@ -165,17 +188,17 @@ class BuildFooterButton extends StatelessWidget {
child: ShowFillButton(
txtColor: MyColors.black,
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
title: "Save As Draft",
onPressed: () async {
await adVm.saveAdAsDraft(context: context, stepNoEnum: AdCreationStepsEnum.reviewAd, bypassValidation: true);
adVm.isDraftEditEnabled = false;
adVm.isAdEditEnabled = false;
adVm.currentProgressStep = AdCreationStepsEnum.vehicleDetails;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),

@ -78,8 +78,7 @@ class SelectAdTypeView extends StatelessWidget {
onTap: () async {
adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""));
if (adVM.isAdEditEnabled) {
adVM.
autoFillSelectedVehicleAdsDetails();
adVM.autoFillSelectedVehicleAdsDetails();
}
if (AppState().currentAppType == AppType.provider) {
if (isFromExtendAd && !adVM.isAdEditEnabled) {

Loading…
Cancel
Save