added lazy loading

aamir_dev
Faiz Hashmi 11 months ago
parent 618a27ab4d
commit 70870f1903

@ -760,5 +760,6 @@
"tapToSeeItems": "اضغط لرؤية العناصر",
"tapToSelect": "اضغط للاختيار",
"noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.",
"requestCreatedOn": "تم إنشاء الطلب في"
"requestCreatedOn": "تم إنشاء الطلب في",
"online": "عبر الإنترنت"
}

@ -758,5 +758,6 @@
"tapToSelect": "Tap to select",
"tapToSeeItems": "Tap to see items",
"noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.",
"requestCreatedOn": "Request created on"
"requestCreatedOn": "Request created on",
"online": "Online"
}

@ -55,7 +55,7 @@ class ApiConsts {
static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get";
static String serviceProviderServiceCreate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create";
static String serviceProviderServiceUpdate = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update";
static String serviceProviderServiceStatusUpdate = "${baseUrlServices}api/ServiceProviders/CategoryAndServiceDeactivateBySP";
static String serviceProviderServiceStatusUpdate = "${baseUrlServices}api/ServiceProviders/CategoryAndService_ActivateDeactivateBySP";
static String getProviderServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String setScheduleInactive = "${baseUrlServices}api/ServiceProviders/BranchAppointmentSchedule_IsActiveUpdate";
static String serviceProviderAppointmentGetByCategoryOrService = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_GetByCategoryOrService";

@ -776,7 +776,8 @@ class CodegenLoader extends AssetLoader{
"tapToSeeItems": "اضغط لرؤية العناصر",
"tapToSelect": "اضغط للاختيار",
"noteCopyItemsExplanation": "ملاحظة: ستتمكن من نسخ العناصر من خدمة إلى أخرى في الفئة المحددة. يجب عليك إنشاء الخدمات أولاً ويجب أن تكون معتمدة. ثم ستتمكن من الحصول على الخدمات المتاحة التي يمكنك نسخ جميع العناصر منها أو تحديد العناصر التي تريد نسخها.",
"requestCreatedOn": "تم إنشاء الطلب في"
"requestCreatedOn": "تم إنشاء الطلب في",
"online": "عبر الإنترنت"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1538,7 +1539,8 @@ static const Map<String,dynamic> en_US = {
"tapToSelect": "Tap to select",
"tapToSeeItems": "Tap to see items",
"noteCopyItemsExplanation": "Note: You will be able to copy items from one service to another in a selected category. You must create the services first and they should be approved. Then you will be able to get the available services from which you can copy all or selected items.",
"requestCreatedOn": "Request created on"
"requestCreatedOn": "Request created on",
"online": "Online"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -740,5 +740,6 @@ abstract class LocaleKeys {
static const tapToSelect = 'tapToSelect';
static const noteCopyItemsExplanation = 'noteCopyItemsExplanation';
static const requestCreatedOn = 'requestCreatedOn';
static const online = 'online';
}

@ -50,6 +50,7 @@ class AdDetailsModel {
String? warrantyYears;
CreatedByRoleEnum? createdByRoleEnum;
List<ChatMessageModel>? adMessages;
int? totalItemsCount;
AdDetailsModel({
this.id,
@ -95,6 +96,7 @@ class AdDetailsModel {
this.createdByRoleEnum,
this.modifiedOn,
this.adMessages,
this.totalItemsCount,
});
int getRandomValue({required int min, required int max}) {
@ -103,7 +105,7 @@ class AdDetailsModel {
return randomNumber;
}
AdDetailsModel.fromJson(Map<String, dynamic> json, bool isMyAds) {
AdDetailsModel.fromJson(Map<String, dynamic> json, bool isMyAds, int totalItems) {
id = json['id'];
startdate = json['startdate'];
enddate = json['enddate'];
@ -150,6 +152,7 @@ class AdDetailsModel {
createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum();
isMyAd = isMyAds;
isReservedByMe = false;
totalItemsCount = totalItems;
}
}

@ -1,10 +1,12 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/models/advertisment_models/ads_bank_details_model.dart';
import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart';
@ -14,6 +16,7 @@ import 'package:mc_common_app/models/advertisment_models/special_service_model.d
import 'package:mc_common_app/models/chat_models/buyers_chat_for_ads_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
abstract class AdsRepo {
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId});
@ -22,7 +25,12 @@ abstract class AdsRepo {
Future<GenericRespModel> createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew});
Future<List<AdDetailsModel>> getAllAds({required bool isMyAds, AdPostStatus? adPostStatus, CreatedByRoleEnum? createdByRoleEnum});
Future<List<AdDetailsModel>> getAllAds({
required bool isMyAds,
AdPostStatus? adPostStatus,
CreatedByRoleEnum? createdByRoleEnum,
int? page,
});
Future<List<AdDetailsModel>> getExploreAdsBasedOnFilters({
List<String>? cityIdsList,
@ -31,6 +39,8 @@ abstract class AdsRepo {
List<String>? createdByRolesIdsList,
List<String>? vehicleAdConditionIdsList,
List<String>? vehicleAdCreatedDateList,
int page,
bool isMyAds = false,
});
Future<List<AdDetailsModel>> getMyReservedAds();
@ -62,10 +72,10 @@ class AdsRepoImp implements AdsRepo {
@override
Future<List<AdsDurationModel>> getAdsDuration({required int? countryId}) async {
int roleID = appState.getUser!.data!.userInfo!.roleId ?? 0;
int roleID = appState.getUser.data!.userInfo!.roleId ?? 0;
var param = {
"CountryID": countryId.toString() ?? "0",
"roleID": roleID.toString() ?? "0",
"CountryID": countryId.toString(),
"roleID": roleID.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
@ -168,7 +178,12 @@ class AdsRepoImp implements AdsRepo {
}
@override
Future<List<AdDetailsModel>> getAllAds({required isMyAds, AdPostStatus? adPostStatus, CreatedByRoleEnum? createdByRoleEnum}) async {
Future<List<AdDetailsModel>> getAllAds({
required isMyAds,
AdPostStatus? adPostStatus,
CreatedByRoleEnum? createdByRoleEnum,
int? page,
}) async {
Map<String, dynamic> onlyMyAdsParams = {
"userID": appState.getUser.data!.userInfo!.userId ?? "",
};
@ -176,6 +191,7 @@ class AdsRepoImp implements AdsRepo {
onlyMyAdsParams.addAll({
"AdsStatuses": ["${adPostStatus.getIdFromAdPostStatusEnum()}"],
"PageSize": "30",
"PageIndex": page != null ? page.toString() : "0",
});
}
var allAdsParams = {
@ -183,6 +199,7 @@ class AdsRepoImp implements AdsRepo {
"isActive": "true", //only Active ADS
"isExplore": "true",
"PageSize": "30",
"PageIndex": page != null ? page.toString() : "0",
};
if (!isMyAds && createdByRoleEnum != null) {
@ -196,7 +213,7 @@ class AdsRepoImp implements AdsRepo {
ApiConsts.vehicleAdsGet,
queryParameters: isMyAds ? onlyMyAdsParams : allAdsParams,
);
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], isMyAds));
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], isMyAds, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails;
}
@ -208,6 +225,8 @@ class AdsRepoImp implements AdsRepo {
List<String>? createdByRolesIdsList,
List<String>? vehicleAdConditionIdsList,
List<String>? vehicleAdCreatedDateList,
int? page,
bool isMyAds = false,
}) async {
var parameters = {
"CityIDs": cityIdsList ?? [],
@ -218,17 +237,29 @@ class AdsRepoImp implements AdsRepo {
"VehicleNew": vehicleAdConditionIdsList ?? [],
"CreatedOn": (vehicleAdCreatedDateList != null && vehicleAdCreatedDateList.isNotEmpty) ? vehicleAdCreatedDateList.first.toString() : "",
"isActive": "true", //only Active ADS
"isExplore": "true",
"isExplore": isMyAds.toString(),
"PageSize": "30",
"PageIndex": page != null ? page.toString() : "1",
};
if (isMyAds) {
parameters.addAll({
"userID": appState.getUser.data!.userInfo!.userId ?? "",
});
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet,
queryParameters: parameters,
);
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], false));
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], false, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails;
}
@ -244,6 +275,11 @@ class AdsRepoImp implements AdsRepo {
ApiConsts.myAdsReserveGet,
queryParameters: params,
);
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<MyReservedAdsRespModel> reservedAds = List.generate(adsGenericModel.data.length, (index) => MyReservedAdsRespModel.fromJson(adsGenericModel.data[index]));
List<String> selectedIdsString = reservedAds.map((component) => component.adsID.toString()).toList();
@ -266,7 +302,11 @@ class AdsRepoImp implements AdsRepo {
queryParameters: params,
ApiConsts.vehicleAdsGet,
);
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true));
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true, adsGenericModel.totalItemsCount ?? 1));
for (int i = 0; i < vehicleAdsDetails.length; i++) {
vehicleAdsDetails[i].adReserveStatus = (reservedAds[i].adsReserveStatus ?? 0).toAdRserveStatusEnum();
@ -288,7 +328,11 @@ class AdsRepoImp implements AdsRepo {
queryParameters: params,
ApiConsts.vehicleAdsGet,
);
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true));
if (adsGenericModel.messageStatus != 1 || adsGenericModel.data == null) {
Utils.showToast(adsGenericModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AdDetailsModel> vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true, adsGenericModel.totalItemsCount ?? 1));
return vehicleAdsDetails;
}

