Merge branch 'faiz_development_common' into master_new_changes

# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/generated/codegen_loader.g.dart
#	lib/generated/locale_keys.g.dart
#	lib/utils/location/Location.dart
#	lib/view_models/service_view_model.dart
#	lib/view_models/subscriptions_view_model.dart
#	lib/views/location_views/map_selection_widget.dart
#	lib/views/location_views/pick_location_page.dart
#	lib/views/setting_options/provider_license_page.dart
master_new_changes
Aamir 1 year ago
commit 1b37692dd7

@ -242,6 +242,7 @@
"payLater": "ادفع لاحقًا",
"complete": "اكتمل",
"makeAnOffer": "قدم عرضًا",
"provideOffer": "تقديم العرض",
"enterAmount": "أدخل المبلغ",
"submit": "إرسال",
"viewChat": "عرض الدردشة",
@ -491,8 +492,7 @@
"submitAd": "إرسال الإعلان",
"selectAdType": "اختر نوع الإعلان",
"validUntilSubscriptionExpiration": "صالح حتى انتهاء الاشتراك",
"adsRemainingVar": "الإعلانات المتبقية",
"youLeftAdsGivenSubscription": "لقد بقي لديك 05 من 50 إعلانًا في الاشتراك.",
"youLeftAdsGivenSubscription": "لقد تركت مع إعلانات محدودة الواردة في الاشتراك.",
"updateSubscription": "تحديث الاشتراك",
"workInProgress": "العمل جارٍ",
"visitCompleted": "تمت الزيارة",
@ -516,7 +516,6 @@
"itemsSelected": "العناصر المحددة",
"workshopFullAccessServices": "بعض الخدمات غير متوفرة في الموقع المنزلي. قم بتغيير الموقع إلى ورشة العمل للوصول الكامل إلى الخدمات",
"changeLocationService": "تغيير الموقع أو الخدمة:",
"noItemstoShow": "لا توجد عناصر لعرضها.",
"someDescriptionSubServices": "بعض الوصف عن الخدمات الفرعية",
"selectServicesYouWant": "اختر الخدمات التي تريدها",
"selectServiceType": "اختر نوع الخدمة",
@ -680,5 +679,11 @@
"inviteFriendsByEmail": "دعوة الأصدقاء عبر البريد الإلكتروني",
"noFAQsToShow": "لا توجد أسئلة شائعة في الوقت الحالي. يرجى الاتصال بنا إذا كان لديك أي استفسار.",
"appInfo": "معلومات التطبيق",
"attachPDF": "إرفاق قوات الدفاع الشعبي"
"users": "المستخدمين",
"adsRemaining": "الإعلانات المتبقية",
"attachPDF": "إرفاق PDF",
"noItemsToShow": "لا توجد عناصر لعرضها.",
"serviceItem": "عنصر الخدمة",
"createdBy": "تم الإنشاء بواسطة",
"createGroupServices": "إنشاء خدمات المجموعة"
}

@ -242,6 +242,7 @@
"payLater": "Pay Later",
"complete": "Complete",
"makeAnOffer": "Make an offer",
"provideOffer": "Provider Offer",
"enterAmount": "Enter amount",
"submit": "Submit",
"viewChat": "View Chat",
@ -492,8 +493,7 @@
"submitAd": "Submit Ad",
"selectAdType": "Select Ad Type",
"validUntilSubscriptionExpiration": "Valid Until Subscription Expiration",
"adsRemainingVar ": "Ads Remaining",
"youLeftAdsGivenSubscription": "You have left with 05 out of 50 ads given in the subscription.",
"youLeftAdsGivenSubscription": "You have left with limited ads given in the subscription.",
"updateSubscription": "Update Subscription",
"workInProgress": "Work In Progress",
"visitCompleted": "Visit Completed",
@ -517,7 +517,6 @@
"itemsSelected": "Item(s) Selected",
"workshopFullAccessServices": "Few services are not available on home location. Change the location to workshop to full access the services",
"changeLocationService": "Change location or service:",
"noItemstoShow": "No Items to show.",
"someDescriptionSubServices": "Some description about the sub-services",
"selectServicesYouWant": "Select services you want",
"selectServiceType": "Select service type",
@ -584,11 +583,11 @@
"addNewAppointment": "Add New Appointment",
"myNearbyBranches": "My Nearby Branches",
"myRecentBranches": "My Recent Branches",
"favoriteList": "Favourite List",
"favoriteList": "Favorite List",
"noReviewsBranch": "This branch has no reviews.",
"readLess": "Read Less",
"readMoreReviews": "Read More Reviews",
"noProvidersInFav": "You have no providers in Favourites.",
"noProvidersInFav": "You have no providers in Favorites.",
"providerHasNoBranches": "This Provider has no branches yet.",
"totalBranches": "Total Branches",
"memberSince": "Member Since",
@ -678,5 +677,11 @@
"inviteFriendsByEmail": "Invite Friends By Email",
"noFAQsToShow": "There are no Frequently asked Questions Right now. Please contact us if you have any query.",
"appInfo": "App Info",
"attachPDF": "Attach PDF"
"users": "Users",
"adsRemaining": "Ads Remaining",
"attachPDF": "Attach PDF",
"noItemsToShow": "No Items to show.",
"serviceItem": "Service Item",
"createdBy": "Created By",
"createGroupServices": "Create Group Services"
}

@ -41,7 +41,7 @@ class AppState {
currentAppType = appType;
}
User? _user = null;
User? _user;
set setUser(v) => _user = v;

@ -31,6 +31,7 @@ class AppDependencies {
injector.registerSingleton<ApiClient>(() => ApiClientImp());
injector.registerSingleton<CommonAppServices>(() => CommonServicesImp());
injector.registerSingleton<PaymentService>(() => PaymentServiceImp());
injector.registerSingleton<Location>(() => LocationService());
injector.registerSingleton<FirebaseMessagingService>(() => FirebaseMessagingServiceImp(
firebaseMessaging: FirebaseMessaging.instance,
flutterLocalNotifications: FlutterLocalNotificationsPlugin(),

@ -69,6 +69,43 @@ class AppRoutes {
static const String changeEmailPage = "/changeEmailPage";
static const String editAccountPage = "/editAccoundPage";
// Provider App Routes
//settings
static const defineLicense = "/defineLicese";
static const String dealershipSetting = "/dealershipSetting";
static const String branchList = "/branchList";
static const String branchDetail = "/branchDetail";
static const String defineBranch = "/defineBranch";
//Appointments
static const String appointment = "/appointment";
static const String appointmentDetailList = "/appointmentDetailList";
static const String updateAppointmentPage = "/updateAppointmentPage";
static const String addServiceInAppointment = "/addServiceInAppointment";
static const String mergeAppointments = "/mergeAppointments";
//Services
static const String dealerUser = "/dealerUser";
static const String servicesList = "/servicesList";
static const String itemsList = "/itemsList";
static const String createItem = "/createItem";
static const String createServices = "/createServices";
static const String createServices2 = "/createServices2";
static const String createServices3 = "/createServices3";
//Schedules
static const String schedulesList = "/schedulesList";
static const String addSchedule = "/addSchedule";
// Subscriptions
static const String mySubscriptionsPage = "/mySubscriptionsPage";
static const String subscriptionsPage = "/subscriptionsPage";
//Bracnh Duplication
static const String matchServices = "/matchServices";
static const String userSettings = "/userSettings";
static const String dashboard = "/dashboard";
static const String bookProviderAppView = "/bookProviderAppView";
@ -100,17 +137,13 @@ class AppRoutes {
static const String providerProfileView = "/providerProfilePage";
static const String favoriteListView = "/favoriteListView";
// Subscriptions
static const String mySubscriptionsPage = "/mySubscriptionsPage";
static const String subscriptionsPage = "/subscriptionsPage";
//Requests
static const String requestsDetailPage = "/requestsDetailPage";
static const String sendOfferPage = "/sendOfferPage";
static const String myRequestsPage = "/myRequestsPage";
static const String requestsFilterView = "/requestsFilterView";
static const String createRequestPage = "/createRequestPage";
static const String offersListPage = "/offersListPage";
static const String requestsDetailPage = "/requestsDetailPage";
static const String sendOfferPage = "/sendOfferPage";
static const String reviewRequestOffer = "/reviewRequestOffer";
//Setting Options
@ -126,14 +159,8 @@ class AppRoutes {
//Profile Screen
static const String profileView = "/profileView";
static const providerLicensePage = "/providerLicensePage";
//Provider User Page
static const dealerUser = "/dealerUser";
// HomePage Provider
static const String generalChatsListForProvider = "/generalChatsListForProvider";
//Chat

@ -633,11 +633,11 @@ extension DateTimeConversions on DateTime {
} else if (difference.inHours >= 1) {
return (numericDates) ? '1 hour ago' : 'An hour ago';
} else if (difference.inMinutes >= 2) {
return '${difference.inMinutes} minutes ago';
return '${difference.inMinutes} min ago';
} else if (difference.inMinutes >= 1) {
return (numericDates) ? '1 minute ago' : 'A minute ago';
return (numericDates) ? '1 min ago' : 'A min ago';
} else if (difference.inSeconds >= 3) {
return '${difference.inSeconds} seconds ago';
return '${difference.inSeconds} sec ago';
} else {
return 'Just now';
}

@ -258,6 +258,7 @@ class CodegenLoader extends AssetLoader{
"payLater": "ادفع لاحقًا",
"complete": "اكتمل",
"makeAnOffer": "قدم عرضًا",
"provideOffer": "تقديم العرض",
"enterAmount": "أدخل المبلغ",
"submit": "إرسال",
"viewChat": "عرض الدردشة",
@ -507,8 +508,7 @@ class CodegenLoader extends AssetLoader{
"submitAd": "إرسال الإعلان",
"selectAdType": "اختر نوع الإعلان",
"validUntilSubscriptionExpiration": "صالح حتى انتهاء الاشتراك",
"adsRemainingVar": "الإعلانات المتبقية",
"youLeftAdsGivenSubscription": "لقد بقي لديك 05 من 50 إعلانًا في الاشتراك.",
"youLeftAdsGivenSubscription": "لقد تركت مع إعلانات محدودة الواردة في الاشتراك.",
"updateSubscription": "تحديث الاشتراك",
"workInProgress": "العمل جارٍ",
"visitCompleted": "تمت الزيارة",
@ -532,7 +532,6 @@ class CodegenLoader extends AssetLoader{
"itemsSelected": "العناصر المحددة",
"workshopFullAccessServices": "بعض الخدمات غير متوفرة في الموقع المنزلي. قم بتغيير الموقع إلى ورشة العمل للوصول الكامل إلى الخدمات",
"changeLocationService": "تغيير الموقع أو الخدمة:",
"noItemstoShow": "لا توجد عناصر لعرضها.",
"someDescriptionSubServices": "بعض الوصف عن الخدمات الفرعية",
"selectServicesYouWant": "اختر الخدمات التي تريدها",
"selectServiceType": "اختر نوع الخدمة",
@ -696,7 +695,13 @@ class CodegenLoader extends AssetLoader{
"inviteFriendsByEmail": "دعوة الأصدقاء عبر البريد الإلكتروني",
"noFAQsToShow": "لا توجد أسئلة شائعة في الوقت الحالي. يرجى الاتصال بنا إذا كان لديك أي استفسار.",
"appInfo": "معلومات التطبيق",
"attachPDF": "إرفاق قوات الدفاع الشعبي"
"users": "المستخدمين",
"adsRemaining": "الإعلانات المتبقية",
"attachPDF": "إرفاق PDF",
"noItemsToShow": "لا توجد عناصر لعرضها.",
"serviceItem": "عنصر الخدمة",
"createdBy": "تم الإنشاء بواسطة",
"createGroupServices": "إنشاء خدمات المجموعة"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -942,6 +947,7 @@ static const Map<String,dynamic> en_US = {
"payLater": "Pay Later",
"complete": "Complete",
"makeAnOffer": "Make an offer",
"provideOffer": "Provider Offer",
"enterAmount": "Enter amount",
"submit": "Submit",
"viewChat": "View Chat",
@ -1192,8 +1198,7 @@ static const Map<String,dynamic> en_US = {
"submitAd": "Submit Ad",
"selectAdType": "Select Ad Type",
"validUntilSubscriptionExpiration": "Valid Until Subscription Expiration",
"adsRemainingVar ": "Ads Remaining",
"youLeftAdsGivenSubscription": "You have left with 05 out of 50 ads given in the subscription.",
"youLeftAdsGivenSubscription": "You have left with limited ads given in the subscription.",
"updateSubscription": "Update Subscription",
"workInProgress": "Work In Progress",
"visitCompleted": "Visit Completed",
@ -1217,7 +1222,6 @@ static const Map<String,dynamic> en_US = {
"itemsSelected": "Item(s) Selected",
"workshopFullAccessServices": "Few services are not available on home location. Change the location to workshop to full access the services",
"changeLocationService": "Change location or service:",
"noItemstoShow": "No Items to show.",
"someDescriptionSubServices": "Some description about the sub-services",
"selectServicesYouWant": "Select services you want",
"selectServiceType": "Select service type",
@ -1284,11 +1288,11 @@ static const Map<String,dynamic> en_US = {
"addNewAppointment": "Add New Appointment",
"myNearbyBranches": "My Nearby Branches",
"myRecentBranches": "My Recent Branches",
"favoriteList": "Favourite List",
"favoriteList": "Favorite List",
"noReviewsBranch": "This branch has no reviews.",
"readLess": "Read Less",
"readMoreReviews": "Read More Reviews",
"noProvidersInFav": "You have no providers in Favourites.",
"noProvidersInFav": "You have no providers in Favorites.",
"providerHasNoBranches": "This Provider has no branches yet.",
"totalBranches": "Total Branches",
"memberSince": "Member Since",
@ -1378,7 +1382,13 @@ static const Map<String,dynamic> en_US = {
"inviteFriendsByEmail": "Invite Friends By Email",
"noFAQsToShow": "There are no Frequently asked Questions Right now. Please contact us if you have any query.",
"appInfo": "App Info",
"attachPDF": "Attach PDF"
"users": "Users",
"adsRemaining": "Ads Remaining",
"attachPDF": "Attach PDF",
"noItemsToShow": "No Items to show.",
"serviceItem": "Service Item",
"createdBy": "Created By",
"createGroupServices": "Create Group Services"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -222,6 +222,7 @@ abstract class LocaleKeys {
static const payLater = 'payLater';
static const complete = 'complete';
static const makeAnOffer = 'makeAnOffer';
static const provideOffer = 'provideOffer';
static const enterAmount = 'enterAmount';
static const submit = 'submit';
static const viewChat = 'viewChat';
@ -470,7 +471,6 @@ abstract class LocaleKeys {
static const submitAd = 'submitAd';
static const selectAdType = 'selectAdType';
static const validUntilSubscriptionExpiration = 'validUntilSubscriptionExpiration';
static const adsRemainingVar = 'adsRemainingVar';
static const youLeftAdsGivenSubscription = 'youLeftAdsGivenSubscription';
static const updateSubscription = 'updateSubscription';
static const workInProgress = 'workInProgress';
@ -495,7 +495,6 @@ abstract class LocaleKeys {
static const itemsSelected = 'itemsSelected';
static const workshopFullAccessServices = 'workshopFullAccessServices';
static const changeLocationService = 'changeLocationService';
static const noItemstoShow = 'noItemstoShow';
static const someDescriptionSubServices = 'someDescriptionSubServices';
static const selectServicesYouWant = 'selectServicesYouWant';
static const selectServiceType = 'selectServiceType';
@ -659,6 +658,12 @@ abstract class LocaleKeys {
static const inviteFriendsByEmail = 'inviteFriendsByEmail';
static const noFAQsToShow = 'noFAQsToShow';
static const appInfo = 'appInfo';
static const users = 'users';
static const adsRemaining = 'adsRemaining';
static const attachPDF = 'attachPDF';
static const noItemsToShow = 'noItemsToShow';
static const serviceItem = 'serviceItem';
static const createdBy = 'createdBy';
static const createGroupServices = 'createGroupServices';
}

@ -134,11 +134,11 @@ class AdDetailsModel {
priceExcludingDiscount = json['priceExcludingDiscount'];
reservePrice = json['reservePrice'];
isMCHandled = json['isMCHandled'];
modifiedOn = json['modifiedOn'];
phoneNo = json['phoneNo'];
whatsAppNo = json['whatsAppNo'];
modifiedOn = json['modifiedOn'];
phoneNo = json['vehicle'] != null ? (json['vehicle']['mobileNo'] ?? "") : "";
whatsAppNo = json['vehicle'] != null ? (json['vehicle']['whatsAppNo'] ?? "") : "";
warrantyYears = json['vehicle'] != null ? (json['vehicle']['warantyYears'] != null ? ((json['vehicle']['warantyYears']).toString()) : "") : "";
adOwnerName = json['adOwnerName'] ?? "";
warrantyYears = json['warantyYears'] ?? "";
adPostStatus = (json['statusID'] as int).toAdPostEnum();
adReserveStatus = AdReserveStatus.defaultStatus;
createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum();
@ -174,32 +174,31 @@ class Vehicle {
int? countryID;
String? currency;
Vehicle(
{this.id,
this.cityID,
this.cityName,
this.demandAmount,
this.isActive,
this.isFinanceAvailable,
this.status,
this.statustext,
this.category,
this.color,
this.condition,
this.mileage,
this.model,
this.modelyear,
this.sellertype,
this.transmission,
this.duration,
this.image,
this.damagereport,
this.vehicleDescription,
this.vehicleTitle,
this.vehicleType,
this.vehicleVIN,
this.countryID,
this.currency});
Vehicle({this.id,
this.cityID,
this.cityName,
this.demandAmount,
this.isActive,
this.isFinanceAvailable,
this.status,
this.statustext,
this.category,
this.color,
this.condition,
this.mileage,
this.model,
this.modelyear,
this.sellertype,
this.transmission,
this.duration,
this.image,
this.damagereport,
this.vehicleDescription,
this.vehicleTitle,
this.vehicleType,
this.vehicleVIN,
this.countryID,
this.currency});
Vehicle.fromJson(Map<String, dynamic> json) {
id = json['id'];

@ -187,4 +187,9 @@ class UserInfo {
"customerID": customerId,
"dealershipID": dealershipId,
};
@override
String toString() {
return 'UserInfo{id: $id, userId: $userId, firstName: $firstName, lastName: $lastName, mobileNo: $mobileNo, email: $email, userImageUrl: $userImageUrl, roleId: $roleId, roleName: $roleName, isEmailVerified: $isEmailVerified, serviceProviderBranch: $serviceProviderBranch, isVerified: $isVerified, userRoles: $userRoles, isCustomer: $isCustomer, isProviderDealership: $isProviderDealership, isDealershipUser: $isDealershipUser, providerId: $providerId, customerId: $customerId, dealershipId: $dealershipId, userLocalImage: $userLocalImage}';
}
}

@ -124,7 +124,9 @@ class AdsRepoImp implements AdsRepo {
"demandAmount": adsCreationPayloadModel.vehiclePosting!.demandAmount,
// "adStatus": 1,
"vehiclePostingImages": vehiclePostingImages,
"vehiclePostingDamageParts": vehiclePostingDamageParts
"vehiclePostingDamageParts": vehiclePostingDamageParts,
"mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo,
"whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo,
}
};

@ -1,11 +1,11 @@
import 'dart:async';
import 'package:flutter/cupertino.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/models/general_models/generic_resp_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_review_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/branch.dart';
@ -15,6 +15,7 @@ import 'package:mc_common_app/models/provider_branches_models/profile/services.d
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
abstract class BranchRepo {
Future<GenericRespModel> createBranch({
@ -53,6 +54,8 @@ abstract class BranchRepo {
Future<Services> fetchProviderServices(String branchID, String serviceCategoryId);
Future<List<ServiceModel>> fetchProviderServicesModelByCategoryIdAndBranchID(String branchID, String serviceCategoryId);
Future<GenericRespModel> createNewService(List<Map<String, dynamic>> map);
Future<Document> getServiceProviderDocument(dynamic userId);
@ -81,7 +84,7 @@ abstract class BranchRepo {
Future<GenericRespModel> addNewServicesInAppointment(Map<String, dynamic> map);
Future<List<BranchDetailModel>> getAllNearBranchAndServices();
Future<List<BranchDetailModel>> getAllNearBranchAndServices({required double latitude, required double longitude});
Future<List<ItemData>> getServiceItems(int serviceId);
@ -188,7 +191,9 @@ class BranchRepoImp implements BranchRepo {
};
String? token = AppState().getUser.data?.accessToken;
debugPrint(token);
return await injector.get<ApiClient>().getJsonForObject((json) => Document.fromJson(json), ApiConsts.fetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
return await injector
.get<ApiClient>()
.getJsonForObject((json) => Document.fromJson(json), ApiConsts.fetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
}
@override
@ -355,6 +360,28 @@ class BranchRepoImp implements BranchRepo {
return await apiClient.getJsonForObject((json) => Services.fromJson(json), ApiConsts.getProviderServices, queryParameters: postParams, token: t);
}
@override
Future<List<ServiceModel>> fetchProviderServicesModelByCategoryIdAndBranchID(String branchID, String serviceCategoryId) async {
var queryParameters = {
"ID": branchID,
"ServiceCategoryIDs": [serviceCategoryId],
};
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAllNearBranches,
token: appState.getUser.data!.accessToken,
queryParameters: queryParameters,
);
List<BranchDetailModel> nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index]));
if (nearBranches.isNotEmpty) {
List<ServiceModel> services = nearBranches.first.branchServices ?? [];
return services;
}
return [];
}
@override
Future<GenericRespModel> addNewServicesInAppointment(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
@ -362,10 +389,12 @@ class BranchRepoImp implements BranchRepo {
}
@override
Future<List<BranchDetailModel>> getAllNearBranchAndServices() async {
Future<List<BranchDetailModel>> getAllNearBranchAndServices({required double latitude, required double longitude}) async {
var queryParameters = {
"isActive": "true",
"Status": "3",
"latitude": latitude.toString(),
"longitude": longitude.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
@ -379,7 +408,11 @@ class BranchRepoImp implements BranchRepo {
@override
Future<List<BranchDetailModel>> getMyRecentBranchesWithServices() async {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.getMyRecentBranches, token: appState.getUser.data!.accessToken);
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getMyRecentBranches,
token: appState.getUser.data!.accessToken,
);
List<BranchDetailModel> recentBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index]));
return recentBranches;
}
@ -403,7 +436,8 @@ class BranchRepoImp implements BranchRepo {
@override
Future<ProviderProfileModel> getBranchAndServicesByProviderId(int providerId) async {
var postParams = {"serviceProviderID": providerId.toString()};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.branchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
return ProviderProfileModel.fromJson(adsGenericModel.data);
}

@ -1,3 +1,4 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:mc_common_app/api/api_client.dart';
@ -25,17 +26,17 @@ class ShippingRepoImp extends ShippingRepo {
@override
Future<List<ShippingRequestModel>> getShippingRequestListByStatus({ShippingRequestStatusEnum? shippingStatusEnum, int? requestId}) async {
String token = appState.getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {
Map queryParameters = {
"requestID": "${requestId ?? 0}",
"shippingStatus": "${shippingStatusEnum != null ? shippingStatusEnum.getIdFromShippingStatusEnum() : 0}",
};
GenericRespModel genericRespModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.shippingRequestStatusGet,
queryParameters,
token: token,
);
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.shippingRequestStatusGet,
queryParameters,
token: token,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
@ -56,12 +57,12 @@ class ShippingRepoImp extends ShippingRepo {
"comment": comment ?? "",
};
GenericRespModel genericRespModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.shippingRequestStatusUpdate,
queryParameters,
token: token,
);
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.shippingRequestStatusUpdate,
queryParameters,
token: token,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());

@ -5,16 +5,15 @@ import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart';
import 'package:mc_common_app/models/subscriptions_models/provider_subscription_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/models/user_models/branch_user.dart';
abstract class SubscriptionRepo {
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID);
// Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID);
Future<SubscriptionModel> getMySubscriptions(String? serviceProviderID);
// Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID});
Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID});
Future<SubscriptionModel> getMySubscriptions(String? serviceProviderID);
Future<SubscriptionModel> getSubscriptionBySP(String? serviceProviderID, bool isRenew);
@ -29,23 +28,10 @@ class SubscriptionRepoImp extends SubscriptionRepo {
ApiClient apiClient = injector.get<ApiClient>();
AppState appState = injector.get<AppState>();
@override
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
queryParameters = {
"ID": serviceProviderID,
};
}
return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
}
@override
Future<SubscriptionModel> getSubscriptionBySP(String? serviceProviderID, bool isRenew) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
Map<String, dynamic> queryParameters = {};
if (serviceProviderID != null) {
queryParameters = {
"ProviderID": serviceProviderID,
@ -138,25 +124,38 @@ class SubscriptionRepoImp extends SubscriptionRepo {
return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
}
@override
Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID}) async {
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
queryParameters = {
"ServiceProviderID": serviceProviderID,
"IsActiveSubscriptionForProvider": "true",
};
}
// @override
// Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID) async {
// String t = AppState().getUser.data!.accessToken ?? "";
// Map<String, String> queryParameters = {};
// if (serviceProviderID != null) {
// queryParameters = {
// "ID": serviceProviderID,
// };
// }
//
// return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
// }
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.getMySubscriptions,
queryParameters: queryParameters,
);
List<ProviderSubscriptionModel> providerSubList = List.generate(adsGenericModel.data.length, (index) => ProviderSubscriptionModel.fromJson(adsGenericModel.data[index]));
return providerSubList;
}
// @override
// Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID}) async {
// Map<String, String> queryParameters = {};
// if (serviceProviderID != null) {
// queryParameters = {
// "ServiceProviderID": serviceProviderID,
// "IsActiveSubscriptionForProvider": "true",
// };
// }
//
// GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
// token: appState.getUser.data!.accessToken,
// (json) => GenericRespModel.fromJson(json),
// ApiConsts.getMySubscriptions,
// queryParameters: queryParameters,
// );
// List<ProviderSubscriptionModel> providerSubList = List.generate(adsGenericModel.data.length, (index) => ProviderSubscriptionModel.fromJson(adsGenericModel.data[index]));
// return providerSubList;
// }
// @override
// Future<SubscriptionModel> getProviderSubscription(

@ -51,7 +51,7 @@ class LocationService implements Location {
getCurrentLocation((LatLng? latlng) {
print(latlng);
AppState().currentLocation = latlng ?? const LatLng(0, 0);
print("App State Location" + AppState().currentLocation.toJson().toString());
print("App State Location${AppState().currentLocation.toJson()}");
});
}
});

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:mc_common_app/generated/locale_keys.g.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/navigator.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:path/path.dart' as p;
@ -27,7 +28,13 @@ class Utils {
static bool get isLoading => _isLoadingVisible;
static void showToast(String message) {
Fluttertoast.showToast(msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
Fluttertoast.showToast(msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 2,
backgroundColor: Colors.black54,
textColor: Colors.white,
fontSize: 16.0);
}
static Future<void> openNumberViaCaller({required String phoneNumber}) async {
@ -70,7 +77,11 @@ class Utils {
return "";
}
return ("${timeOfDay.hour.toString().length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute.toString().length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
return ("${timeOfDay.hour
.toString()
.length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute
.toString()
.length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
}
static dynamic getNotNullValue(List<dynamic> list, int index) {
@ -511,7 +522,7 @@ class Utils {
border: Border.all(
width: w, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -534,7 +545,7 @@ class Utils {
border: Border.all(
width: 1, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -552,7 +563,8 @@ class Utils {
}
static String getAdsPaymentBrowserForm({required int paymentId, required int adId}) {
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts
.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
}
// BOTTOM SHEETS
@ -567,22 +579,36 @@ class Utils {
maxHeight: 55,
title: LocaleKeys.callNow.tr(),
fontSize: 18,
onPressed: () {},
onPressed: () {
pop(context);
},
),
),
actionButtonNo: const SizedBox(),
);
}
static Widget buildStatusContainer(String text) {
static Widget buildStatusContainer(String text, {double marginAll = 8, double fontSize = 14}) {
return Center(
child: text.toText(color: MyColors.lightTextColor, fontSize: 14),
child: text.toText(color: MyColors.lightTextColor, fontSize: fontSize),
).toContainer(
marginAll: 8,
marginAll: marginAll,
paddingAll: 15,
borderRadius: 8,
width: double.infinity,
backgroundColor: MyColors.grey98Color.withOpacity(0.1),
);
}
static Future<void> openLocationInMaps({required double latitude, required double longitude}) async {
final Uri googleMapsUrl = Uri.parse('https://www.google.com/maps/search/?api=1&query=$latitude,$longitude');
if (await canLaunchUrl(googleMapsUrl)) {
try {
await launchUrl(googleMapsUrl);
} catch (e) {
await launchUrl(googleMapsUrl);
}
}
}
}

@ -1302,6 +1302,10 @@ class AdVM extends BaseVM {
warrantyDuration = "";
vehicleDescription = "";
selectionDurationStartDate = "";
isPhoneNumberShown = false;
isNumberOnWhatsApp = false;
adPhoneNumberDialCode = "";
adPhoneNumber = "";
clearSpecialServiceCard();
updateFinanceAvailableStatus(false);
notifyListeners();

@ -28,6 +28,7 @@ import 'package:mc_common_app/repositories/branch_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/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
@ -148,7 +149,7 @@ class AppointmentsVM extends BaseVM {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
} else {
Utils.showToast(LocaleKeys.appointmentBookedSuccessfully.tr());
getMyAppointments();
getMyAppointmentsForCustomer();
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
}
@ -180,9 +181,9 @@ class AppointmentsVM extends BaseVM {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast(genericRespModel.message.toString());
await getMyAppointments();
await getMyAppointmentsForCustomer();
Utils.hideLoading(context);
getMyAppointments();
getMyAppointmentsForCustomer();
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
} catch (e) {
@ -349,12 +350,14 @@ class AppointmentsVM extends BaseVM {
// notifyListeners();
// }
Future<void> getMyAppointments({bool isNeedToRebuild = false}) async {
Future<void> getMyAppointmentsForCustomer({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
// myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
myUpComingAppointments = myAppointments
.where((element) => (element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList();
setState(ViewState.idle);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners();
@ -380,7 +383,9 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.busy);
myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map);
myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
myUpComingAppointments = myAppointments
.where((element) => (element.appointmentStatusEnum == AppointmentStatusEnum.confirmed || element.appointmentStatusEnum == AppointmentStatusEnum.booked) && (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList();
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
setState(ViewState.idle);
}
@ -704,6 +709,10 @@ class AppointmentsVM extends BaseVM {
}
void onServicesNextPressed(BuildContext context) async {
if (allSelectedItemsInAppointments.isEmpty) {
Utils.showToast("Please select at least one service.");
return;
}
Utils.showLoading(context);
List<String> serviceItemIdsForHome = [];
@ -795,7 +804,7 @@ class AppointmentsVM extends BaseVM {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast(genericRespModel.message.toString());
getMyAppointments();
getMyAppointmentsForCustomer();
Utils.hideLoading(context);
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
@ -830,12 +839,28 @@ class AppointmentsVM extends BaseVM {
if (isNeedToRebuild) setState(ViewState.busy);
if (isFromRefresh) {
var selectedBranch = branchesFilterOptions.firstWhere((element) => element.isSelected);
nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [selectedBranch.id]);
var selectedFilter = branchesFilterOptions.firstWhere((element) => element.isSelected);
log("selectedFilter: ${selectedFilter.id}");
if (selectedFilter.id == 0) {
nearbyBranches = await branchRepo.getAllNearBranchAndServices(
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
} else {
nearbyBranches = await branchRepo.getBranchesByFilters(
categoryIdsList: [selectedFilter.id],
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
}
setState(ViewState.idle);
return;
}
nearbyBranches = await branchRepo.getAllNearBranchAndServices();
nearbyBranches = await branchRepo.getAllNearBranchAndServices(
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
setState(ViewState.idle);
}
@ -1162,20 +1187,24 @@ class AppointmentsVM extends BaseVM {
serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null,
distanceKm: branchFilterCurrentDistance.toInt(),
rating: branchFilterByRating.toInt(),
latitude: 24.694969,
longitude: 46.724129,
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
setState(ViewState.idle);
}
Future<void> getBranchesBasedOnCategoryFilters({required int categoryId}) async {
setState(ViewState.busy);
if (categoryId == 0) {
await getAllNearBranches();
return;
}
setState(ViewState.busy);
nearbyBranches.clear();
nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [categoryId]);
nearbyBranches = await branchRepo.getBranchesByFilters(
categoryIdsList: [categoryId],
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
setState(ViewState.idle);
}
@ -1186,7 +1215,11 @@ class AppointmentsVM extends BaseVM {
Future<void> fetchAllBranchesBySelectedProviderId({required List<int> providersIdsList}) async {
branchesDropList.clear();
setOnlyState(ViewState.busy);
List<BranchDetailModel> providers = await branchRepo.getBranchesByFilters(providerIdsList: providersIdsList);
List<BranchDetailModel> providers = await branchRepo.getBranchesByFilters(
providerIdsList: providersIdsList,
latitude: AppState().currentLocation.latitude,
longitude: AppState().currentLocation.longitude,
);
for (var element in providers) {
branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", ""));
}
@ -1388,7 +1421,7 @@ class AppointmentsVM extends BaseVM {
appointmentFilterBranchSearchHistory.clear();
appointmentFiltersCounter = 0;
clearAppointmentFilterSelections();
getMyAppointments();
getMyAppointmentsForCustomer();
notifyListeners();
}
@ -1538,5 +1571,4 @@ class AppointmentsVM extends BaseVM {
// .whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments));
// }
}
}

@ -65,7 +65,7 @@ class DashboardVmCustomer extends BaseVM {
appointmentsVM.populateAppointmentsFilterList();
adVM.populateAdsFilterList();
requestsVM.populateDataForRequestsFilter();
await appointmentsVM.getMyAppointments();
await appointmentsVM.getMyAppointmentsForCustomer();
await appointmentsVM.applyFilterOnBranches(index: 0); // to get all branches!
await appointmentsVM.getMyRecentBranches(); // to get my recent branches!
await adVM.getMyAds();

@ -0,0 +1,140 @@
import 'dart:io';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/shipping_management_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/add_phone_num_wiget.dart';
import 'package:provider/provider.dart';
import 'package:mc_common_app/utils/location/Location.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/view_models/appointments_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
class DashboardVMProvider extends BaseVM {
final CommonAppServices commonServices;
final UserRepo userRepo;
DashboardVMProvider({required this.commonServices, required this.userRepo});
String pickedImage = "";
int selectedNavbarBarIndex = 2;
void onNavbarTapped(int index) async {
logger.i(AppState().getDeviceToken);
selectedNavbarBarIndex = index;
notifyListeners();
}
void pickImageFromPhone(BuildContext context, int sourceFlag) async {
final File? pickedImageFile = await commonServices.pickImageFromPhone(sourceFlag);
if (pickedImageFile == null) {
return;
}
int sizeInBytes = pickedImageFile.lengthSync();
if (sizeInBytes > 1000000) {
Utils.showToast(LocaleKeys.fileLarger.tr());
return;
} else {
String image64 = Utils.convertFileToBase64(pickedImageFile);
Utils.showLoading(context);
ImageResponse response = await userRepo.updateUserImage(image64);
Utils.hideLoading(context);
Navigator.pop(context);
if (response.messageStatus == 1) {
Utils.showToast(LocaleKeys.imageUploaded.tr());
AppState().getUser.data!.userInfo!.userImageUrl = response.data;
} else {
Utils.showToast(response.message ?? "");
}
}
}
Future<ImageResponse> updateUserImage(String image) async {
return await userRepo.updateUserImage(image);
}
Future<void> onRefresh(BuildContext context) async {
final requestsVM = context.read<RequestsVM>();
final chatVM = context.read<ChatVM>();
final appointmentVM = context.read<AppointmentsVM>();
final shippingManagementVM = context.read<ShippingManagementVM>();
final serviceVM = context.read<ServiceVM>();
final adVm = context.read<AdVM>();
final subscriptionsVM = context.read<SubscriptionsVM>();
requestsVM.populateDataForRequestsFilter();
appointmentVM.populateAppointmentsFilterList();
shippingManagementVM.populateShippingRequestFilterList();
await serviceVM.getBranchAndServices();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0"});
adVm.populateAdsFilterList();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
await chatVM.buildHubConnection(context);
await adVm.getMyAds();
await adVm.getExploreAds();
await adVm.getVehicleTypes();
await adVm.getVehicleAdsDuration();
await requestsVM.getRequests();
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
}
void checkUserSubscription(SubscriptionActionTypeEnum actionType, BuildContext context, {required Function() callback}) async {
switch (actionType) {
case SubscriptionActionTypeEnum.ads:
performCheckOnAds(context);
break;
case SubscriptionActionTypeEnum.users:
performCheckOnUsers(context, callback);
break;
case SubscriptionActionTypeEnum.branches:
performCheckOnBranches(context);
break;
}
}
void performCheckOnBranches(BuildContext context) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.branchesRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, AppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Branches.");
}
}
void performCheckOnAds(BuildContext context) async {
//adsRemaining
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.adsRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, AppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Ads.");
}
}
void performCheckOnUsers(BuildContext context, Function() callBack) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.subUsersRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
showMyBottomSheet(context, isDismissible: false, child: const AddPhoneNumWidget(), callBackFunc: callBack);
} else {
Utils.showToast("Upgrade your subscription to add more Sub Users.");
}
}
}

@ -12,6 +12,7 @@ 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/dashboard_view_model_customer.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_provider.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
@ -84,11 +85,12 @@ class PaymentVM extends ChangeNotifier {
);
Utils.hideLoading(context);
if (!isPaid) {
Utils.showToast(LocaleKeys.paymentFailed.tr());
pop(context);
return;
}
// TODO: VERIFY THIS WITH ZAHOOR
// if (!isPaid) {
// Utils.showToast(LocaleKeys.paymentFailed.tr());
// pop(context);
// return;
// }
Utils.showToast(LocaleKeys.paymentSuccessful.tr());
onVerified();
} catch (e) {
@ -181,12 +183,20 @@ class PaymentVM extends ChangeNotifier {
}
void onRequestPaymentSuccess(BuildContext context) {
context.read<DashboardVmCustomer>().onNavbarTapped(4);
if (AppState().currentAppType == AppType.provider) {
context.read<DashboardVMProvider>().onNavbarTapped(4);
} else {
context.read<DashboardVmCustomer>().onNavbarTapped(4);
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
void onAdsPaymentSuccess(BuildContext context) {
context.read<DashboardVmCustomer>().onNavbarTapped(3);
if (AppState().currentAppType == AppType.provider) {
context.read<DashboardVMProvider>().onNavbarTapped(3);
} else {
context.read<DashboardVmCustomer>().onNavbarTapped(3);
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
@ -197,7 +207,11 @@ class PaymentVM extends ChangeNotifier {
}
void onAppointmentSuccess(BuildContext context) {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
if (AppState().currentAppType == AppType.provider) {
context.read<DashboardVMProvider>().onNavbarTapped(1);
} else {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}

@ -3,6 +3,8 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
@ -14,9 +16,10 @@ import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/provider_offers_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/repositories/request_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
@ -28,7 +31,6 @@ 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/dropdown/dropdow_field.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class RequestsVM extends BaseVM {
final CommonAppServices commonServices;
@ -60,6 +62,8 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
ServiceProvidersOffers? currentSelectedOffer;
String? acceptedRequestOfferProviderName;
updateAcceptedRequestOfferProviderName(String value) {
@ -67,6 +71,19 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
String addressSparePartRequestDelivery = "";
String additionalAddressSparePartRequestDelivery = "";
void updateAddressSparePartRequestDelivery(String value) {
addressSparePartRequestDelivery = value;
notifyListeners();
}
void updateAdditionalAddressSparePartRequestDelivery(String value) {
additionalAddressSparePartRequestDelivery = value;
notifyListeners();
}
Future<void> getRequests({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
@ -76,9 +93,7 @@ class RequestsVM extends BaseVM {
Future<bool> getRequestsBasedOnFilters() async {
myFilteredRequests.clear();
setState(ViewState.busy);
int requestTypeIdApi = requestsTypeFilterOptions
.firstWhere((element) => element.isSelected)
.id;
int requestTypeIdApi = requestsTypeFilterOptions.firstWhere((element) => element.isSelected).id;
int requestCityIdApi = 0;
if (vehicleCityId.selectedId != -1) {
@ -612,7 +627,7 @@ class RequestsVM extends BaseVM {
bool isCountryFetching = false;
//Request Management
String price = "";
String price = "1.0";
String description = "";
String address = "";
String model = "";
@ -734,9 +749,6 @@ class RequestsVM extends BaseVM {
} else if (vehicleCityId.selectedId == -1) {
Utils.showToast(LocaleKeys.selectValidCity.tr());
isValid = false;
} else if (price.isEmpty) {
Utils.showToast(LocaleKeys.addValidPrice.tr());
isValid = false;
} else if (description.isEmpty) {
Utils.showToast(LocaleKeys.addValidDescription.tr());
isValid = false;

@ -1,13 +1,13 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.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/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/repositories/branch_repo.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/document.dart';
@ -18,6 +18,7 @@ import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/models/user_models/branch_user.dart';
import 'package:mc_common_app/models/user_models/cities.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/repositories/branch_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/utils/enums.dart';
@ -26,7 +27,6 @@ import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:easy_localization/easy_localization.dart';
class ServiceVM extends BaseVM {
final BranchRepo branchRepo;
@ -96,31 +96,15 @@ class ServiceVM extends BaseVM {
commerceCertificates.clear();
commercialCertificates.clear();
vatCertificates.clear();
// 0 Need To Upload
//1 Pending
//2
//3 Approved
//4 Rejected
// document = await branchRepo.getServiceProviderDocument(providerId);
document = await branchRepo.getServiceProviderDocument(providerId);
// if (document != null && document!.data != null && document!.data!.isNotEmpty) {
// print(document!.data!.length);
// for (var doc in document!.data!) {
// print("doc: ${doc.status}");
// if (doc.status != 3 || doc.status == 1) {
// log("doc: ${doc.status}");
// if (doc.status != 3) {
// updateIsAllDocsApproved(false);
// }
// }
// }
//
document = await branchRepo.getServiceProviderDocument(providerId);
// 0 Need To Upload
//1 Pending
//2
//3 Approved
//4 Rejected
setState(ViewState.idle);
}
@ -147,39 +131,47 @@ class ServiceVM extends BaseVM {
notifyListeners();
}
int selectedBranchId = 0;
updateSelectedBranchId(var value) {
selectedBranchId = value;
}
filterUserBranchCategories() {
categories = [];
List<BranchDetailModel>? localbranches;
if (branches!.data != null) {
if (selectedBranchStatus == 3) {
localbranches = branches!.data!.serviceProviderBranch!.where((element) => element.statusId == 3).toList();
} else {
localbranches = branches!.data!.serviceProviderBranch!.where((element) => element.statusId != 3).toList();
}
}
setState(ViewState.busy);
categories.clear();
// List<BranchDetailModel> localBranches = [];
// if (branches!.data != null) {
// if (selectedBranchStatus == 3) {
// localBranches = branches!.data!.serviceProviderBranch!.where((element) => element.statusId == 3).toList();
// } else {
// localBranches = branches!.data!.serviceProviderBranch!.where((element) => element.statusId != 3).toList();
// }
// }
for (var branch in localbranches!) {
for (var element in branch.branchServices!) {
categories.add(
CategoryData(
id: element.categoryId,
categoryName: element.categoryName,
categoryNameN: element.categoryName,
),
);
}
categories = categories.toSet().toList();
for (var payment in categories) {
for (var element in branch.branchServices!) {
if (payment.id == element.categoryId) {
payment.services ??= [];
payment.services!.add(element);
}
final BranchDetailModel currentBranch = branches!.data!.serviceProviderBranch!.firstWhere((element) => element.id == selectedBranchId);
for (var element in currentBranch.branchServices!) {
categories.add(
CategoryData(
id: element.categoryId,
categoryName: element.categoryName,
categoryNameN: element.categoryName,
),
);
}
categories = categories.toSet().toList();
for (var payment in categories) {
for (var element in currentBranch.branchServices!) {
if (payment.id == element.categoryId) {
payment.services ??= [];
payment.services!.add(element);
}
}
}
categories = categories;
setState(ViewState.idle);
notifyListeners();
}
// Future<String?> selectFile(BuildContext context, int index) async {
@ -242,12 +234,11 @@ class ServiceVM extends BaseVM {
context,
allowMultiple: false,
);
if (files != null && files.any((file) => file.path.split('.').last.toLowerCase() != 'pdf')) {
Utils.showToast("Only PDF files are allowed");
if (files != null && files.any((element) => element.path.split('.').last.toLowerCase() != 'pdf')) {
Utils.showToast("Only PDF Files are allowed");
return;
}
if (files == null) return;
for (var element in files) {
imageModels.add(ImageModel(
filePath: element.path,
@ -479,6 +470,18 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<List<ServiceModel>> fetchProviderServicesModelByCategoryIdAndBranchID({required String branchID, required String categoryId}) async {
setState(ViewState.busy);
try {
List<ServiceModel> services = await branchRepo.fetchProviderServicesModelByCategoryIdAndBranchID(branchID, categoryId);
setState(ViewState.idle);
return services;
} catch (e) {
setState(ViewState.idle);
return [];
}
}
Future<GenericRespModel> createService(List<Map<String, dynamic>> map) async {
setState(ViewState.busy);
return await branchRepo.createService(map);

@ -1,9 +1,10 @@
import 'dart:developer';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/utils/enums.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/widgets/dropdown/dropdow_field.dart';
import '../repositories/subscription_repo.dart';
@ -24,27 +25,27 @@ class SubscriptionsVM extends BaseVM {
//My Subscriptions
//All Subscriptions
getAllAvailableSubscriptions(String? serviceProviderID) async {
selectedIndex = 0;
setState(ViewState.busy);
allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID);
if (allSubscriptions.messageStatus == 1) {
monthlyTabs.clear();
var idSet = <int>{};
for (var d in allSubscriptions.data ?? []) {
if (idSet.add(d.durationDays ?? 0)) {
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "", isEnabled: false));
}
}
monthlyTabs.sort((a, b) => a.value.compareTo(b.value));
monthlyTabs.first.isEnabled = true;
selectedMonthlyTab = monthlyTabs.first;
filterSubscriptions();
setState(ViewState.idle);
} else {
setState(ViewState.error);
}
}
// getAllAvailableSubscriptions(String? serviceProviderID) async {
// selectedIndex = 0;
// setState(ViewState.busy);
// allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID);
// if (allSubscriptions.messageStatus == 1) {
// monthlyTabs.clear();
// var idSet = <int>{};
// for (var d in allSubscriptions.data ?? []) {
// if (idSet.add(d.durationDays ?? 0)) {
// monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "", isEnabled: false));
// }
// }
// monthlyTabs.sort((a, b) => a.value.compareTo(b.value));
// monthlyTabs.first.isEnabled = true;
// selectedMonthlyTab = monthlyTabs.first;
// filterSubscriptions();
// setState(ViewState.idle);
// } else {
// setState(ViewState.error);
// }
// }
getSubscriptionBySP(String serviceProviderID, bool isRenew) async {
selectedIndex = 0;
@ -77,7 +78,6 @@ class SubscriptionsVM extends BaseVM {
GenericRespModel genericRespModel = await subscriptionRepo.calculationUpgradePrice(serviceProviderID, newSubscription);
if (genericRespModel.messageStatus == 1) {
setState(ViewState.idle);
print("=========== ${genericRespModel.data.toString()}=================");
newPrice = genericRespModel.data.toString();
} else {
setState(ViewState.error);
@ -116,12 +116,7 @@ class SubscriptionsVM extends BaseVM {
}
Future<GenericRespModel> createSubscriptionOrder(int subscriptionId, bool isStartNow, bool isRenew, {bool isDegrade = false, List<int>? listOfBranches, List<int>? listOfUsers}) async {
Map<String, dynamic> map = {
"providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "",
"subscriptionID": subscriptionId.toString(),
"isStartNow": isStartNow.toString(),
"isRenew": isRenew.toString()
};
Map<String, dynamic> map = {"providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", "subscriptionID": subscriptionId.toString(), "isStartNow": isStartNow.toString(), "isRenew": isRenew.toString()};
GenericRespModel genericRespModel = await subscriptionRepo.payForProviderSubscription(map);
return genericRespModel;
}
@ -191,18 +186,17 @@ class SubscriptionsVM extends BaseVM {
// My Provider Subscription
getMySubscriptionsBySP() async {
setState(ViewState.busy);
mySubscriptionsBySp.clear();
if (mySubscriptionsBySp.isEmpty) {
// allSubscriptions.data
for (var element in allSubscriptions.data!) {
if (element.subscriptionTypeEnum == SubscriptionTypeEnum.current) {
mySubscriptionsBySp.add(element);
}
setState(ViewState.busy);
// allSubscriptions.data
for (var element in allSubscriptions.data!) {
if (element.subscriptionTypeEnum == SubscriptionTypeEnum.current) {
mySubscriptionsBySp.add(element);
}
AppState().setproviderSubscription = mySubscriptionsBySp;
}
// mySubscriptionsBySp = await subscriptionRepo.getProviderSubscription(serviceProviderID: serviceProviderID);
AppState().setproviderSubscription = mySubscriptionsBySp;
setState(ViewState.idle);
}
}

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
@ -13,6 +14,7 @@ import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/models/user_models/basic_otp.dart';
import 'package:mc_common_app/models/user_models/change_email.dart';
import 'package:mc_common_app/models/user_models/change_mobile.dart';
@ -34,11 +36,14 @@ import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/shared_prefrence.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/service_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/views/location_views/map_selection_widget.dart';
import 'package:mc_common_app/widgets/dialog/dialogs.dart';
import 'package:mc_common_app/widgets/dialog/message_dialog.dart';
import 'package:mc_common_app/widgets/dialog/otp_dialog.dart';
import 'package:mc_common_app/widgets/tab/login_email_tab.dart';
import 'package:provider/provider.dart';
class UserVM extends BaseVM {
final UserRepo userRepo;
@ -345,6 +350,7 @@ class UserVM extends BaseVM {
}
Future<void> performBasicOtpLoginSelectionPage(BuildContext context, {required String userToken, required AppType appType, String? loginType}) async {
log("loginType: $loginType");
if (loginType == "3" || loginType == "4") {
//Utils.showLoading(context);
LoginPasswordRespModel user = await userRepo.loginV2OTP(userToken, loginType!);
@ -427,6 +433,9 @@ class UserVM extends BaseVM {
} else {
Utils.showToast(LocaleKeys.onlyCustomerApp.tr());
}
} else {
Utils.showToast("Please verify your credentials and role type.");
}
} else {
Utils.showToast(verifiedUser.message ?? "");
@ -673,7 +682,13 @@ class UserVM extends BaseVM {
AppState().getUser.data!.userInfo!.userLocalImage = null;
AppState().getUser.data!.userInfo!.userImageUrl = null;
}
AppState().setproviderSubscription = null;
AppState().setUser = null;
if (AppState().currentAppType == AppType.provider) {
AppState().setproviderSubscription = null;
context.read<SubscriptionsVM>().mySubscriptionsBySp.clear();
context.read<SubscriptionsVM>().allSubscriptions = SubscriptionModel();
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.registerSelection);
}
}

@ -227,6 +227,8 @@ class VehicleDetails extends StatelessWidget {
errorValue: adVM.warrantyError,
keyboardType: TextInputType.number,
hint: LocaleKeys.warrantyAvailableYears.tr(),
numbersOnly: true,
allowOnlyOneDigit: true,
onChanged: (v) => adVM.updateVehicleWarrantyDuration(v),
),
8.height,

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
@ -34,15 +35,12 @@ class AdsDetailView extends StatefulWidget {
class _AdsDetailViewState extends State<AdsDetailView> {
late AdVM adVM;
late List<VehicleDamageCard> damagePartsPictures;
@override
void initState() {
adVM = context.read<AdVM>();
damagePartsPictures = [];
scheduleMicrotask(() {
onAdDetailsLoaded();
populateDamagePartPictures();
});
super.initState();
}
@ -54,24 +52,6 @@ class _AdsDetailViewState extends State<AdsDetailView> {
}
}
void populateDamagePartPictures() {
if (widget.adDetails.vehicle!.damagereport != null && widget.adDetails.vehicle!.damagereport!.isNotEmpty) {
for (var element in widget.adDetails.vehicle!.damagereport!) {
int index = -1;
ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true);
VehicleDamageCard vehicleDamageCard = VehicleDamageCard(
partSelectedId: SelectionModel(
selectedId: element.vehicleDamagePartID!,
selectedOption: element.partName ?? "",
),
partImages: [imageModel],
);
damagePartsPictures.add(vehicleDamageCard);
}
}
}
void deleteAdBottomSheet(BuildContext context) {
return actionConfirmationBottomSheet(
context: context,

@ -218,7 +218,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
}
Widget defaultActionForProviderAndCustomer(BuildContext context, AdDetailsModel adDetailsModel) {
return (adDetailsModel.phoneNo == null)
return (adDetailsModel.phoneNo != null && adDetailsModel.phoneNo!.isNotEmpty)
? Row(
children: [
Expanded(
@ -236,7 +236,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
},
),
),
if (adDetailsModel.whatsAppNo == null) ...[
if (adDetailsModel.whatsAppNo != null && adDetailsModel.whatsAppNo!.isNotEmpty) ...[
8.width,
Container(height: 55, width: 55, alignment: Alignment.center, decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), child: MyAssets.whatsAppIcon.buildSvg(height: 33, width: 35)).onPress(() {
Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? "");

@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:developer';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
@ -65,7 +68,21 @@ class _AdDamagePartPicturesSheetState extends State<AdDamagePartPicturesSheet> {
onCrossPressedSecondary: (imageIndex, filePath) {},
index: index,
onAddFilePressed: () {},
),
).onPress(() {
if (vehicleDamageCard.partImages == null) {
return;
}
List<MessageImageModel> images = [];
for (var image in vehicleDamageCard.partImages!) {
images.add(MessageImageModel(
id: image.id,
isFromNetwork: true,
imageUrl: image.filePath,
));
}
navigateWithName(context, AppRoutes.mediaViewerScreen, arguments: images);
}),
],
).toWhiteContainer(
width: double.infinity,

@ -30,7 +30,6 @@ class AdsListWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (isAdsFragment && adsList.isEmpty) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
@ -139,11 +138,7 @@ class AdCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
(adDetails.vehicle!.cityName ?? "").toText(color: MyColors.lightTextColor),
adDetails.createdOn != null
? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText(
color: MyColors.lightTextColor,
)
: const SizedBox(),
adDetails.createdOn != null ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText(color: MyColors.lightTextColor) : const SizedBox(),
],
),
],

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

@ -1,8 +1,10 @@
import 'dart:developer';
import 'package:flutter/gestures.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/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
@ -10,6 +12,7 @@ import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.
import 'package:mc_common_app/models/general_models/widgets_models.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/view_models/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
@ -76,7 +79,6 @@ class SelectAdTypeView extends StatelessWidget {
if (adVM.isAdEditEnabled) {
adVM.autoFillSelectedVehicleAdsDetails();
}
log("isUpdateAdSelected: ${adVM.isAdEditEnabled}}");
showMyBottomSheet(context, child: AdDurationSelectionSheet(isUpdateAdSelected: adVM.isAdEditEnabled, isFromExtendAd: isFromExtendAd, adsID: adsId));
},
child: SizedBox(
@ -147,27 +149,33 @@ class SelectAdTypeView extends StatelessWidget {
children: [
Row(
children: [
"$remainingAds of $totalAds ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1),
LocaleKeys.adsRemainingVar.tr().toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true),
"$remainingAds ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1),
LocaleKeys.adsRemaining.tr().toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true),
],
),
Text.rich(
TextSpan(
children: [
TextSpan(
text: LocaleKeys.youLeftAdsGivenSubscription.tr(),
style: const TextStyle(
fontSize: 14,
color: MyColors.lightTextColor,
)),
text: LocaleKeys.youLeftAdsGivenSubscription.tr(),
style: const TextStyle(
fontSize: 14,
color: MyColors.lightTextColor,
),
),
TextSpan(
text: LocaleKeys.updateSubscription.tr(),
style: const TextStyle(
decoration: TextDecoration.underline,
fontSize: 14,
fontWeight: FontWeight.w600,
color: MyColors.darkPrimaryColor,
))
text: " ${LocaleKeys.updateSubscription.tr()}",
recognizer: TapGestureRecognizer()
..onTap = () {
navigateWithName(context, AppRoutes.mySubscriptionsPage);
},
style: const TextStyle(
decoration: TextDecoration.underline,
fontSize: 14,
fontWeight: FontWeight.w600,
color: MyColors.darkPrimaryColor,
),
)
],
),
),

@ -61,15 +61,6 @@ class BookAppointmentServicesView extends StatelessWidget {
],
),
if (true) ...[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
4.width,
(serviceData.isHomeSelected ? serviceData.homeLocation : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(),
],
),
5.height,
Column(
children: List.generate(serviceData.serviceItems!.length, (itemIndex) {
ItemData itemData = serviceData.serviceItems![itemIndex];
@ -83,6 +74,15 @@ class BookAppointmentServicesView extends StatelessWidget {
}),
),
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
4.width,
(serviceData.isHomeSelected ? serviceData.homeLocation : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(),
],
),
5.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [

@ -64,7 +64,7 @@ class BookAppointmentsItemView extends StatelessWidget {
],
).horPaddingMain(),
appointmentsVM.serviceItemsFromApi.isEmpty
? Expanded(child: Center(child: LocaleKeys.noItemstoShow.toText(fontSize: 16, color: MyColors.lightTextColor)))
? Expanded(child: Center(child: LocaleKeys.noItemsToShow.toText(fontSize: 16, color: MyColors.lightTextColor)))
: ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: appointmentsVM.serviceItemsFromApi.length,

@ -200,6 +200,7 @@ class _ChatViewState extends State<ChatView> {
] else if (chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestType.toRequestTypeStatusEnum() == RequestsTypeEnum.specialCarRequest &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress &&
requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted &&
AppState().currentAppType == AppType.customer) ...[
Expanded(
child: ShowFillButton(

@ -13,22 +13,20 @@ class AppMap extends StatefulWidget {
late AppMapState _state;
final Function onMapCreated;
AppMap(this.initialCamera,
{required this.onCameraMove, required this.onCameraIdle, required this.onMapCreated});
AppMap(this.initialCamera, {required this.onCameraMove, required this.onCameraIdle, required this.onMapCreated});
@override
State<StatefulWidget> createState() => _state = AppMapState();
moveTo({required CameraPosition cameraPostion}) {
_state.googleMapController
.animateCamera(CameraUpdate.newCameraPosition(cameraPostion));
_state.googleMapController.animateCamera(CameraUpdate.newCameraPosition(cameraPostion));
}
}
class AppMapState extends State<AppMap> {
bool isHuawei = false;
Completer<GoogleMapController> _googleMapControllerComp = Completer();
final Completer<GoogleMapController> _googleMapControllerComp = Completer();
late GoogleMapController googleMapController;
checkIsHuawei() async {
@ -46,7 +44,7 @@ class AppMapState extends State<AppMap> {
@override
Widget build(BuildContext context) {
if (isHuawei == null) return CircularProgressIndicator();
if (isHuawei == null) return const CircularProgressIndicator();
return googleMap();
}
@ -56,9 +54,7 @@ class AppMapState extends State<AppMap> {
zoomControlsEnabled: true,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition.fromMap(widget.initialCamera) ??
const CameraPosition(
target: LatLng(-26.1711459, 27.9002758), zoom: 2.0),
initialCameraPosition: CameraPosition.fromMap(widget.initialCamera) ?? const CameraPosition(target: LatLng(-26.1711459, 27.9002758), zoom: 2.0),
onCameraMove: widget.onCameraMove,
onCameraIdle: widget.onCameraIdle,
onMapCreated: (GoogleMapController controller) {

@ -33,11 +33,9 @@ class _PickLocationPageState extends State<PickLocationPage> {
final Set<Marker> markers = {};
late AppMap appMap;
static CameraPosition _kGooglePlex = CameraPosition(
target: AppState().currentLocation,
zoom: 14.4746,
);
static CameraPosition _kGooglePlex = CameraPosition(target: AppState().currentLocation, zoom: 14.4746);
late LatLng currentPosition;
Completer<GoogleMapController> mapController = Completer();
final ValueNotifier<String> _counter = ValueNotifier<String>("");
@override
@ -47,15 +45,14 @@ class _PickLocationPageState extends State<PickLocationPage> {
onCameraMove: (camera) {
_updatePosition(camera);
},
onCameraIdle: (){
print("===== Idle Triggered =====");
onCameraIdle: () {
updateAddress(latitude, longitude);
},
onMapCreated: () {
// goToCurrentLocation();
_getUserLocation();
setState(() {});
},
);
super.initState();
}
@ -129,7 +126,9 @@ class _PickLocationPageState extends State<PickLocationPage> {
Future<void> _updatePosition(CameraPosition position) async {
latitude = position.target.latitude;
longitude = position.target.longitude;
// updateAddress(latitude, longitude);
log(latitude.toString());
log(latitude.toString());
// updateAddress(latitude, longitude);
}
void _getUserLocation() async {
@ -158,24 +157,16 @@ class _PickLocationPageState extends State<PickLocationPage> {
}
updateAddress(double latitude, double longitude) async {
print("=========");
List<Placemark> placemarks = await placemarkFromCoordinates(latitude, longitude).catchError((e) {
print(e);
});
print(placemarks.length);
print("====end=====");
List<Placemark> placemarks = await placemarkFromCoordinates(latitude, longitude);
_counter.value = '${placemarks.first.street}, ${placemarks.first.subLocality}, ${placemarks.first.locality}, ${placemarks.first.postalCode}, ${placemarks.first.country}';
}
setMap() {
// setState(() {
_kGooglePlex = CameraPosition(
target: currentPosition,
zoom: 14.4746,
);
appMap.moveTo(cameraPostion: _kGooglePlex);
// });
}
Future<String> getCurrentAddress() async {

@ -101,7 +101,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
CustomProfileOptionsTile(
titleText: LocaleKeys.phone.tr(),
subtitleText: "${AppState().getUser.data!.userInfo!.email}",
subtitleText: "${AppState().getUser.data!.userInfo!.mobileNo}",
needBorderBelow: true,
onTap: () {
Navigator.pushNamed(context, AppRoutes.changeMobilePage);

@ -1,12 +1,14 @@
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/views/location_views/pick_location_page.dart';
@ -16,7 +18,6 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class CreateRequestPage extends StatelessWidget {
const CreateRequestPage({super.key});
@ -42,6 +43,16 @@ class CreateRequestPage extends StatelessWidget {
child: CircularProgressIndicator(),
),
] else ...[
if (AppState().getUser.data!.userInfo != null) ...[
TxtField(
value: "${AppState().getUser.data!.userInfo!.firstName ?? ""} ${AppState().getUser.data!.userInfo!.lastName ?? ""}",
isBackgroundEnabled: true,
isNeedClickAll: true,
hint: '',
onTap: () {},
),
],
8.height,
Builder(builder: (context) {
List<DropValue> requestTypeDrop = [];
for (var element in requestsVM.myRequestsTypeEnum) {
@ -122,7 +133,8 @@ class CreateRequestPage extends StatelessWidget {
return DropdownField(
(DropValue value) => requestsVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)),
list: vehicleOwnerDrop,
dropdownValue: requestsVM.vehicleConditionId.selectedId != -1 ? DropValue(requestsVM.vehicleConditionId.selectedId, requestsVM.vehicleConditionId.selectedOption, "") : null,
dropdownValue:
requestsVM.vehicleConditionId.selectedId != -1 ? DropValue(requestsVM.vehicleConditionId.selectedId, requestsVM.vehicleConditionId.selectedOption, "") : null,
hint: LocaleKeys.condition.tr(),
errorValue: requestsVM.vehicleConditionId.errorValue,
);
@ -165,13 +177,13 @@ class CreateRequestPage extends StatelessWidget {
}),
],
],
8.height,
TxtField(
hint: LocaleKeys.price.tr(),
value: requestsVM.price,
keyboardType: TextInputType.number,
onChanged: (e) => requestsVM.updatePrice(e),
),
// 8.height,
// TxtField(
// hint: LocaleKeys.price.tr(),
// value: requestsVM.price,
// keyboardType: TextInputType.number,
// onChanged: (e) => requestsVM.updatePrice(e),
// ),
8.height,
TxtField(
hint: LocaleKeys.description.tr(),
@ -209,11 +221,13 @@ class CreateRequestPage extends StatelessWidget {
),
8.height,
],
DottedRectContainer(
onTap: () => context.read<RequestsVM>().pickMultipleImages(),
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
),
if (requestsVM.pickedVehicleImages.isEmpty) ...[
DottedRectContainer(
onTap: () => context.read<RequestsVM>().pickMultipleImages(),
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
),
],
if (requestsVM.vehicleImageError != "") ...[
10.height,
Row(

@ -12,6 +12,7 @@ import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
@ -37,7 +38,10 @@ class OfferListPage extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(text: "Offer ${Utils.getNameByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!)}", chipColor: Utils.getChipColorByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!)),
Utils.statusContainerChip(
text: "Offer ${Utils.getNameByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!)}",
chipColor: Utils.getChipColorByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
@ -80,6 +84,7 @@ class OfferListPage extends StatelessWidget {
),
],
).onPress(() async {
context.read<RequestsVM>().currentSelectedOffer = offersModel;
ChatViewArgumentsForRequest chatViewArgumentsForRequest = ChatViewArgumentsForRequest(
chatTypeEnum: ChatTypeEnum.requestOffer,
receiverId: "${offersModel.providerUserId}",

@ -25,7 +25,7 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
builder: (BuildContext context) {
return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.makeAnOffer.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
title: LocaleKeys.provideOffer.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
@ -48,22 +48,20 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
TxtField(
value: requestsVM.serviceItem,
errorValue: requestsVM.offerPriceError,
keyboardType: TextInputType.number,
hint: "Service Item",
hint: LocaleKeys.serviceItem.tr(),
onChanged: (v) => requestsVM.updateServiceItem(v),
),
12.height,
TxtField(
value: requestsVM.itemManufacturer,
errorValue: requestsVM.offerPriceError,
keyboardType: TextInputType.number,
hint: LocaleKeys.manufacturer.tr(),
hint: LocaleKeys.createdBy.tr(),
onChanged: (v) => requestsVM.updateItemManufacturer(v),
),
12.height,
TxtField(
errorValue: "",
hint: LocaleKeys.manufacturedOn.tr(),
hint: LocaleKeys.createdOn.tr(),
value: requestsVM.serviceItemCreatedOn,
isNeedClickAll: true,
postfixData: Icons.calendar_month_rounded,

@ -149,7 +149,7 @@ class RequestDetailPage extends StatelessWidget {
maxWidth: double.infinity,
margin: const EdgeInsets.all(15),
maxHeight: 55,
title: LocaleKeys.sendOffer.tr(),
title: LocaleKeys.provideOffer.tr(),
isBold: false,
fontSize: 18,
onPressed: () => buildSendOfferBottomSheet(context: context, requestDetailPageArguments: requestDetailPageArguments, isFromChatScreen: false),
@ -208,37 +208,37 @@ class RequestDetailPage extends StatelessWidget {
showItem("${LocaleKeys.customerName.tr()}: ", requestDetail.customerName),
showItem("${LocaleKeys.description.tr()}: ", requestDetail.description),
16.height,
showItem("${LocaleKeys.priceRange.tr()}:", ""),
Row(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"${requestDetail.price.toInt()}".toText(fontSize: 19, isBold: true, letterSpacing: -1.16),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4),
],
),
Row(
children: [
Utils.statusContainerChip(
text: (requestDetail.requestStatusName),
chipColor: MyColors.grey98Color.withOpacity(0.1),
textColor: MyColors.lightTextColor,
),
],
),
],
),
),
// const Icon(Icons.arrow_forward)
],
),
// showItem("${LocaleKeys.priceRange.tr()}:", ""),
// Row(
// children: [
// Expanded(
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// "${requestDetail.price.toInt()}".toText(fontSize: 19, isBold: true, letterSpacing: -1.16),
// 2.width,
// LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4),
// ],
// ),
// Row(
// children: [
// Utils.statusContainerChip(
// text: (requestDetail.requestStatusName),
// chipColor: MyColors.grey98Color.withOpacity(0.1),
// textColor: MyColors.lightTextColor,
// ),
// ],
// ),
// ],
// ),
// ),
// // const Icon(Icons.arrow_forward)
// ],
// ),
],
);
}

@ -8,19 +8,40 @@ 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/user_models/user.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/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_review_containers.dart';
import 'package:mc_common_app/views/location_views/pick_location_page.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class ReviewRequestOffer extends StatelessWidget {
class ReviewRequestOffer extends StatefulWidget {
const ReviewRequestOffer({super.key});
@override
State<ReviewRequestOffer> createState() => _ReviewRequestOfferState();
}
class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
@override
void initState() {
final requestVM = context.read<RequestsVM>();
if (requestVM.currentSelectedRequest != null && requestVM.currentSelectedRequest!.address.isEmpty) {
requestVM.addressSparePartRequestDelivery = "";
WidgetsBinding.instance.addPostFrameCallback((_) async => buildLocationInformationEditBottomSheet(context, requestVM));
}
super.initState();
}
Widget buildPersonalInformation() {
UserInfo userInfo = AppState().getUser.data!.userInfo!;
return Column(
@ -30,7 +51,7 @@ class ReviewRequestOffer extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.personalInformation.tr().toText(fontSize: 18),
MyAssets.icEdit.buildSvg().onPress(() {}),
const SizedBox(),
],
),
8.height,
@ -44,6 +65,7 @@ class ReviewRequestOffer extends StatelessWidget {
children: [
SingleDetailWidget(text: "${userInfo.firstName ?? ""} ${userInfo.lastName ?? ""}", type: LocaleKeys.name.tr()),
16.height,
SingleDetailWidget(text: userInfo.email ?? "", type: LocaleKeys.email.tr()),
],
),
),
@ -52,8 +74,9 @@ class ReviewRequestOffer extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleDetailWidget(text: userInfo.email ?? "", type: "${LocaleKeys.email.tr()} / ${LocaleKeys.phone.tr()}"),
SingleDetailWidget(text: userInfo.mobileNo ?? "", type: LocaleKeys.phone.tr()),
16.height,
const SingleDetailWidget(text: "", type: ""),
],
),
),
@ -64,7 +87,8 @@ class ReviewRequestOffer extends StatelessWidget {
}
Widget buildLocationInformation(BuildContext context) {
final requestVM = context.read<RequestsVM>();
final requestVM = context.watch<RequestsVM>();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -72,7 +96,7 @@ class ReviewRequestOffer extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.locationInformation.tr().toText(fontSize: 18),
MyAssets.icEdit.buildSvg().onPress(() {}),
MyAssets.icEdit.buildSvg().onPress(() => buildLocationInformationEditBottomSheet(context, requestVM)),
],
),
8.height,
@ -81,7 +105,7 @@ class ReviewRequestOffer extends StatelessWidget {
children: [
SingleDetailWidget(text: requestVM.currentSelectedRequest!.address ?? "", type: LocaleKeys.location.tr()),
16.height,
SingleDetailWidget(text: "N/A", type: "${LocaleKeys.email.tr()} / ${LocaleKeys.additionalAddressDetails.tr()}"),
SingleDetailWidget(text: requestVM.additionalAddressSparePartRequestDelivery.isNotEmpty ? requestVM.additionalAddressSparePartRequestDelivery : "N/A", type: LocaleKeys.additionalAddressDetails.tr()),
],
),
],
@ -100,9 +124,9 @@ class ReviewRequestOffer extends StatelessWidget {
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
children: <Widget>[
LocaleKeys.serviceInformation.tr().toText(fontSize: 18),
MyAssets.icEdit.buildSvg().onPress(() {}),
const SizedBox(),
],
),
8.height,
@ -155,6 +179,82 @@ class ReviewRequestOffer extends StatelessWidget {
);
}
Future buildLocationInformationEditBottomSheet(BuildContext context, RequestsVM requestsVM) async {
String additionalDetails = "";
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
title: LocaleKeys.locationInformation.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: MediaQuery.of(context).viewInsets,
child: StatefulBuilder(
builder: (BuildContext context, setState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Update your location information".toText(fontSize: 14, fontWeight: MyFonts.Medium),
8.height,
TxtField(
hint: LocaleKeys.address.tr(),
isNeedClickAll: false,
value: requestsVM.addressSparePartRequestDelivery,
postfixWidget: IconButton(
icon: const Icon(
size: 28,
Icons.add_location_outlined,
),
onPressed: () {
navigateTo(
context,
PickLocationPage(
onPickAddress: (double latitude, double longitude, String address) {
requestsVM.updateAddressSparePartRequestDelivery(address);
setState(() {});
},
),
);
}),
onChanged: (e) => requestsVM.updateAddressSparePartRequestDelivery(e),
),
8.height,
TxtField(
hint: LocaleKeys.additionalAddressDetails.tr(),
isNeedClickAll: false,
value: requestsVM.additionalAddressSparePartRequestDelivery,
onChanged: (e) {
additionalDetails = e;
}),
19.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () {
// TODO: Call some api here to update this info for this specific request.
requestsVM.currentSelectedRequest!.address = requestsVM.addressSparePartRequestDelivery;
requestsVM.updateAdditionalAddressSparePartRequestDelivery(additionalDetails);
requestsVM.notifyListeners();
pop(context);
},
),
)
],
),
25.height,
],
);
},
),
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(

@ -1,26 +1,20 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/requests_models/request_model.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/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class RequestItem extends StatelessWidget {
final RequestModel request;
@ -79,28 +73,28 @@ class RequestItem extends StatelessWidget {
],
),
showItem("${LocaleKeys.description.tr()}:", request.description),
showItem("${LocaleKeys.priceRange.tr()}: ", ""),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
request.price.toInt().toString().toText(fontSize: 19, color: MyColors.darkTextColor, isBold: true, letterSpacing: -1.16),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4).paddingOnly(bottom: 3),
],
),
request.requestStatus == RequestStatusEnum.submitted
? SvgPicture.asset(
MyAssets.arrowRight,
height: 9.69,
width: 13,
)
: const SizedBox()
],
),
// showItem("${LocaleKeys.priceRange.tr()}: ", ""),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// request.price.toInt().toString().toText(fontSize: 19, color: MyColors.darkTextColor, isBold: true, letterSpacing: -1.16),
// 2.width,
// LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4).paddingOnly(bottom: 3),
// ],
// ),
// request.requestStatus == RequestStatusEnum.submitted
// ? SvgPicture.asset(
// MyAssets.arrowRight,
// height: 9.69,
// width: 13,
// )
// : const SizedBox()
// ],
// ),
],
).toContainer(isShadowEnabled: true).onPress(() async {
RequestsVM requestsVM = context.read<RequestsVM>();

@ -45,6 +45,19 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
});
}
bool isAllowContinue(ServiceVM model) {
bool isShow = false;
if (model.document != null && model.document!.data != null && model.document!.data!.isNotEmpty) {
for (var doc in model.document!.data!) {
log("doc: ${doc.status}");
if (doc.status == 4 || doc.status == 0) {
isShow = true;
}
}
}
return isShow;
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -59,7 +72,7 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
);
}
return GestureDetector(
onTap: () => FocusScope.of(context).focusedChild?.unfocus(),
onTap: () => FocusScope.of(context).focusedChild!.unfocus(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -85,7 +98,7 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
status = await updateDocument(serviceVM);
}
Future.delayed(const Duration(seconds: 1), () {
if (status != null && status) {
if (status) {
pop(context);
}
});
@ -111,19 +124,6 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
return valid;
}
bool isAllowContinue(ServiceVM model) {
bool isShow = false;
if (model.document != null && model.document!.data != null && model.document!.data!.isNotEmpty) {
for (var doc in model.document!.data!) {
print("doc: ${doc.status}");
if (doc.status == 4 || doc.status == 0) {
isShow = true;
}
}
}
return isShow;
}
Future<bool> updateDocument(ServiceVM model) async {
try {
Utils.showLoading(context);
@ -131,7 +131,7 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(LocaleKeys.documentsUploadedSuccessfully.tr());
// Navigator.of(context).pop();
Navigator.of(context).pop();
return true;
} else {
Utils.showToast(res.message ?? "");
@ -169,26 +169,21 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
],
],
),
if (document.status != 1 && document.status != 3) ...[
Padding(
padding: const EdgeInsets.only(top: 4, bottom: 8),
child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor),
),
// TxtField(
// hint: LocaleKeys.description.tr(),
// maxLines: 3,
// isBackgroundEnabled: true,
// value: document.description != null ? document.description : "",
// onChanged: (val) {
// document.description = val;
// },
// ),
],
// if (document.status != 1 && document.status != 3) ...[
// Padding(
// padding: const EdgeInsets.only(top: 4, bottom: 8),
// child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor),
// ),
// TxtField(
// hint: LocaleKeys.description.tr(),
// maxLines: 3,
// isBackgroundEnabled: true,
// ),
// ],
10.height,
if (isNeedToShow(model: serviceVM, document: document)) ...[
PickedFilesContainer(
//|| document.status == 3 || document.status != 4
isReview: document.status != 0 && document.status == 1 || document.status == 3,
isReview: document.status != 0 && (document.status == 1 || document.status == 3),
allowAdButton: false,
pickedFiles: isLocalOrNetworkFiles(model: serviceVM, document: document),
onCrossPressedPrimary: isNetworkImage(document: document)

@ -68,7 +68,6 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
needBorderBelow: false,
onTap: () => navigateWithName(context, AppRoutes.settingOptionsInviteFriends),
),
],
).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0),
10.height,
@ -99,7 +98,7 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
),
),
titleText: LocaleKeys.mySubscription.tr(),
subTitle: AppState().getproviderSubscription.first.name ?? "",
subTitle: AppState().getproviderSubscription.isNotEmpty ? (AppState().getproviderSubscription.first.name ?? "") : "",
isForLanguage: false,
needBorderBelow: true,
onTap: () {
@ -208,3 +207,5 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
);
}
}

@ -62,6 +62,7 @@ class _RegisterPageState extends State<RegisterProviderPage> {
@override
Widget build(BuildContext context) {
log("role: ${role}");
return Scaffold(
appBar: const CustomAppBar(isRemoveBackButton: false, title: ""),
body: Container(
@ -79,7 +80,6 @@ class _RegisterPageState extends State<RegisterProviderPage> {
letterSpacing: -1.44,
),
20.height,
LocaleKeys.enterPhoneNumber.tr().toText(
color: MyColors.lightTextColor,
textAlign: TextAlign.center,
@ -100,7 +100,7 @@ class _RegisterPageState extends State<RegisterProviderPage> {
role = snapshot.data?.data?.first.id ?? -1;
}
return RoleTypeTab(
0,
role == 6 ? 1 : 0,
dropList,
onSelect: (DropValue value) {
role = value.id;
@ -118,12 +118,8 @@ class _RegisterPageState extends State<RegisterProviderPage> {
if (snapshot.hasData) {
List<DropValue> dropList = [];
snapshot.data?.data?.forEach((element) {
dropList.add(DropValue(
element.id ?? 0,
EasyLocalization.of(context)?.currentLocale?.countryCode == "SA"
? (element.countryNameN ?? "") + " " + (element.countryCode ?? "")
: (element.countryName ?? "") + " " + (element.countryCode ?? ""),
element.countryCode ?? ""));
dropList.add(DropValue(element.id ?? 0,
EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? "${element.countryNameN ?? ""} ${element.countryCode ?? ""}" : "${element.countryName ?? ""} ${element.countryCode ?? ""}", element.countryCode ?? ""));
});
return Column(
children: [
@ -143,12 +139,12 @@ class _RegisterPageState extends State<RegisterProviderPage> {
},
dropdownValue: selectedDrop,
list: dropList,
hint: LocaleKeys.chooseCountry .tr(),
hint: LocaleKeys.chooseCountry.tr(),
),
],
);
} else {
return CircularProgressIndicator();
return const CircularProgressIndicator();
}
},
),
@ -169,7 +165,7 @@ class _RegisterPageState extends State<RegisterProviderPage> {
child: Row(
children: [
Text(
(countryCode.isEmpty ? "+00" : "+" + countryCode),
(countryCode.isEmpty ? "+00" : "+$countryCode"),
style: const TextStyle(
fontSize: 20,
color: MyColors.black,

@ -0,0 +1,139 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/user_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:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class AddPhoneNumWidget extends StatefulWidget {
const AddPhoneNumWidget({Key? key}) : super(key: key);
@override
State<AddPhoneNumWidget> createState() => _AddPhoneNumWidgetState();
}
class _AddPhoneNumWidgetState extends State<AddPhoneNumWidget> {
String phoneNum = "", countryCode = "";
late UserVM userVM;
Country? _country;
@override
void initState() {
super.initState();
scheduleMicrotask(() {
userVM = Provider.of(context, listen: false);
getCountryList();
});
}
getCountryList() async {
_country = await userVM.getAllCountries();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
width: double.infinity,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
"Enter Phone Number".toText(fontSize: 16, isBold: true),
8.height,
getCountry(context),
8.height,
TxtField(
keyboardType: TextInputType.phone,
hint: "546758594",
value: phoneNum,
isSidePaddingZero: true,
onChanged: (v) {
phoneNum = v;
},
),
16.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: "Cancel",
backgroundColor: MyColors.greyButtonColor,
txtColor: Colors.black,
onPressed: () {
pop(context);
},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: LocaleKeys.sendOTP.tr(),
onPressed: () {
//User Role: Dealer|Manager for a branch
FocusScope.of(context).unfocus();
if (validation()) {
userVM.performBasicOtpRegisterPage(context, countryCode: countryCode, phoneNum: phoneNum, role: 7, isNeedToPassToken: true, reloadPage: () {
pop(context);
});
}
},
),
),
],
)
],
),
),
);
}
Widget getCountry(BuildContext context) {
if (_country != null) {
List<DropValue> dropList = [];
_country!.data?.forEach((element) {
dropList.add(DropValue(element.id ?? 0, "${element.countryName ?? ""} ${element.countryCode ?? ""}", element.countryCode ?? ""));
});
return DropdownField(
(DropValue value) {
countryCode = value.subValue;
},
list: dropList,
hint: countryCode.isNotEmpty ? countryCode.toString() : LocaleKeys.selectCountryCode.tr(),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
}
bool validation() {
bool isValid = true;
if (countryCode.isEmpty) {
Utils.showToast(LocaleKeys.selectCountryCode.tr());
//("Please select Country Code");
isValid = false;
} else if (phoneNum.isEmpty) {
Utils.showToast(LocaleKeys.addPhoneNo.tr());
//("Please add Phone No");
isValid = false;
}
return isValid;
}
}

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
@ -56,13 +57,15 @@ class BranchDetailCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
title.toText(fontSize: 16, isBold: true),
Row(
children: [
("${LocaleKeys.location.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
providerLocation.toText(fontSize: 12, isBold: true),
],
),
if (AppState().currentLocation.latitude != 0 && AppState().currentLocation.longitude != 0) ...[
Row(
children: [
("${LocaleKeys.location.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
providerLocation.toText(fontSize: 12, isBold: true),
],
),
],
if (providerName != null)
Row(
children: [

@ -18,19 +18,18 @@ class CardButtonWithIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 110,
width: 110,
// height: 150,
width: 150,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
icon,
// 16.height,
title.toText(
fontSize: 11,
isBold: true,
textAlign: TextAlign.left,
)
).paddingOnly(top: 10)
],
).toWhiteContainer(allPading: 12, width: double.infinity).onPress(onCardTapped),
);

@ -97,7 +97,7 @@ class _OtpDialogState extends State<OtpDialog> {
height: 1.2,
),
),
Text(" " + LocaleKeys.sec.tr()),
Text(" ${LocaleKeys.sec.tr()}"),
],
),
),

@ -64,7 +64,7 @@ class _DropdownFieldState extends State<DropdownField> {
width: widget.showAppointmentPickerVariant ? 170 : null,
child: DropdownButton<DropValue>(
value: dropdownValue,
icon: Icon(Icons.keyboard_arrow_down_sharp, color: !widget.isSelectAble ? Colors.transparent : null),
icon: Icon(Icons.keyboard_arrow_down_sharp, color: !widget.isSelectAble ? Colors.transparent : null, size: 21,),
elevation: 16,
iconSize: widget.showAppointmentPickerVariant ? 26 : 16,
iconEnabledColor: borderColor,

@ -36,6 +36,7 @@ class TxtField extends StatelessWidget {
Widget? postfixWidget;
Widget? preFixWidget;
bool numbersOnly;
bool allowOnlyOneDigit;
TxtField({
Key? key,
@ -65,6 +66,7 @@ class TxtField extends StatelessWidget {
this.preFixWidget,
this.onPostFixPressed,
this.numbersOnly = false,
this.allowOnlyOneDigit = false,
}) : super(key: key);
@override
@ -101,7 +103,11 @@ class TxtField extends StatelessWidget {
obscureText: isPasswordEnabled ?? false,
onChanged: onChanged,
onSubmitted: onSubmitted,
inputFormatters: numbersOnly ? <TextInputFormatter>[FilteringTextInputFormatter.allow(RegExp('[0-9]'))] : [],
inputFormatters: allowOnlyOneDigit && numbersOnly
? <TextInputFormatter>[FilteringTextInputFormatter.allow(RegExp('[0-9]')), LengthLimitingTextInputFormatter(1)]
: numbersOnly
? <TextInputFormatter>[FilteringTextInputFormatter.allow(RegExp('[0-9]'))]
: [],
decoration: InputDecoration(
labelText: lable,
alignLabelWithHint: true,

Loading…
Cancel
Save