@ -75,6 +75,8 @@ abstract class BranchRepo {
Future<GenericRespModel> updateServiceStatus({required int branchId, required List<int> serviceIds, required ServiceStatusEnum serviceStatusEnum});
Future<GenericRespModel> updateCategoryStatus({required int branchId, required int categoryId, required ServiceStatusEnum serviceStatusEnum});
Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId});
Future<GenericRespModel> getMatchedServices(int oldBranchId, int newBranchId, int categoryId);
@ -236,7 +238,7 @@ class BranchRepoImp implements BranchRepo {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: t,
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.serviceProviderDDLGet,
);
List<ProviderBasicDataModel> providersList = List.generate(adsGenericModel.data.length, (index) => ProviderBasicDataModel.fromJson(adsGenericModel.data[index]));
@ -268,8 +270,7 @@ class BranchRepoImp implements BranchRepo {
serviceProviderBranchImages.add(imageMap);
}
String lat = "0",
long = "0";
String lat = "0", long = "0";
try {
lat = latitude.toString().substring(0, 9);
long = longitude.toString().substring(0, 9);
@ -332,6 +333,19 @@ class BranchRepoImp implements BranchRepo {
return await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.serviceProviderServiceStatusUpdate, queryParameters: map, token: t);
}
@override
Future<GenericRespModel> updateCategoryStatus({required int branchId, required int categoryId, required ServiceStatusEnum serviceStatusEnum}) async {
int providerID = AppState().getUser.data!.userInfo!.providerId;
var map = {
"ServiceProviderID": providerID.toString(),
"ProviderBranchID": branchId.toString(),
"ServiceCategoryID": categoryId.toString(),
"Status": serviceStatusEnum.getIdFromServiceStatusEnum().toString(),
};
String t = AppState().getUser.data!.accessToken ?? "";
return await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.serviceProviderServiceStatusUpdate, queryParameters: map, token: t);
}
@override
Future<List<AppointmentBasicDetailsModel>> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}) async {
var map = {
@ -341,7 +355,7 @@ class BranchRepoImp implements BranchRepo {
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.serviceProviderAppointmentGetByCategoryOrService,
queryParameters: map,
token: t,
@ -416,7 +430,7 @@ class BranchRepoImp implements BranchRepo {
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAllNearBranches,
token: appState.getUser.data!.accessToken,
queryParameters: queryParameters,
@ -444,7 +458,7 @@ class BranchRepoImp implements BranchRepo {
"longitude": longitude.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAllNearBranches,
token: appState.getUser.data!.accessToken,
queryParameters: queryParameters,
@ -456,7 +470,7 @@ class BranchRepoImp implements BranchRepo {
@override
Future<List<BranchDetailModel>> getMyRecentBranchesWithServices() async {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getMyRecentBranches,
token: appState.getUser.data!.accessToken,
);
@ -471,7 +485,7 @@ class BranchRepoImp implements BranchRepo {
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getServiceItems,
token: appState.getUser.data!.accessToken,
queryParameters: serviceId.toString() != "-1" ? queryParameters : null,
@ -491,7 +505,7 @@ class BranchRepoImp implements BranchRepo {
postParams.addAll({"Latitude": "$latitude"});
}
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
return ProviderProfileModel.fromJson(adsGenericModel.data);
}
@ -536,7 +550,7 @@ class BranchRepoImp implements BranchRepo {
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAllNearBranches,
token: appState.getUser.data!.accessToken,
queryParameters: postParams,
@ -550,7 +564,7 @@ class BranchRepoImp implements BranchRepo {
var postParams = {"ServiceProviderBranchID": serviceProviderBranchID.toString()};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.getBranchRatings,
token: appState.getUser.data!.accessToken,
queryParameters: postParams,
@ -564,7 +578,7 @@ class BranchRepoImp implements BranchRepo {
final customerID = appState.getUser.data!.userInfo!.customerId;
final parameters = {"title": title, "review": review, "ratNo": ratingNo, "serviceProviderBranchID": serviceProviderBranchID, "customerID": "$customerID"};
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.createBranchRatings,
parameters,
token: appState.getUser.data!.accessToken,
@ -580,7 +594,7 @@ class BranchRepoImp implements BranchRepo {
"customerID": customerID.toString(),
};
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.favouriteServiceProviderCreate,
parameters,
token: appState.getUser.data!.accessToken,
@ -592,7 +606,7 @@ class BranchRepoImp implements BranchRepo {
Future<GenericRespModel> removeProviderFromFavourite({required int providerID}) async {
final parameters = {"id": providerID.toString()};
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.unFavouriteServiceProvider,
parameters,
token: appState.getUser.data!.accessToken,
@ -607,7 +621,7 @@ class BranchRepoImp implements BranchRepo {
var postParams = {"customerID": customerID.toString()};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
(json) => GenericRespModel.fromJson(json),
ApiConsts.favouriteServiceProviderGet,
token: appState.getUser.data!.accessToken,
queryParameters: postParams,

@ -6,7 +6,6 @@ import 'package:local_auth/local_auth.dart';
import 'package:local_auth_android/local_auth_android.dart';
import 'package:local_auth_darwin/types/auth_messages_ios.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:easy_localization/easy_localization.dart';
abstract class CommonAuthServices {
@ -18,10 +17,11 @@ abstract class CommonAuthServices {
class CommonAuthImp implements CommonAuthServices {
final LocalAuthentication localAuth = LocalAuthentication();
@override
Future<bool> authenticate() async {
try {
final availableBiometrics = await localAuth.getAvailableBiometrics();
if (availableBiometrics == null || availableBiometrics.isEmpty) {
if (availableBiometrics.isEmpty) {
return false;
}

@ -201,6 +201,8 @@ class AdVM extends BaseVM {
}
applyFilterOnExploreAds({required CreatedByRoleEnum createdByRoleFilter}) async {
pageIndexForExploreAds = 1;
hasMoreDataForExploreAds = true;
if (exploreAdsFilterOptions.isEmpty) return;
int index = exploreAdsFilterOptions.indexWhere((element) => element.id.toCreatedByRoleEnum() == createdByRoleFilter);
@ -219,18 +221,71 @@ class AdVM extends BaseVM {
notifyListeners();
}
int currentPageForExploreAds = 1;
int currentPageForMyAds = 1;
int pageIndexForExploreAds = 1;
int pageIndexForMyAds = 1;
bool hasMoreDataForExploreAds = true;
bool hasMoreDataForMyAds = true;
bool isLoadingMore = false;
bool hasMoreData = true;
fetchMoreAds() async {}
Future<void> fetchMoreExploreAds() async {
if (isLoadingMore) return;
isLoadingMore = true;
hasMoreDataForExploreAds = true;
notifyListeners();
try {
final List<AdDetailsModel> newAds = await adsRepo.getExploreAdsBasedOnFilters(page: pageIndexForExploreAds);
if (newAds.isEmpty) {
hasMoreDataForExploreAds = false;
} else {
exploreAdsFilteredList.addAll(newAds);
pageIndexForExploreAds++;
if (exploreAdsFilteredList.length < exploreAdsFilteredList.last.totalItemsCount!) {
hasMoreDataForExploreAds = true;
} else {
hasMoreDataForExploreAds = false;
}
}
} catch (error) {
isLoadingMore = false;
Utils.showToast(error.toString());
}
isLoadingMore = false;
notifyListeners();
}
Future<void> fetchMoreMyAds({required AdPostStatus adsStatus}) async {
if (isLoadingMore) return;
hasMoreDataForMyAds = true;
isLoadingMore = true;
notifyListeners();
try {
final List<AdDetailsModel> newAds = await adsRepo.getAllAds(page: pageIndexForMyAds, isMyAds: true, adPostStatus: adsStatus);
if (newAds.isEmpty) {
hasMoreDataForMyAds = false;
} else {
myAdsFilteredList.addAll(newAds);
pageIndexForMyAds++;
if (myAdsFilteredList.length < myAdsFilteredList.last.totalItemsCount!) {
hasMoreDataForMyAds = true;
} else {
hasMoreDataForMyAds = false;
}
}
} catch (error) {
isLoadingMore = false;
Utils.showToast(error.toString());
}
isLoadingMore = false;
notifyListeners();
}
Future<List<AdDetailsModel>> getAdsByFilter({AdPostStatus? adPostStatus, required bool isMyAds, CreatedByRoleEnum? createdByRoleEnum}) async {
return await adsRepo.getAllAds(isMyAds: isMyAds, adPostStatus: adPostStatus, createdByRoleEnum: createdByRoleEnum);
}
applyFilterOnMyAds({required AdPostStatus adPostStatusEnum}) async {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
if (myAdsFilterOptions.isEmpty) return;
int index = myAdsFilterOptions.indexWhere((element) => element.id.toAdPostEnum() == adPostStatusEnum);
@ -265,7 +320,7 @@ class AdVM extends BaseVM {
if (genericRespModel.messageStatus == null) {
Utils.hideLoading(context);
Utils.showToast(genericRespModel.message ?? "Something went wrong!");
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
return false;
}
Utils.hideLoading(context);
@ -273,6 +328,8 @@ class AdVM extends BaseVM {
}
Future<void> getExploreAds() async {
pageIndexForExploreAds = 1;
hasMoreDataForExploreAds = true;
setState(ViewState.busy);
exploreAds = await adsRepo.getAllAds(isMyAds: false);
exploreAdsFilteredList = exploreAds;
@ -281,6 +338,8 @@ class AdVM extends BaseVM {
}
Future<void> getMyAds() async {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
setState(ViewState.busy);
myAds = await adsRepo.getAllAds(isMyAds: true);
myAdsFilteredList = myAds;
@ -1581,6 +1640,11 @@ class AdVM extends BaseVM {
Future<void> populateDataForAdFilter() async {
setState(ViewState.busy);
pageIndexForExploreAds = 1;
pageIndexForMyAds = 1;
hasMoreDataForExploreAds = true;
hasMoreDataForMyAds = true;
isLoadingMore = false;
if (vehicleConditionsEnum.isEmpty) {
vehicleConditionsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.conditionEnumId);
@ -1846,13 +1910,13 @@ class AdVM extends BaseVM {
}
exploreAdsFilteredList = await adsRepo.getExploreAdsBasedOnFilters(
cityIdsList: cityIdsList,
createdByRolesIdsList: adOwnerIdsList,
vehicleBrandIdsList: brandsIdsList,
vehicleModelYearIdsList: vehicleYearIdsList,
vehicleAdConditionIdsList: conditionsIdsList,
vehicleAdCreatedDateList: createdDatesList,
);
cityIdsList: cityIdsList,
createdByRolesIdsList: adOwnerIdsList,
vehicleBrandIdsList: brandsIdsList,
vehicleModelYearIdsList: vehicleYearIdsList,
vehicleAdConditionIdsList: conditionsIdsList,
vehicleAdCreatedDateList: createdDatesList,
page: pageIndexForExploreAds);
setState(ViewState.idle);
}
@ -1944,7 +2008,9 @@ class AdVM extends BaseVM {
updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.label ?? ""));
updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? ""));
updateSelectionVehicleMileageId(SelectionModel(
selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}"));
selectedId: previousAdDetails!.vehicle!.mileage!.id!,
selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}",
));
updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? ""));
updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? ""));
int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID);

@ -92,6 +92,38 @@ class RequestsVM extends BaseVM {
setState(ViewState.idle);
}
int pageIndexForRequests = 1;
bool hasMoreDataRequests = true;
bool isLoadingMore = false;
// Future<void> fetchMoreRequests() async {
// log("isLoadingMore: $isLoadingMore");
// log("hasMoreDataRequests: $hasMoreDataRequests");
// if (isLoadingMore) return;
// isLoadingMore = true;
// hasMoreDataRequests = true;
// notifyListeners();
// try {
// final List<RequestModel> newRequests = await requestRepo.getRequestsBasedOnFilters(requestedDate: requestedDateFilter, requestTypeId: requestTypeId);
// if (newAds.isEmpty) {
// hasMoreDataForExploreAds = false;
// } else {
// exploreAdsFilteredList.addAll(newAds);
// pageIndexForExploreAds++;
// if (exploreAdsFilteredList.length < exploreAdsFilteredList.last.totalItemsCount!) {
// hasMoreDataForExploreAds = true;
// } else {
// hasMoreDataForExploreAds = false;
// }
// }
// } catch (error) {
// isLoadingMore = false;
// Utils.showToast(error.toString());
// }
// isLoadingMore = false;
// notifyListeners();
// }
Future<bool> getRequestsBasedOnFilters() async {
myFilteredRequests.clear();
setState(ViewState.busy);
@ -127,7 +159,7 @@ class RequestsVM extends BaseVM {
);
setState(ViewState.idle);
return true;
} catch (e, s) {
} catch (e) {
logger.i("e: ${e.toString()}");
setState(ViewState.idle);
return false;
@ -1061,7 +1093,7 @@ class RequestsVM extends BaseVM {
pop(context);
}
}
} catch (e, s) {
} catch (e) {
Utils.hideLoading(context);
log(e.toString());
Utils.showToast(e.toString());

@ -272,11 +272,7 @@ class ServiceVM extends BaseVM {
context,
allowMultiple: false,
);
if (files != null && files.any((element) =>
element.path
.split('.')
.last
.toLowerCase() != 'pdf')) {
if (files != null && files.any((element) => element.path.split('.').last.toLowerCase() != 'pdf')) {
Utils.showToast("Only PDF Files are allowed");
return;
}
@ -290,8 +286,8 @@ class ServiceVM extends BaseVM {
documentID == 1
? commerceCertificates.addAll(imageModels)
: documentID == 2
? commercialCertificates.addAll(imageModels)
: vatCertificates.addAll(imageModels);
? commercialCertificates.addAll(imageModels)
: vatCertificates.addAll(imageModels);
document!.data![index].document = Utils.convertFileToBase64(files.first);
document!.data![index].fileExt = Utils.checkFileExt(files.first.path);
document!.data![index].documentUrl = files.first.path;
@ -467,10 +463,10 @@ class ServiceVM extends BaseVM {
DropValue(
element.id ?? 0,
((element.categoryName!.isEmpty
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
"N/A"),
"",
),
@ -567,6 +563,25 @@ class ServiceVM extends BaseVM {
}
}
Future<bool> updateCategoryStatus({required BuildContext context, required ServiceStatusEnum serviceStatusEnum, required int branchId, required int categoryId}) async {
try {
Utils.showLoading(context);
GenericRespModel genericRespModel = await branchRepo.updateCategoryStatus(
branchId: branchId,
categoryId: categoryId,
serviceStatusEnum: serviceStatusEnum,
);
Utils.hideLoading(context);
Utils.showToast(genericRespModel.message ?? "");
return genericRespModel.messageStatus == 1;
} catch (e) {
Utils.hideLoading(context);
log(e.toString());
Utils.showToast(e.toString());
return false;
}
}
Future buildDealNotCompletedBottomSheetOptions({required BuildContext mainContext, required List<AppointmentBasicDetailsModel> appointments, required String branchName}) async {
return actionConfirmationBottomSheet(
isOnlyOneButton: true,
@ -751,9 +766,7 @@ class ServiceVM extends BaseVM {
File file = File(imageModel.filePath!);
List<int> imageBytes = await file.readAsBytes();
String image = base64Encode(imageBytes);
String fileName = file.path
.split('/')
.last;
String fileName = file.path.split('/').last;
branchPostingImages = BranchPostingImages(
imageName: fileName,
imageStr: image,

@ -21,12 +21,14 @@ class AdsListWidget extends StatelessWidget {
final ScrollPhysics? scrollPhysics;
final bool isAdsFragment;
final bool shouldShowAdStatus;
final bool hasMoreData;
final Function()? onFetchMoreAds;
const AdsListWidget({
super.key,
required this.adsList,
required this.shouldShowAdStatus,
required this.hasMoreData,
this.onFetchMoreAds,
this.scrollPhysics,
this.isAdsFragment = false,
@ -44,7 +46,8 @@ class AdsListWidget extends StatelessWidget {
}
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && context.read<AdVM>().hasMoreData) {
log("hasMoreData: $hasMoreData");
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && hasMoreData) {
if (onFetchMoreAds != null) {
onFetchMoreAds!();
}

@ -771,7 +771,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
] else if (AppState().currentAppType == AppType.provider &&
chatMessageTypeEnum == ChatMessageTypeEnum.offer &&
widget.chatMessageModel.reqOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.offer &&
(widget.chatMessageModel.isMyMessage == true)) ...[
(widget.chatMessageModel.isMyMessage == true && widget.chatMessageModel.reqOffer != null && widget.chatMessageModel.reqOffer!.id != null)) ...[
MyAssets.icEdit.buildSvg(color: MyColors.white, height: 15).onPress(() => onOfferEditIconPressed()),
],
Expanded(

@ -79,7 +79,9 @@ class AdsFragment extends StatelessWidget {
title: LocaleKeys.exploreAds.tr(),
txtColor: adVM.isExploreAdsTapped ? MyColors.white : MyColors.darkTextColor,
onPressed: () {
print("accessToken: ${AppState().getUser.data!.accessToken}");
log("accessToken: ${AppState().getUser.data!.accessToken}");
log("AppState().getUser.data!.userInfo!.userId;: ${AppState().getUser.data!.userInfo!.userId}");
if (adVM.myAds.isEmpty) {
adVM.getMyAds();
}
@ -107,7 +109,9 @@ class AdsFragment extends StatelessWidget {
16.height,
FiltersList(
filterList: adVM.exploreAdsFilterOptions,
onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum()),
onFilterTapped: (index, selectedFilterId) {
adVM.applyFilterOnExploreAds(createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum());
},
needLeftPadding: false,
).paddingOnly(left: 21),
]
@ -115,7 +119,9 @@ class AdsFragment extends StatelessWidget {
16.height,
FiltersList(
filterList: adVM.myAdsFilterOptions,
onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnMyAds(adPostStatusEnum: selectedFilterId.toAdPostEnum()),
onFilterTapped: (index, selectedFilterId) {
adVM.applyFilterOnMyAds(adPostStatusEnum: selectedFilterId.toAdPostEnum());
},
needLeftPadding: false,
).paddingOnly(left: 21),
],
@ -141,12 +147,26 @@ class AdsFragment extends StatelessWidget {
isAdsFragment: true,
shouldShowAdStatus: !adVM.isExploreAdsTapped,
adsList: getAdsList(adVM),
onFetchMoreAds: () {
log("fetch more ads");
hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds,
onFetchMoreAds: () async {
AdPostStatus adPostStatusEnum = adVM.myAdsFilterOptions.firstWhere((element) => element.isSelected).id.toAdPostEnum();
if (adVM.isExploreAdsTapped) {
await adVM.fetchMoreExploreAds();
} else {
await adVM.fetchMoreMyAds(adsStatus: adPostStatusEnum);
}
},
),
),
)
),
if (adVM.isLoadingMore) ...[
const Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
))
]
],
),
),

@ -162,6 +162,7 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
16.height,
SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()),
16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
],
),
),
@ -186,12 +187,14 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
16.height,
SingleDetailWidget(text: requestCreatedOn, type: LocaleKeys.requestCreatedOn.tr()),
],
16.height,
SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()),
],
),
),
],
),
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
],
);
}

@ -1,15 +1,51 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:provider/provider.dart';
class SplashPage extends StatelessWidget {
const SplashPage({Key? key}) : super(key: key);
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@override
Widget build(BuildContext context) {
SplashPageState createState() => SplashPageState();
}
class SplashPageState extends State<SplashPage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
performTimer(context);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
final chatVM = context.read<ChatVM>();
chatVM.buildHubConnection(context);
}
}
// Timer function to navigate after a delay
performTimer(BuildContext context) {
Utils.delay(3).whenComplete(() {
navigateReplaceWithName(context, AppRoutes.registerSelection);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
@ -17,37 +53,36 @@ class SplashPage extends StatelessWidget {
color: Colors.black,
child: Column(
children: [
Utils. mExp(1),
// Spacer widget for flexible spacing
Utils.mExp(1),
// Logo Image
Expanded(
child: Image.asset(
MyAssets.icLogoWhitePng,
),
),
// Car Image (flex value adjusted to make it more responsive)
Expanded(
flex: 10,
child: Image.asset(
MyAssets.bnCar,
fit: BoxFit.cover,
width: double.infinity,
height: 00,
height: double.infinity, // Use full height in this expanded section
),
),
// Engine Image
Expanded(
flex: 3,
child: Image.asset(
MyAssets.icEnginePng,
),
),
// Spacer widget again for spacing
Utils.mExp(1),
],
),
),
);
}
performTimer(BuildContext context) {
Utils.delay(3).whenComplete(() {
navigateReplaceWithName(context, AppRoutes.registerSelection);
});
}
}

Loading…
Cancel
Save