Fixing JIRA Issues

aamir_dev
Faiz Hashmi 12 months ago
parent d414327147
commit 7326886660

@ -698,7 +698,6 @@
"explore": "استكشاف", "explore": "استكشاف",
"manageRequests": "إدارة الطلبات", "manageRequests": "إدارة الطلبات",
"serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.", "serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.",
"noAvailableItems": "لا توجد عناصر متاحة.",
"wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.", "wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.",
"noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.", "noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.",
"testTheService": "اختبر الخدمة.", "testTheService": "اختبر الخدمة.",
@ -706,5 +705,20 @@
"customerLocation": "موقع العميل", "customerLocation": "موقع العميل",
"deliveryAvailable": "التوصيل متاح", "deliveryAvailable": "التوصيل متاح",
"viewed": "تم المشاهدة", "viewed": "تم المشاهدة",
"itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا." "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.",
"reactivateAd": "إعادة تنشيط الإعلان",
"dealOutsideApp": "تمت الصفقة خارج التطبيق مع عميل آخر.",
"noAgreementCustomer": "لا يوجد اتفاق من جانب العميل.",
"dealNotCompleted": "لم تكتمل الصفقة",
"changedDesireToSell": "غيرت رغبتي في بيع المركبة.",
"vehicleDealOutsideApp": "تمت صفقة المركبة خارج التطبيق.",
"markAdAsSoldDesc": "سيتم وضع علامة 'تم البيع' على هذا الإعلان، ولن يتمكن المستخدمون الآخرون من التواصل معك.",
"ownerInformation": "معلومات المالك",
"acceptedRequests": "الطلبات المقبولة",
"specialRequestChat": "دردشة الطلب الخاص",
"companyName": "اسم الشركة",
"noAvailableItems": "لا توجد عناصر متاحة.",
"serviceDeliveryType": "نوع تقديم الخدمة",
"noImagesToShow": "لا توجد صور للعرض",
"updateGroupServices": "تحديث خدمات المجموعة"
} }

@ -626,7 +626,7 @@
"priceRange": "Price Range", "priceRange": "Price Range",
"cancelOffer": "Cancel Offer", "cancelOffer": "Cancel Offer",
"pleaseSpecify": "Please Specify", "pleaseSpecify": "Please Specify",
"customerNotResponding": "Customer Not Responding", "customerNotResponding": "The customer is not responding.",
"cancelRequestPrompt": "Do you want to cancel this request?", "cancelRequestPrompt": "Do you want to cancel this request?",
"requestPermanentlyCancelled": "Your request will be permanently cancelled. You cannot undo this action.", "requestPermanentlyCancelled": "Your request will be permanently cancelled. You cannot undo this action.",
"awaitingResponseFromCustomer": "Awaiting Response From Customer", "awaitingResponseFromCustomer": "Awaiting Response From Customer",
@ -695,7 +695,6 @@
"explore": "Explore", "explore": "Explore",
"manageRequests": "Manage Requests", "manageRequests": "Manage Requests",
"serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.", "serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.",
"noAvailableItems": "There are no available items.",
"wantToRescheduleAppointment": "I want to reschedule the appointment.", "wantToRescheduleAppointment": "I want to reschedule the appointment.",
"noNeedForService": "I do not need this service anymore.", "noNeedForService": "I do not need this service anymore.",
"testTheService": "Test the service.", "testTheService": "Test the service.",
@ -703,6 +702,21 @@
"customerLocation": "Customer Location", "customerLocation": "Customer Location",
"deliveryAvailable": "Delivery Available", "deliveryAvailable": "Delivery Available",
"viewed": "Viewed", "viewed": "Viewed",
"itemNoLongerAvailable": "This item is no longer available." "itemNoLongerAvailable": "This item is no longer available.",
"reactivateAd": "Reactivate Ad",
"dealOutsideApp": "The deal was done outside the app with another customer.",
"noAgreementCustomer": "There is no agreement from the customer side.",
"dealNotCompleted": "Deal not completed",
"changedDesireToSell": "I changed my desire to sell the vehicle.",
"vehicleDealOutsideApp": "The vehicle deal was done outside the app.",
"markAdAsSoldDesc": "This ad will be marked as sold, and other users will no longer be able to contact you.",
"ownerInformation": "Owner Information",
"noItemsToShow": "There are no Items no show.",
"acceptedRequests": "Accepted Requests",
"specialRequestChat": "Special Request Chat",
"companyName": "Company Name",
"noAvailableItems": "There are no available items.",
"serviceDeliveryType": "Service Delivery Type",
"noImagesToShow": "No Images to Show",
"updateGroupServices": "Update Group Services"
} }

@ -14,6 +14,8 @@ class ApiConsts {
static String basicComplete = "${baseUrlServices}api/Register/BasicComplete"; static String basicComplete = "${baseUrlServices}api/Register/BasicComplete";
static String refreshToken = "${baseUrlServices}api/Account/RefreshToken"; static String refreshToken = "${baseUrlServices}api/Account/RefreshToken";
static String signalRUrl = "$baseUrl/McHub";
//User //User
static String Login_V1 = "${baseUrlServices}api/Account/Login_V1"; static String Login_V1 = "${baseUrlServices}api/Account/Login_V1";
static String Login_V2_OTP = "${baseUrlServices}api/Account/Login_V2_OTP"; static String Login_V2_OTP = "${baseUrlServices}api/Account/Login_V2_OTP";
@ -96,6 +98,7 @@ class ApiConsts {
static String updateSchedule = "${baseUrlServices}api/ServiceProviders/BranchAppointmentSchedule_Update"; static String updateSchedule = "${baseUrlServices}api/ServiceProviders/BranchAppointmentSchedule_Update";
static String createGroup = "${baseUrlServices}api/ServiceProviders/BranchScheduleGroupService_Create"; static String createGroup = "${baseUrlServices}api/ServiceProviders/BranchScheduleGroupService_Create";
static String updateGroup = "${baseUrlServices}api/ServiceProviders/BranchScheduleGroupService_Update"; static String updateGroup = "${baseUrlServices}api/ServiceProviders/BranchScheduleGroupService_Update";
static String checkGroupServiceInBranchSchedule = "${baseUrlServices}api/ServiceProviders/BranchScheduleGroupService_Check";
//Advertisement APIs //Advertisement APIs
static String vehicleTypeGet = "${baseUrlServices}api/ServiceProviders/VehicleType_Get"; static String vehicleTypeGet = "${baseUrlServices}api/ServiceProviders/VehicleType_Get";
@ -227,7 +230,8 @@ class GlobalConsts {
static String homeLocationEmptyError = "Home location cannot be empty"; static String homeLocationEmptyError = "Home location cannot be empty";
static String fillAllFields = "Please fill out all the fields."; static String fillAllFields = "Please fill out all the fields.";
static String requestTypeCannotBeEmpty = "Request type cannot be empty."; static String requestTypeCannotBeEmpty = "Request type cannot be empty.";
static String reserveAdPriceInfo = "Some dummy description to explain the following concept. This price will be for 24 hours and if a user cancels the reservations before 24 hours then the amount will be automatically refunded to the buyer."; static String reserveAdPriceInfo =
"Some dummy description to explain the following concept. This price will be for 24 hours and if a user cancels the reservations before 24 hours then the amount will be automatically refunded to the buyer.";
static String appInvitationMessageEn = "🚗 Hey , check out MOWATER to book car services, buy/sell vehicles, and more—join here! [Invite Link]"; static String appInvitationMessageEn = "🚗 Hey , check out MOWATER to book car services, buy/sell vehicles, and more—join here! [Invite Link]";
static String getAppInvitationLink() { static String getAppInvitationLink() {

@ -18,6 +18,7 @@ import 'package:mc_common_app/views/requests/offer_list_page.dart';
import 'package:mc_common_app/views/requests/request_detail_page.dart'; import 'package:mc_common_app/views/requests/request_detail_page.dart';
import 'package:mc_common_app/views/requests/requests_filter_view.dart'; import 'package:mc_common_app/views/requests/requests_filter_view.dart';
import 'package:mc_common_app/views/requests/review_request_offer.dart'; import 'package:mc_common_app/views/requests/review_request_offer.dart';
import 'package:mc_common_app/views/setting_options/provider_accepted_requests_view.dart';
import 'package:mc_common_app/views/setting_options/provider_license_page.dart'; import 'package:mc_common_app/views/setting_options/provider_license_page.dart';
import 'package:mc_common_app/views/setting_options/setting_option_help.dart'; import 'package:mc_common_app/views/setting_options/setting_option_help.dart';
import 'package:mc_common_app/views/setting_options/setting_options_app_info.dart'; import 'package:mc_common_app/views/setting_options/setting_options_app_info.dart';
@ -145,6 +146,7 @@ class AppRoutes {
static const String createRequestPage = "/createRequestPage"; static const String createRequestPage = "/createRequestPage";
static const String offersListPage = "/offersListPage"; static const String offersListPage = "/offersListPage";
static const String reviewRequestOffer = "/reviewRequestOffer"; static const String reviewRequestOffer = "/reviewRequestOffer";
static const String providerAcceptedRequestsView = "/providerAcceptedRequestsView";
//Setting Options //Setting Options
static const String settingOptionsFaqs = "/settingOptionsFaqs"; static const String settingOptionsFaqs = "/settingOptionsFaqs";
@ -208,7 +210,7 @@ class AppRoutes {
//Requests //Requests
AppRoutes.requestsDetailPage: (context) => RequestDetailPage(requestDetailPageArguments: ModalRoute.of(context)!.settings.arguments as RequestDetailPageArguments), AppRoutes.requestsDetailPage: (context) => RequestDetailPage(requestDetailPageArguments: ModalRoute.of(context)!.settings.arguments as RequestDetailPageArguments),
AppRoutes.createRequestPage: (context) => const CreateRequestPage(), AppRoutes.createRequestPage: (context) => const CreateRequestPage(),
AppRoutes.offersListPage: (context) => OfferListPage(offerListPageArguments: ModalRoute.of(context)!.settings.arguments as OfferListPageArguments), AppRoutes.offersListPage: (context) => OfferListPage(requestId: ModalRoute.of(context)!.settings.arguments as int),
AppRoutes.reviewRequestOffer: (context) => const ReviewRequestOffer(), AppRoutes.reviewRequestOffer: (context) => const ReviewRequestOffer(),
AppRoutes.requestsFilterView: (context) => const RequestsFilterView(), AppRoutes.requestsFilterView: (context) => const RequestsFilterView(),
@ -216,7 +218,7 @@ class AppRoutes {
AppRoutes.mediaViewerScreen: (context) => MediaViewerScreen(images: ModalRoute.of(context)!.settings.arguments as List<MessageImageModel>), AppRoutes.mediaViewerScreen: (context) => MediaViewerScreen(images: ModalRoute.of(context)!.settings.arguments as List<MessageImageModel>),
// ChatsList Provider // ChatsList Provider
AppRoutes.generalChatsListForProvider: (context) => OfferListPage(offerListPageArguments: ModalRoute.of(context)!.settings.arguments as OfferListPageArguments), AppRoutes.generalChatsListForProvider: (context) => OfferListPage(requestId: ModalRoute.of(context)!.settings.arguments as int),
//Shipping //Shipping
AppRoutes.shippingManagementView: (context) => const ShippingManagementView(), AppRoutes.shippingManagementView: (context) => const ShippingManagementView(),

@ -238,6 +238,8 @@ extension AdPostEnum on int {
return AdPostStatus.buyingService; return AdPostStatus.buyingService;
} else if (this == 11) { } else if (this == 11) {
return AdPostStatus.reserveCancel; return AdPostStatus.reserveCancel;
} else if (this == 12) {
return AdPostStatus.deActive;
} else if (this == 0) { } else if (this == 0) {
return AdPostStatus.allAds; return AdPostStatus.allAds;
} else { } else {
@ -264,15 +266,21 @@ extension AppointmentStatusToInt on AppointmentStatusEnum {
case AppointmentStatusEnum.rescheduled: case AppointmentStatusEnum.rescheduled:
return 5; return 5;
case AppointmentStatusEnum.upcoming:
return 6;
case AppointmentStatusEnum.workStarted: case AppointmentStatusEnum.workStarted:
return 7; return 7;
case AppointmentStatusEnum.visitCompleted: case AppointmentStatusEnum.visitCompleted:
return 8; return 8;
case AppointmentStatusEnum.today:
return 9;
case AppointmentStatusEnum.past:
return 10;
case AppointmentStatusEnum.upcoming:
return 11;
case AppointmentStatusEnum.allAppointments: case AppointmentStatusEnum.allAppointments:
return 0; return 0;
@ -334,14 +342,18 @@ extension AppointmentStatusToString on AppointmentStatusEnum {
case AppointmentStatusEnum.visitCompleted: case AppointmentStatusEnum.visitCompleted:
return "Visit Completed"; return "Visit Completed";
case AppointmentStatusEnum.past:
return "Past";
case AppointmentStatusEnum.today:
return "Today";
default: default:
return "Booked"; return "Booked";
} }
} }
} }
//TODO: Need to verify Enum on upcoming and inprogress with the database
//TODO: 6 is service Deactivated
extension AppointmentEnum on int { extension AppointmentEnum on int {
AppointmentStatusEnum toAppointmentStatusEnum() { AppointmentStatusEnum toAppointmentStatusEnum() {
if (this == 1) { if (this == 1) {
@ -354,12 +366,16 @@ extension AppointmentEnum on int {
return AppointmentStatusEnum.cancelled; return AppointmentStatusEnum.cancelled;
} else if (this == 5) { } else if (this == 5) {
return AppointmentStatusEnum.rescheduled; return AppointmentStatusEnum.rescheduled;
} else if (this == 6) {
return AppointmentStatusEnum.upcoming;
} else if (this == 7) { } else if (this == 7) {
return AppointmentStatusEnum.workStarted; return AppointmentStatusEnum.workStarted;
} else if (this == 8) { } else if (this == 8) {
return AppointmentStatusEnum.visitCompleted; return AppointmentStatusEnum.visitCompleted;
} else if (this == 9) {
return AppointmentStatusEnum.today;
} else if (this == 10) {
return AppointmentStatusEnum.past;
} else if (this == 11) {
return AppointmentStatusEnum.upcoming;
} else { } else {
return AppointmentStatusEnum.allAppointments; return AppointmentStatusEnum.allAppointments;
} }
@ -409,7 +425,7 @@ extension AppointmentPaymentEnum on int {
} }
extension RequestTypeTypEnum on int { extension RequestTypeTypEnum on int {
RequestsTypeEnum toRequestTypeStatusEnum() { RequestsTypeEnum toRequestTypeEnum() {
if (this == 1) { if (this == 1) {
return RequestsTypeEnum.specialCarRequest; return RequestsTypeEnum.specialCarRequest;
} else if (this == 2) { } else if (this == 2) {
@ -420,7 +436,7 @@ extension RequestTypeTypEnum on int {
} }
extension RequestTypeStatusToInt on RequestsTypeEnum { extension RequestTypeStatusToInt on RequestsTypeEnum {
int getIdFromRequestTypeStatusEnum() { int getIdFromRequestTypeEnum() {
switch (this) { switch (this) {
case RequestsTypeEnum.specialCarRequest: case RequestsTypeEnum.specialCarRequest:
return 1; return 1;
@ -439,6 +455,7 @@ extension AdPostStatusToInt on AdPostStatus {
switch (this) { switch (this) {
case AdPostStatus.pendingForReview: case AdPostStatus.pendingForReview:
return 1; return 1;
case AdPostStatus.pendingForPayment: case AdPostStatus.pendingForPayment:
return 2; return 2;
@ -468,6 +485,10 @@ extension AdPostStatusToInt on AdPostStatus {
case AdPostStatus.reserveCancel: case AdPostStatus.reserveCancel:
return 11; return 11;
case AdPostStatus.deActive:
return 12;
default: default:
return 0; return 0;
} }
@ -910,8 +931,10 @@ extension SubscriptionTypeEnumToString on SubscriptionTypeEnum {
extension ShippingStatusEnumExt on int { extension ShippingStatusEnumExt on int {
ShippingRequestStatusEnum toShippingStatusEnum() { ShippingRequestStatusEnum toShippingStatusEnum() {
if (this == 0) { if (this == -1) {
return ShippingRequestStatusEnum.allRequests; return ShippingRequestStatusEnum.allRequests;
} else if (this == 0) {
return ShippingRequestStatusEnum.pending;
} else if (this == 1) { } else if (this == 1) {
return ShippingRequestStatusEnum.initiated; return ShippingRequestStatusEnum.initiated;
} else if (this == 2) { } else if (this == 2) {
@ -921,13 +944,15 @@ extension ShippingStatusEnumExt on int {
} else if (this == 4) { } else if (this == 4) {
return ShippingRequestStatusEnum.delivered; return ShippingRequestStatusEnum.delivered;
} }
return ShippingRequestStatusEnum.initiated; return ShippingRequestStatusEnum.pending;
} }
} }
extension ShippingStatusEnumToInt on ShippingRequestStatusEnum { extension ShippingStatusEnumToInt on ShippingRequestStatusEnum {
int getIdFromShippingStatusEnum() { int getIdFromShippingStatusEnum() {
switch (this) { switch (this) {
case ShippingRequestStatusEnum.pending:
return 0;
case ShippingRequestStatusEnum.initiated: case ShippingRequestStatusEnum.initiated:
return 1; return 1;
case ShippingRequestStatusEnum.inTransit: case ShippingRequestStatusEnum.inTransit:
@ -936,7 +961,6 @@ extension ShippingStatusEnumToInt on ShippingRequestStatusEnum {
return 3; return 3;
case ShippingRequestStatusEnum.delivered: case ShippingRequestStatusEnum.delivered:
return 4; return 4;
default: default:
return 0; return 0;
} }

@ -714,7 +714,6 @@ class CodegenLoader extends AssetLoader{
"explore": "استكشاف", "explore": "استكشاف",
"manageRequests": "إدارة الطلبات", "manageRequests": "إدارة الطلبات",
"serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.", "serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.",
"noAvailableItems": "لا توجد عناصر متاحة.",
"wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.", "wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.",
"noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.", "noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.",
"testTheService": "اختبر الخدمة.", "testTheService": "اختبر الخدمة.",
@ -722,7 +721,22 @@ class CodegenLoader extends AssetLoader{
"customerLocation": "موقع العميل", "customerLocation": "موقع العميل",
"deliveryAvailable": "التوصيل متاح", "deliveryAvailable": "التوصيل متاح",
"viewed": "تم المشاهدة", "viewed": "تم المشاهدة",
"itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا." "itemNoLongerAvailable": "لم يعد هذا العنصر متاحًا.",
"reactivateAd": "إعادة تنشيط الإعلان",
"dealOutsideApp": "تمت الصفقة خارج التطبيق مع عميل آخر.",
"noAgreementCustomer": "لا يوجد اتفاق من جانب العميل.",
"dealNotCompleted": "لم تكتمل الصفقة",
"changedDesireToSell": "غيرت رغبتي في بيع المركبة.",
"vehicleDealOutsideApp": "تمت صفقة المركبة خارج التطبيق.",
"markAdAsSoldDesc": "سيتم وضع علامة 'تم البيع' على هذا الإعلان، ولن يتمكن المستخدمون الآخرون من التواصل معك.",
"ownerInformation": "معلومات المالك",
"acceptedRequests": "الطلبات المقبولة",
"specialRequestChat": "دردشة الطلب الخاص",
"companyName": "اسم الشركة",
"noAvailableItems": "لا توجد عناصر متاحة.",
"serviceDeliveryType": "نوع تقديم الخدمة",
"noImagesToShow": "لا توجد صور للعرض",
"updateGroupServices": "تحديث خدمات المجموعة"
}; };
static const Map<String,dynamic> en_US = { static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In", "firstTimeLogIn": "First Time Log In",
@ -1352,7 +1366,7 @@ static const Map<String,dynamic> en_US = {
"priceRange": "Price Range", "priceRange": "Price Range",
"cancelOffer": "Cancel Offer", "cancelOffer": "Cancel Offer",
"pleaseSpecify": "Please Specify", "pleaseSpecify": "Please Specify",
"customerNotResponding": "Customer Not Responding", "customerNotResponding": "The customer is not responding.",
"cancelRequestPrompt": "Do you want to cancel this request?", "cancelRequestPrompt": "Do you want to cancel this request?",
"requestPermanentlyCancelled": "Your request will be permanently cancelled. You cannot undo this action.", "requestPermanentlyCancelled": "Your request will be permanently cancelled. You cannot undo this action.",
"awaitingResponseFromCustomer": "Awaiting Response From Customer", "awaitingResponseFromCustomer": "Awaiting Response From Customer",
@ -1421,7 +1435,6 @@ static const Map<String,dynamic> en_US = {
"explore": "Explore", "explore": "Explore",
"manageRequests": "Manage Requests", "manageRequests": "Manage Requests",
"serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.", "serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.",
"noAvailableItems": "There are no available items.",
"wantToRescheduleAppointment": "I want to reschedule the appointment.", "wantToRescheduleAppointment": "I want to reschedule the appointment.",
"noNeedForService": "I do not need this service anymore.", "noNeedForService": "I do not need this service anymore.",
"testTheService": "Test the service.", "testTheService": "Test the service.",
@ -1429,7 +1442,23 @@ static const Map<String,dynamic> en_US = {
"customerLocation": "Customer Location", "customerLocation": "Customer Location",
"deliveryAvailable": "Delivery Available", "deliveryAvailable": "Delivery Available",
"viewed": "Viewed", "viewed": "Viewed",
"itemNoLongerAvailable": "This item is no longer available." "itemNoLongerAvailable": "This item is no longer available.",
"reactivateAd": "Reactivate Ad",
"dealOutsideApp": "The deal was done outside the app with another customer.",
"noAgreementCustomer": "There is no agreement from the customer side.",
"dealNotCompleted": "Deal not completed",
"changedDesireToSell": "I changed my desire to sell the vehicle.",
"vehicleDealOutsideApp": "The vehicle deal was done outside the app.",
"markAdAsSoldDesc": "This ad will be marked as sold, and other users will no longer be able to contact you.",
"ownerInformation": "Owner Information",
"noItemsToShow": "There are no Items no show.",
"acceptedRequests": "Accepted Requests",
"specialRequestChat": "Special Request Chat",
"companyName": "Company Name",
"noAvailableItems": "There are no available items.",
"serviceDeliveryType": "Service Delivery Type",
"noImagesToShow": "No Images to Show",
"updateGroupServices": "Update Group Services"
}; };
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
} }

@ -677,7 +677,6 @@ abstract class LocaleKeys {
static const explore = 'explore'; static const explore = 'explore';
static const manageRequests = 'manageRequests'; static const manageRequests = 'manageRequests';
static const serviceNotAvailableAtHomeLocation = 'serviceNotAvailableAtHomeLocation'; static const serviceNotAvailableAtHomeLocation = 'serviceNotAvailableAtHomeLocation';
static const noAvailableItems = 'noAvailableItems';
static const wantToRescheduleAppointment = 'wantToRescheduleAppointment'; static const wantToRescheduleAppointment = 'wantToRescheduleAppointment';
static const noNeedForService = 'noNeedForService'; static const noNeedForService = 'noNeedForService';
static const testTheService = 'testTheService'; static const testTheService = 'testTheService';
@ -686,5 +685,19 @@ abstract class LocaleKeys {
static const deliveryAvailable = 'deliveryAvailable'; static const deliveryAvailable = 'deliveryAvailable';
static const viewed = 'viewed'; static const viewed = 'viewed';
static const itemNoLongerAvailable = 'itemNoLongerAvailable'; static const itemNoLongerAvailable = 'itemNoLongerAvailable';
static const reactivateAd = 'reactivateAd';
static const dealOutsideApp = 'dealOutsideApp';
static const noAgreementCustomer = 'noAgreementCustomer';
static const dealNotCompleted = 'dealNotCompleted';
static const changedDesireToSell = 'changedDesireToSell';
static const vehicleDealOutsideApp = 'vehicleDealOutsideApp';
static const markAdAsSoldDesc = 'markAdAsSoldDesc';
static const ownerInformation = 'ownerInformation';
static const acceptedRequests = 'acceptedRequests';
static const specialRequestChat = 'specialRequestChat';
static const companyName = 'companyName';
static const noAvailableItems = 'noAvailableItems';
static const serviceDeliveryType = 'serviceDeliveryType';
static const noImagesToShow = 'noImagesToShow';
static const updateGroupServices = 'updateGroupServices';
} }

@ -45,6 +45,8 @@ class AdDetailsModel {
String? phoneNo; String? phoneNo;
String? whatsAppNo; String? whatsAppNo;
String? adOwnerName; String? adOwnerName;
String? adOwnerEmail;
AdOwnerDetails? adOwnerDetails;
String? warrantyYears; String? warrantyYears;
CreatedByRoleEnum? createdByRoleEnum; CreatedByRoleEnum? createdByRoleEnum;
List<ChatMessageModel>? adMessages; List<ChatMessageModel>? adMessages;
@ -87,6 +89,8 @@ class AdDetailsModel {
this.phoneNo, this.phoneNo,
this.whatsAppNo, this.whatsAppNo,
this.adOwnerName, this.adOwnerName,
this.adOwnerEmail,
this.adOwnerDetails,
this.warrantyYears, this.warrantyYears,
this.createdByRoleEnum, this.createdByRoleEnum,
this.modifiedOn, this.modifiedOn,
@ -138,7 +142,9 @@ class AdDetailsModel {
phoneNo = json['vehicle'] != null ? (json['vehicle']['mobileNo'] ?? "") : ""; phoneNo = json['vehicle'] != null ? (json['vehicle']['mobileNo'] ?? "") : "";
whatsAppNo = json['vehicle'] != null ? (json['vehicle']['whatsAppNo'] ?? "") : ""; whatsAppNo = json['vehicle'] != null ? (json['vehicle']['whatsAppNo'] ?? "") : "";
warrantyYears = json['vehicle'] != null ? (json['vehicle']['warantyYears'] != null ? ((json['vehicle']['warantyYears']).toString()) : "") : ""; warrantyYears = json['vehicle'] != null ? (json['vehicle']['warantyYears'] != null ? ((json['vehicle']['warantyYears']).toString()) : "") : "";
adOwnerName = json['adOwnerName'] ?? ""; adOwnerName = json['vehicle'] != null ? (json['vehicle']['adOwnerName'] ?? "") : "";
adOwnerEmail = json['vehicle'] != null ? (json['vehicle']['adOwnerEmail'] ?? "") : "";
adOwnerDetails = (json['vehicle'] != null && json['vehicle']['aDsUser'] != null) ? (AdOwnerDetails.fromJson(json['vehicle']['aDsUser'])) : null;
adPostStatus = (json['statusID'] as int).toAdPostEnum(); adPostStatus = (json['statusID'] as int).toAdPostEnum();
adReserveStatus = AdReserveStatus.defaultStatus; adReserveStatus = AdReserveStatus.defaultStatus;
createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum(); createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum();
@ -155,7 +161,7 @@ class Vehicle {
bool? isActive; bool? isActive;
bool? isFinanceAvailable; bool? isFinanceAvailable;
int? status; int? status;
String? statustext; String? statusText;
Category? category; Category? category;
Category? color; Category? color;
Condition? condition; Condition? condition;
@ -174,14 +180,15 @@ class Vehicle {
int? countryID; int? countryID;
String? currency; String? currency;
Vehicle({this.id, Vehicle(
{this.id,
this.cityID, this.cityID,
this.cityName, this.cityName,
this.demandAmount, this.demandAmount,
this.isActive, this.isActive,
this.isFinanceAvailable, this.isFinanceAvailable,
this.status, this.status,
this.statustext, this.statusText,
this.category, this.category,
this.color, this.color,
this.condition, this.condition,
@ -208,7 +215,7 @@ class Vehicle {
isActive = json['isActive']; isActive = json['isActive'];
isFinanceAvailable = json['isFinanceAvailable']; isFinanceAvailable = json['isFinanceAvailable'];
status = json['status']; status = json['status'];
statustext = json['statustext']; statusText = json['statustext'];
category = json['category'] != null ? Category.fromJson(json['category']) : null; category = json['category'] != null ? Category.fromJson(json['category']) : null;
color = json['color'] != null ? Category.fromJson(json['color']) : null; color = json['color'] != null ? Category.fromJson(json['color']) : null;
condition = json['condition'] != null ? Condition.fromJson(json['condition']) : null; condition = json['condition'] != null ? Condition.fromJson(json['condition']) : null;
@ -417,3 +424,28 @@ class DamageReport {
return data; return data;
} }
} }
class AdOwnerDetails {
String? name;
String? email;
String? mobileNo;
String? profilePic;
AdOwnerDetails({this.name, this.email, this.mobileNo, this.profilePic});
AdOwnerDetails.fromJson(Map<String, dynamic> json) {
name = json['name'];
email = json['email'];
mobileNo = json['mobileNo'];
profilePic = json['profilePic'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['email'] = email;
data['mobileNo'] = mobileNo;
data['profilePic'] = profilePic;
return data;
}
}

@ -11,6 +11,7 @@ class CustomTimeDateSlotModel {
} }
class ServiceAppointmentScheduleModel { class ServiceAppointmentScheduleModel {
String? scheduleName;
List<ServiceSlotList>? serviceSlotList; List<ServiceSlotList>? serviceSlotList;
List<ServiceModel>? servicesListInAppointment; List<ServiceModel>? servicesListInAppointment;
int? selectedDateIndex; int? selectedDateIndex;
@ -23,6 +24,7 @@ class ServiceAppointmentScheduleModel {
AppointmentTypeEnum? appointmentTypeEnum; AppointmentTypeEnum? appointmentTypeEnum;
ServiceAppointmentScheduleModel({ ServiceAppointmentScheduleModel({
this.scheduleName,
this.serviceSlotList, this.serviceSlotList,
this.servicesListInAppointment, this.servicesListInAppointment,
this.selectedDateIndex, this.selectedDateIndex,
@ -90,6 +92,8 @@ class ServiceAppointmentScheduleModel {
} }
ServiceAppointmentScheduleModel.fromJson(Map<String, dynamic> json, {bool isForAppointment = false}) { ServiceAppointmentScheduleModel.fromJson(Map<String, dynamic> json, {bool isForAppointment = false}) {
scheduleName = json['scheduleName'];
if (json['serviceSlotList'] != null) { if (json['serviceSlotList'] != null) {
serviceSlotList = <ServiceSlotList>[]; serviceSlotList = <ServiceSlotList>[];
json['serviceSlotList'].forEach((v) { json['serviceSlotList'].forEach((v) {

@ -34,7 +34,7 @@ class ProviderOffersModel {
this.serviceProviders, this.serviceProviders,
}); });
ProviderOffersModel.fromJson(Map<String, dynamic> json) { ProviderOffersModel.fromJson(Map<String, dynamic> json, int? reqId) {
id = json['id']; id = json['id'];
customerID = json['customerID']; customerID = json['customerID'];
requestType = json['requestType']; requestType = json['requestType'];
@ -49,7 +49,7 @@ class ProviderOffersModel {
if (json['serviceProviders'] != null) { if (json['serviceProviders'] != null) {
serviceProviders = <ServiceProvidersOffers>[]; serviceProviders = <ServiceProvidersOffers>[];
json['serviceProviders'].forEach((v) { json['serviceProviders'].forEach((v) {
serviceProviders!.add(ServiceProvidersOffers.fromJson(v)); serviceProviders!.add(ServiceProvidersOffers.fromJson(v, reqId));
}); });
} }
} }
@ -65,6 +65,7 @@ class ServiceProvidersOffers {
String? createdOn; String? createdOn;
RequestOfferStatusEnum? requestOfferStatusEnum; RequestOfferStatusEnum? requestOfferStatusEnum;
int? offerCount; int? offerCount;
int? requestId;
List<ChatMessageModel>? chatMessages; List<ChatMessageModel>? chatMessages;
ServiceProvidersOffers({ ServiceProvidersOffers({
@ -74,13 +75,14 @@ class ServiceProvidersOffers {
this.email, this.email,
this.companyName, this.companyName,
this.offerCount, this.offerCount,
this.requestId,
this.chatMessages, this.chatMessages,
this.providerUserId, this.providerUserId,
this.createdOn, this.createdOn,
this.requestOfferStatusEnum, this.requestOfferStatusEnum,
}); });
ServiceProvidersOffers.fromJson(Map<String, dynamic> json) { ServiceProvidersOffers.fromJson(Map<String, dynamic> json, int? reqId) {
providerId = json['providerID']; providerId = json['providerID'];
providerUserId = json['providerUserID']; providerUserId = json['providerUserID'];
name = json['name']; name = json['name'];
@ -88,6 +90,7 @@ class ServiceProvidersOffers {
email = json['email']; email = json['email'];
companyName = json['companyName']; companyName = json['companyName'];
offerCount = json['offerCount']; offerCount = json['offerCount'];
requestId = reqId;
createdOn = json['createdOn']; createdOn = json['createdOn'];
requestOfferStatusEnum = ((json['offerStatusLast']) as int).toRequestOfferStatusEnum(); requestOfferStatusEnum = ((json['offerStatusLast']) as int).toRequestOfferStatusEnum();
chatMessages = []; chatMessages = [];

@ -1,27 +1,80 @@
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/enums.dart';
class ShippingRequestModel { class ShippingRequestModel {
int? id; int? id;
int? requestID; int? requestID;
RequestModel? request; Request? request;
int? shippingStatus; int? shippingStatus;
ShippingRequestStatusEnum? shippingStatusEnum; ShippingRequestStatusEnum? shippingStatusEnum;
String? deliveredOn; String? deliveredOn;
String? comment; String? comment;
String? createdOn; String? createdOn;
int? customerID;
String? customerName;
ShippingRequestModel({this.id, this.requestID, this.request, this.shippingStatus, this.deliveredOn, this.comment, this.createdOn}); ShippingRequestModel({this.id, this.requestID, this.request, this.shippingStatus, this.deliveredOn, this.comment, this.createdOn, this.customerID, this.customerName});
ShippingRequestModel.fromJson(Map<String, dynamic> json) { ShippingRequestModel.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
requestID = json['requestID']; requestID = json['requestID'];
request = json['request']; request = json['request'] != null ? Request.fromJson(json['request']) : null;
shippingStatus = json['shippingStatus']; shippingStatus = json['shippingStatus'];
shippingStatusEnum = json['shippingStatus'] != null ? (json['shippingStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.initiated; shippingStatusEnum = json['shippingStatus'] != null ? (json['shippingStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.initiated;
deliveredOn = json['deliveredOn']; deliveredOn = json['deliveredOn'];
comment = json['comment']; comment = json['comment'];
createdOn = json['createdOn']; createdOn = json['createdOn'];
customerID = json['customerID'];
customerName = json['customerName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['requestID'] = requestID;
if (request != null) {
data['request'] = request!.toJson();
}
data['shippingStatus'] = shippingStatus;
data['deliveredOn'] = deliveredOn;
data['comment'] = comment;
data['createdOn'] = createdOn;
data['customerID'] = customerID;
data['customerName'] = customerName;
return data;
}
}
class Request {
int? requestType;
String? brand;
String? model;
int? year;
bool? isNew;
String? description;
double? price;
Request({this.requestType, this.brand, this.model, this.year, this.isNew, this.description, this.price});
Request.fromJson(Map<String, dynamic> json) {
requestType = json['requestType'];
brand = json['brand'];
model = json['model'];
year = json['year'];
isNew = json['isNew'];
description = json['description'];
price = json['price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['requestType'] = requestType;
data['brand'] = brand;
data['model'] = model;
data['year'] = year;
data['isNew'] = isNew;
data['description'] = description;
data['price'] = price;
return data;
} }
} }

@ -67,7 +67,8 @@ class AdsRepoImp implements AdsRepo {
var params = { var params = {
"SpecialServiceType": specialServiceType.toString(), "SpecialServiceType": specialServiceType.toString(),
}; };
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params); GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params);
List<SpecialServiceModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index])); List<SpecialServiceModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index]));
return vehicleAdsDuration; return vehicleAdsDuration;
} }
@ -89,7 +90,14 @@ class AdsRepoImp implements AdsRepo {
List vehiclePostingDamageParts = []; List vehiclePostingDamageParts = [];
adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts?.forEach((element) { adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts?.forEach((element) {
var imageMap = {"id": element.id ?? 0, "comment": element.comment, "vehicleImageBase64": element.vehicleImageBase64, "vehicleDamagePartID": element.vehicleDamagePartID, "vehiclePostingID": element.vehiclePostingID ?? 0, "isActive": true}; var imageMap = {
"id": element.id ?? 0,
"comment": element.comment,
"vehicleImageBase64": element.vehicleImageBase64,
"vehicleDamagePartID": element.vehicleDamagePartID,
"vehiclePostingID": element.vehiclePostingID ?? 0,
"isActive": true
};
vehiclePostingDamageParts.add(imageMap); vehiclePostingDamageParts.add(imageMap);
}); });
var postParams = { var postParams = {
@ -148,13 +156,15 @@ class AdsRepoImp implements AdsRepo {
}; };
if (isMyAds && adPostStatus != null) { if (isMyAds && adPostStatus != null) {
onlyMyAdsParams.addAll({ onlyMyAdsParams.addAll({
"AdsStatuses": ["${adPostStatus.getIdFromAdPostStatusEnum()}"] "AdsStatuses": ["${adPostStatus.getIdFromAdPostStatusEnum()}"],
"PageSize": "30",
}); });
} }
var allAdsParams = { var allAdsParams = {
"AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS "AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS
"isActive": "true", //only Active ADS "isActive": "true", //only Active ADS
"isExplore": "true" "isExplore": "true",
"PageSize": "30",
}; };
if (!isMyAds && createdByRoleEnum != null) { if (!isMyAds && createdByRoleEnum != null) {
@ -186,7 +196,8 @@ class AdsRepoImp implements AdsRepo {
"CreatedByRoles": createdByRolesIdsList ?? [], "CreatedByRoles": createdByRolesIdsList ?? [],
"AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS "AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS
"isActive": "true", //only Active ADS "isActive": "true", //only Active ADS
"isExplore": "true" "isExplore": "true",
"PageSize": "30",
}; };
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
@ -222,7 +233,11 @@ class AdsRepoImp implements AdsRepo {
} }
Future<List<AdDetailsModel>> getAdsPerSpecificIds({required List<String> ids, required List<MyReservedAdsRespModel> reservedAds}) async { Future<List<AdDetailsModel>> getAdsPerSpecificIds({required List<String> ids, required List<MyReservedAdsRespModel> reservedAds}) async {
var params = {"AdsIDs": ids, "isActive": "true"}; var params = {
"AdsIDs": ids,
"isActive": "true",
"PageSize": "30",
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
@ -243,6 +258,7 @@ class AdsRepoImp implements AdsRepo {
Future<List<AdDetailsModel>> getMyAds() async { Future<List<AdDetailsModel>> getMyAds() async {
var params = { var params = {
"userID": appState.getUser.data!.userInfo!.userId ?? "", "userID": appState.getUser.data!.userInfo!.userId ?? "",
"PageSize": "30",
}; };
GenericRespModel adsGenericModel = await apiClient.getJsonForObject( GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken, token: appState.getUser.data!.accessToken,

@ -132,7 +132,8 @@ class AppointmentRepoImp implements AppointmentRepo {
if (adsGenericModel.data == null) { if (adsGenericModel.data == null) {
return []; return [];
} }
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel = List.generate(adsGenericModel.data.length, (index) => ServiceAppointmentScheduleModel.fromJson(adsGenericModel.data[index], isForAppointment: true)); List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel =
List.generate(adsGenericModel.data.length, (index) => ServiceAppointmentScheduleModel.fromJson(adsGenericModel.data[index], isForAppointment: true));
return serviceAppointmentScheduleModel; return serviceAppointmentScheduleModel;
} }
@ -149,8 +150,19 @@ class AppointmentRepoImp implements AppointmentRepo {
serviceItemIds.add(item.id!); serviceItemIds.add(item.id!);
} }
} }
int slotId = 0;
int index = schedule.selectedCustomTimeDateSlotModel!.availableSlots!.indexWhere((element) => element.isSelected);
if (index == -1) {
index = 0;
}
slotId = schedule.selectedCustomTimeDateSlotModel!.availableSlots![index].slotId;
mapList.add({ mapList.add({
"serviceSlotID": schedule.selectedCustomTimeDateSlotModel!.date!.slotId, "serviceSlotID": slotId,
"serviceProviderID": serviceProviderID, "serviceProviderID": serviceProviderID,
"customerID": customerId, "customerID": customerId,
"serviceItemID": serviceItemIds, "serviceItemID": serviceItemIds,

@ -51,7 +51,7 @@ class ChatRepoImp implements ChatRepo {
@override @override
Future<HubConnection> getHubConnection() async { Future<HubConnection> getHubConnection() async {
final userId = AppState().getUser.data!.userInfo!.userId ?? ""; final userId = AppState().getUser.data!.userInfo!.userId ?? "";
final hubUrl = "https://ms.hmg.com/McHub?userID=$userId"; final hubUrl = "${ApiConsts.signalRUrl}?userID=$userId";
logger.i("Connecting with Hub ($hubUrl)"); logger.i("Connecting with Hub ($hubUrl)");
HubConnection hub; HubConnection hub;

@ -38,6 +38,7 @@ abstract class RequestRepo {
Future<List<RequestModel>> getRequestsBasedOnFilters({ Future<List<RequestModel>> getRequestsBasedOnFilters({
required int requestTypeId, required int requestTypeId,
int requestStatusId = 0, int requestStatusId = 0,
int reqOfferStatus = 0,
int? cityId = 0, int? cityId = 0,
int? vehicleYearId = 0, int? vehicleYearId = 0,
String? vehicleModel = "", String? vehicleModel = "",
@ -131,6 +132,7 @@ class RequestRepoImp implements RequestRepo {
Future<List<RequestModel>> getRequestsBasedOnFilters({ Future<List<RequestModel>> getRequestsBasedOnFilters({
required int requestTypeId, required int requestTypeId,
int requestStatusId = 0, int requestStatusId = 0,
int reqOfferStatus = 0,
int? cityId = 0, int? cityId = 0,
int? vehicleYearId = 0, int? vehicleYearId = 0,
String? vehicleModel = "", String? vehicleModel = "",
@ -146,6 +148,7 @@ class RequestRepoImp implements RequestRepo {
"doPagination": true, "doPagination": true,
"requestType": requestTypeId.toString(), "requestType": requestTypeId.toString(),
"requestStatus": requestStatusId.toString(), "requestStatus": requestStatusId.toString(),
"reqOfferStatus": reqOfferStatus.toString(),
"brand": vehicleBrand.toString(), "brand": vehicleBrand.toString(),
"requestedDate": requestedDate, "requestedDate": requestedDate,
"model": vehicleModel.toString(), "model": vehicleModel.toString(),
@ -291,7 +294,7 @@ class RequestRepoImp implements RequestRepo {
); );
ProviderOffersModel providerOffersModel = ProviderOffersModel(); ProviderOffersModel providerOffersModel = ProviderOffersModel();
if (genericRespModel.data != null && genericRespModel.data.length > 0) { if (genericRespModel.data != null && genericRespModel.data.length > 0) {
providerOffersModel = ProviderOffersModel.fromJson(genericRespModel.data.first); providerOffersModel = ProviderOffersModel.fromJson(genericRespModel.data.first, requestId);
} }
return providerOffersModel; return providerOffersModel;
} }

@ -11,6 +11,8 @@ abstract class ScheduleRepo {
Future<GenericRespModel> createSchedule(Map map); Future<GenericRespModel> createSchedule(Map map);
Future<GenericRespModel> checkServiceGroupInBranchSchedule(Map map);
Future<GenericRespModel> addServicesInSchedule(Map map); Future<GenericRespModel> addServicesInSchedule(Map map);
Future<GenericRespModel> updateSchedule(Map map); Future<GenericRespModel> updateSchedule(Map map);
@ -36,6 +38,12 @@ class ScheduleRepoImp implements ScheduleRepo {
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.createSchedule, map, token: t); return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.createSchedule, map, token: t);
} }
@override
Future<GenericRespModel> checkServiceGroupInBranchSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.checkGroupServiceInBranchSchedule, map, token: t);
}
@override @override
Future<GenericRespModel> addServicesInSchedule(Map map) async { Future<GenericRespModel> addServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";

@ -61,11 +61,21 @@ class SettingOptionsRepoImp extends SettingOptionsRepo {
@override @override
Future<List<ContactInfoModel>> getAllContactInfos() async { Future<List<ContactInfoModel>> getAllContactInfos() async {
int channel = 0;
if (AppState().currentAppType == AppType.provider) {
channel = 2;
} else {
channel = 3;
}
final params = {"Channel": channel.toString()};
String token = appState.getUser.data!.accessToken ?? ""; String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject( GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.getContactInfo, ApiConsts.getContactInfo,
queryParameters: params,
token: token, token: token,
); );

@ -16,23 +16,15 @@ class AppEnums {
static const int appointmentsFilterEnumId = 13; // Appointments Filter Enums static const int appointmentsFilterEnumId = 13; // Appointments Filter Enums
static const int requestStatusesFilterEnumId = 15; // Appointments Filter Enums static const int requestStatusesFilterEnumId = 15; // Appointments Filter Enums
static const int conditionEnumId = -1; // to get the Condition Filter Enums static const int conditionEnumId = -1; // to get the Condition Filter Enums
static const int shippingStatusEnumId = -2; // to get the Shipping Filter Enums static const int shippingStatusEnumId = 30; // to get the Shipping Filter Enums
} }
enum DashboardRouteEnum { enum DashboardRouteEnum {
fromAdsPayment, fromAdsPayment,
fromAdsSubmit, fromAdsSubmit,
none, none,
} }
enum VehicleType { enum VehicleType {
car, car,
motorCycle, motorCycle,
@ -70,6 +62,7 @@ enum AdPostStatus {
reserved, reserved,
buyingService, buyingService,
reserveCancel, reserveCancel,
deActive,
allAds, allAds,
} }
@ -173,9 +166,11 @@ enum AppointmentStatusEnum {
cancelled, cancelled,
rescheduled, rescheduled,
allAppointments, allAppointments,
upcoming,
workStarted, workStarted,
visitCompleted, visitCompleted,
today,
past,
upcoming,
} }
enum AppointmentPaymentStatusEnum { enum AppointmentPaymentStatusEnum {
@ -228,6 +223,7 @@ enum SubscriptionActionTypeEnum {
enum ShippingRequestStatusEnum { enum ShippingRequestStatusEnum {
allRequests, allRequests,
pending,
initiated, initiated,
inTransit, inTransit,
outForDelivery, outForDelivery,

@ -29,7 +29,14 @@ class Utils {
static bool get isLoading => _isLoadingVisible; static bool get isLoading => _isLoadingVisible;
static void showToast(String message) { 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 { static Future<void> openNumberViaCaller({required String phoneNumber}) async {
@ -84,7 +91,11 @@ class Utils {
return ""; 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) { static dynamic getNotNullValue(List<dynamic> list, int index) {
@ -234,6 +245,9 @@ class Utils {
case AdPostStatus.reserved: case AdPostStatus.reserved:
return MyColors.primaryColor; return MyColors.primaryColor;
case AdPostStatus.deActive:
return MyColors.textColor;
case AdPostStatus.buyingService: case AdPostStatus.buyingService:
case AdPostStatus.reserveCancel: case AdPostStatus.reserveCancel:
case AdPostStatus.allAds: case AdPostStatus.allAds:
@ -313,6 +327,9 @@ class Utils {
case ShippingRequestStatusEnum.delivered: case ShippingRequestStatusEnum.delivered:
return "Delivered"; return "Delivered";
case ShippingRequestStatusEnum.pending:
return "Pending";
} }
} }
@ -332,6 +349,9 @@ class Utils {
case ShippingRequestStatusEnum.delivered: case ShippingRequestStatusEnum.delivered:
return MyColors.greenColor; return MyColors.greenColor;
case ShippingRequestStatusEnum.pending:
return MyColors.pendingColor;
} }
} }
@ -379,7 +399,12 @@ class Utils {
} }
} }
static statusContainerChip({required String text, EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 3, horizontal: 6), Color chipColor = MyColors.greenColor, Color textColor = MyColors.white}) { static statusContainerChip({
required String text,
EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 3, horizontal: 6),
Color chipColor = MyColors.greenColor,
Color textColor = MyColors.white,
}) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: chipColor, color: chipColor,
@ -562,7 +587,8 @@ class Utils {
} }
static String getAdsPaymentBrowserForm({required int paymentId, required int adId}) { 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 // BOTTOM SHEETS

@ -190,11 +190,12 @@ class AdVM extends BaseVM {
} }
myAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0)); myAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0));
log("myAdsFilterOptions: ${myAdsFilterOptions.last.id}");
for (int i = 0; i < exploreAdsEnums.length; i++) { for (int i = 0; i < exploreAdsEnums.length; i++) {
exploreAdsFilterOptions.add(FilterListModel(title: "${exploreAdsEnums[i].enumValueStr} Ads", isSelected: false, id: exploreAdsEnums[i].enumValue)); exploreAdsFilterOptions.add(FilterListModel(title: "${exploreAdsEnums[i].enumValueStr} Ads", isSelected: false, id: exploreAdsEnums[i].enumValue));
} }
exploreAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0)); exploreAdsFilterOptions.insert(0, FilterListModel(title: "All Ads", isSelected: true, id: 0));
notifyListeners(); notifyListeners();
} }
@ -207,8 +208,7 @@ class AdVM extends BaseVM {
} }
exploreAdsFilterOptions[index].isSelected = true; exploreAdsFilterOptions[index].isSelected = true;
if (createdByRoleFilter == CreatedByRoleEnum.allAds) { if (createdByRoleFilter == CreatedByRoleEnum.allAds) {
exploreAdsFilteredList = exploreAds; getExploreAds();
notifyListeners();
return; return;
} }
setState(ViewState.busy); setState(ViewState.busy);
@ -232,12 +232,12 @@ class AdVM extends BaseVM {
myAdsFilterOptions[index].isSelected = true; myAdsFilterOptions[index].isSelected = true;
if (adPostStatusEnum.getIdFromAdPostStatusEnum() == 0) { if (adPostStatusEnum.getIdFromAdPostStatusEnum() == 0) {
myAdsFilteredList = myAds; getMyAds();
notifyListeners();
return; return;
} }
// this means if the filter is reserved ads // this means if the filter is reserved ads
if (adPostStatusEnum == AdPostStatus.reserved) { if (adPostStatusEnum == AdPostStatus.reserved) {
log("reserved: ${myReservedAds.length}");
myAdsFilteredList = myReservedAds; myAdsFilteredList = myReservedAds;
for (var ad in myAdsFilteredList) { for (var ad in myAdsFilteredList) {
ad.isReservedByMe = true; ad.isReservedByMe = true;
@ -591,26 +591,16 @@ class AdVM extends BaseVM {
OfferRequestCommentModel( OfferRequestCommentModel(
index: 0, index: 0,
isSelected: true, isSelected: true,
title: LocaleKeys.changedMind.tr(), title: LocaleKeys.vehicleDealOutsideApp.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 1, index: 1,
isSelected: false, isSelected: false,
title: LocaleKeys.veryHighPrice.tr(), title: LocaleKeys.changedDesireToSell.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 2, index: 2,
isSelected: false, isSelected: false,
title: LocaleKeys.alreadySold.tr(),
),
OfferRequestCommentModel(
index: 3,
isSelected: false,
title: LocaleKeys.customerNotResponding.tr(),
),
OfferRequestCommentModel(
index: 4,
isSelected: false,
title: LocaleKeys.otherVar.tr(), title: LocaleKeys.otherVar.tr(),
), ),
]; ];
@ -626,6 +616,7 @@ class AdVM extends BaseVM {
value.isSelected = false; value.isSelected = false;
} }
selectedDeActivateAdCommentModel = deActivateAdModelList[index]; selectedDeActivateAdCommentModel = deActivateAdModelList[index];
log("selectedDeActivateAdCommentModel: ${selectedDeActivateAdCommentModel.index}");
deActivateAdModelList[index].isSelected = true; deActivateAdModelList[index].isSelected = true;
notifyListeners(); notifyListeners();
} }
@ -684,10 +675,12 @@ class AdVM extends BaseVM {
SelectionModel vehicleSellerTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); SelectionModel vehicleSellerTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleSellerTypeId(SelectionModel id) { void updateSelectionVehicleSellerTypeId(SelectionModel id, {bool needRefresh = true}) {
vehicleSellerTypeId = id; vehicleSellerTypeId = id;
if (needRefresh) {
notifyListeners(); notifyListeners();
} }
}
// SelectionModel vehicleDamagePartId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); // SelectionModel vehicleDamagePartId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
@ -925,12 +918,12 @@ class AdVM extends BaseVM {
vehicleTransmissionId.errorValue = ""; vehicleTransmissionId.errorValue = "";
} }
if (vehicleSellerTypeId.selectedId == -1) { // if (vehicleSellerTypeId.selectedId == -1) {
vehicleSellerTypeId.errorValue = LocaleKeys.vehicle_vehicleSellerType.tr(); // vehicleSellerTypeId.errorValue = LocaleKeys.vehicle_vehicleSellerType.tr();
isValidated = false; // isValidated = false;
} else { // } else {
vehicleSellerTypeId.errorValue = ""; // vehicleSellerTypeId.errorValue = "";
} // }
if (vehicleCountryId.selectedId == -1) { if (vehicleCountryId.selectedId == -1) {
vehicleCountryId.errorValue = LocaleKeys.vehicle_selectAny.tr(); vehicleCountryId.errorValue = LocaleKeys.vehicle_selectAny.tr();
@ -1483,7 +1476,7 @@ class AdVM extends BaseVM {
vehicleConditionID: vehicleConditionId.selectedId, vehicleConditionID: vehicleConditionId.selectedId,
vehicleMileageID: vehicleMileageId.selectedId, vehicleMileageID: vehicleMileageId.selectedId,
vehicleTransmissionID: vehicleTransmissionId.selectedId, vehicleTransmissionID: vehicleTransmissionId.selectedId,
vehicleSellerTypeID: vehicleSellerTypeId.selectedId, vehicleSellerTypeID: vehicleSellerTypeId.selectedId == -1 ? 1 : vehicleSellerTypeId.selectedId,
cityID: vehicleCityId.selectedId, cityID: vehicleCityId.selectedId,
price: int.parse(vehicleDemandAmount), price: int.parse(vehicleDemandAmount),
vehicleVIN: vehicleVin, vehicleVIN: vehicleVin,
@ -1843,7 +1836,8 @@ class AdVM extends BaseVM {
updateSelectionVehicleColorId(SelectionModel(selectedId: previousAdDetails!.vehicle!.color!.id!, selectedOption: previousAdDetails!.vehicle!.color!.label ?? "")); updateSelectionVehicleColorId(SelectionModel(selectedId: previousAdDetails!.vehicle!.color!.id!, selectedOption: previousAdDetails!.vehicle!.color!.label ?? ""));
updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.label ?? "")); updateSelectionVehicleConditionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.condition!.id!, selectedOption: previousAdDetails!.vehicle!.condition!.label ?? ""));
updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? "")); updateSelectionVehicleCategoryId(SelectionModel(selectedId: previousAdDetails!.vehicle!.category!.id!, selectedOption: previousAdDetails!.vehicle!.category!.label ?? ""));
updateSelectionVehicleMileageId(SelectionModel(selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}")); updateSelectionVehicleMileageId(SelectionModel(
selectedId: previousAdDetails!.vehicle!.mileage!.id!, selectedOption: "${previousAdDetails!.vehicle!.mileage!.mileageStart} - ${previousAdDetails!.vehicle!.mileage!.mileageEnd}"));
updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? "")); updateSelectionVehicleTransmissionId(SelectionModel(selectedId: previousAdDetails!.vehicle!.transmission!.id!, selectedOption: previousAdDetails!.vehicle!.transmission!.label ?? ""));
updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? "")); updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: previousAdDetails!.vehicle!.sellertype!.id!, selectedOption: previousAdDetails!.vehicle!.sellertype!.label ?? ""));
int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID); int indexCountry = vehicleCountries.indexWhere((element) => element.id == previousAdDetails!.vehicle!.countryID);

@ -298,9 +298,17 @@ class AppointmentsVM extends BaseVM {
} }
resetAfterBookingAppointment() { resetAfterBookingAppointment() {
// allSelectedItemsInAppointments.clear(); allSelectedItemsInAppointments.clear();
currentServiceSelection = null;
for (var element in servicesInCurrentAppointment) {
if (element.serviceItems != null) {
element.serviceItems!.clear();
element.serviceItems = [];
}
}
servicesInCurrentAppointment.clear(); servicesInCurrentAppointment.clear();
// serviceAppointmentScheduleList.clear(); servicesInCurrentAppointment = [];
log("here servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
} }
List<EnumsModel> myAppointmentsEnum = []; List<EnumsModel> myAppointmentsEnum = [];
@ -315,13 +323,11 @@ class AppointmentsVM extends BaseVM {
} }
appointmentsFilterOptions.insert(0, FilterListModel(title: "All Appointments", isSelected: true, id: 0)); appointmentsFilterOptions.insert(0, FilterListModel(title: "All Appointments", isSelected: true, id: 0));
// TODO: THIS SHOULD REMOVED AND ADDED IN THE ENUMS API
appointmentsFilterOptions.add(FilterListModel(title: "Work In Progress", isSelected: false, id: 7));
appointmentsFilterOptions.add(FilterListModel(title: "Visit Completed", isSelected: false, id: 8));
notifyListeners(); notifyListeners();
} }
applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) {
log("appointmentStatusEnum: ${appointmentStatusEnum}");
// isNeedCustomerFilter IS ONLY FOR THE PROVIDER APP // isNeedCustomerFilter IS ONLY FOR THE PROVIDER APP
if (appointmentsFilterOptions.isEmpty) return; if (appointmentsFilterOptions.isEmpty) return;
for (var value in appointmentsFilterOptions) { for (var value in appointmentsFilterOptions) {
@ -405,7 +411,9 @@ class AppointmentsVM extends BaseVM {
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters(); myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
// myFilteredAppointments = myAppointments; // myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments myUpComingAppointments = myAppointments
.where((element) => (element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) .where((element) =>
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList(); .toList();
setState(ViewState.idle); setState(ViewState.idle);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
@ -433,39 +441,47 @@ class AppointmentsVM extends BaseVM {
myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map); myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map);
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments myUpComingAppointments = myAppointments
.where((element) => (element.appointmentStatusEnum == AppointmentStatusEnum.confirmed || element.appointmentStatusEnum == AppointmentStatusEnum.booked) && (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) .where((element) =>
(element.appointmentStatusEnum == AppointmentStatusEnum.confirmed || element.appointmentStatusEnum == AppointmentStatusEnum.booked) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList(); .toList();
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
setState(ViewState.idle); setState(ViewState.idle);
} }
updateAppointmentStatus({required int appointmentId, required AppointmentStatusEnum appointmentStatusEnum, bool isNeedToRebuild = false}) async { Future<bool> updateAppointmentStatus({required int appointmentId, required AppointmentStatusEnum appointmentStatusEnum, bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentStatus(appointmentId: appointmentId, appointmentStatusEnum: appointmentStatusEnum); GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentStatus(appointmentId: appointmentId, appointmentStatusEnum: appointmentStatusEnum);
if (genericRespModel.messageStatus == 1) { if (genericRespModel.messageStatus == 1) {
Utils.showToast(LocaleKeys.appointmentStatusUpdated.tr()); Utils.showToast(LocaleKeys.appointmentStatusUpdated.tr());
return true;
} else { } else {
Utils.showToast(genericRespModel.message.toString()); Utils.showToast(genericRespModel.message.toString());
return false;
} }
} catch (e) { } catch (e) {
Utils.showToast(e.toString()); Utils.showToast(e.toString());
return false;
} }
} }
updateAppointmentPaymentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async { Future<bool> updateAppointmentPaymentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentPaymentStatus(map); GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentPaymentStatus(map);
if (genericRespModel.messageStatus == 1) { if (genericRespModel.messageStatus == 1) {
Utils.showToast(LocaleKeys.paymentStatusUpdated.tr()); Utils.showToast(LocaleKeys.paymentStatusUpdated.tr());
return true;
} else { } else {
Utils.showToast(genericRespModel.message.toString()); Utils.showToast(genericRespModel.message.toString());
return false;
} }
} catch (e) { } catch (e) {
Utils.showToast(e.toString()); Utils.showToast(e.toString());
return false;
} }
} }
@ -484,7 +500,8 @@ class AppointmentsVM extends BaseVM {
bool inNeedToEnableMergeButton = false; bool inNeedToEnableMergeButton = false;
void updateCheckBoxInMergeRequest(int currentIndex) { void updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected =
!(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []); int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []);
if (count > 1) { if (count > 1) {
@ -540,10 +557,12 @@ class AppointmentsVM extends BaseVM {
void onItemUpdateOrSelected(int index, bool selected, int itemId) { void onItemUpdateOrSelected(int index, bool selected, int itemId) {
int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!); int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
log("index: $index"); // log("currentServiceSelection!.allSelectedItemsInAppointments: ${allSelectedItemsInAppointments.length}");
log("selected: $selected"); // log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
log("itemId: $itemId"); // log("index: $index");
log("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}"); // log("selected: $selected");
// log("itemId: $itemId");
// log("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
serviceItemsFromApi[index].isUpdateOrSelected = selected; serviceItemsFromApi[index].isUpdateOrSelected = selected;
serviceItemsFromApi[index].isHomeSelected = isHomeTapped; serviceItemsFromApi[index].isHomeSelected = isHomeTapped;
@ -554,23 +573,25 @@ class AppointmentsVM extends BaseVM {
selectSubServicesError = ""; selectSubServicesError = "";
currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]); currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]);
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]); allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
for (var element in allSelectedItemsInAppointments) { // for (var element in allSelectedItemsInAppointments) {
if (!ifItemAlreadySelected(element.id!)) { if (!ifItemAlreadySelected(serviceItemsFromApi[index].id!)) {
if (serviceIndex != -1) { if (serviceIndex != -1) {
servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]); servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0"); servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
} servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0");
} }
} }
// }
} else { } else {
log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}"); // log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
selectedSubServicesCounter = selectedSubServicesCounter - 1; selectedSubServicesCounter = selectedSubServicesCounter - 1;
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId); currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}"); // log("currentServiceSelection!.serviceItems: ${currentServiceSelection!.serviceItems!.length}");
allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId); allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId);
if (serviceIndex != -1) { if (serviceIndex != -1) {
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0"); servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId); servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
} }
} }
@ -714,7 +735,9 @@ class AppointmentsVM extends BaseVM {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
(selectedService.isHomeSelected ? "${(selectedService.currentTotalServicePrice) + ((double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms))}" : "${selectedService.currentTotalServicePrice}") (selectedService.isHomeSelected
? "${(selectedService.currentTotalServicePrice) + ((double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms))}"
: "${selectedService.currentTotalServicePrice}")
.toText(fontSize: 29, isBold: true), .toText(fontSize: 29, isBold: true),
2.width, 2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),

@ -19,12 +19,13 @@ import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.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/ad_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart'; import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:signalr_core/signalr_core.dart'; import 'package:signalr_core/signalr_core.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class ChatVM extends ChangeNotifier { class ChatVM extends BaseVM {
final ChatRepo chatRepo; final ChatRepo chatRepo;
final RequestRepo requestRepo; final RequestRepo requestRepo;
final CommonAppServices commonServices; final CommonAppServices commonServices;
@ -75,34 +76,48 @@ class ChatVM extends ChangeNotifier {
} }
} }
List<int> indexesForCancelSpecialCarOffer = [0, 1, 6, 7];
List<int> indexesForCancelSparePartOffer = [2, 7];
List<int> indexesForRejectOffer = [3, 4, 5, 7];
List<OfferRequestCommentModel> offerRejectModelList = [ List<OfferRequestCommentModel> offerRejectModelList = [
OfferRequestCommentModel( OfferRequestCommentModel(
index: 0, index: 0,
isSelected: true, isSelected: true,
title: LocaleKeys.itemNoLongerAvailable.tr(), title: LocaleKeys.dealOutsideApp.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 1, index: 1,
isSelected: false,
title: LocaleKeys.noAgreementCustomer.tr(),
),
OfferRequestCommentModel(
index: 2,
isSelected: false,
title: LocaleKeys.itemNoLongerAvailable.tr(),
),
OfferRequestCommentModel(
index: 3,
isSelected: true, isSelected: true,
title: LocaleKeys.changedMind.tr(), title: LocaleKeys.changedMind.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 2, index: 4,
isSelected: false, isSelected: false,
title: LocaleKeys.veryHighPrice.tr(), title: LocaleKeys.veryHighPrice.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 3, index: 5,
isSelected: false, isSelected: false,
title: LocaleKeys.alreadySold.tr(), title: LocaleKeys.alreadySold.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 4, index: 6,
isSelected: false, isSelected: false,
title: LocaleKeys.customerNotResponding.tr(), title: LocaleKeys.customerNotResponding.tr(),
), ),
OfferRequestCommentModel( OfferRequestCommentModel(
index: 5, index: 7,
isSelected: false, isSelected: false,
title: LocaleKeys.otherVar.tr(), title: LocaleKeys.otherVar.tr(),
), ),
@ -154,7 +169,8 @@ class ChatVM extends ChangeNotifier {
Future<void> onNewMessageReceivedForRequestOffer({required List<ChatMessageModel> messages, bool isMyOwnOffer = false, required RequestsVM requestsVM}) async { Future<void> onNewMessageReceivedForRequestOffer({required List<ChatMessageModel> messages, bool isMyOwnOffer = false, required RequestsVM requestsVM}) async {
if (AppState().currentAppType == AppType.customer) { if (AppState().currentAppType == AppType.customer) {
for (var currentMessage in messages) { for (var currentMessage in messages) {
log("currentMessage: ${currentMessage.reqOffer!.reqOfferImages!.first.imageUrl}"); logger.i(currentMessage);
int providerIndex = serviceProviderOffersList.indexWhere((element) => element.providerUserId == currentMessage.senderUserID); int providerIndex = serviceProviderOffersList.indexWhere((element) => element.providerUserId == currentMessage.senderUserID);
if (providerIndex != -1) { if (providerIndex != -1) {
if (currentMessage.chatMessageTypeEnum == ChatMessageTypeEnum.offer) { if (currentMessage.chatMessageTypeEnum == ChatMessageTypeEnum.offer) {
@ -197,17 +213,17 @@ class ChatVM extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void subscribeToReceiveRequestOfferMessages(BuildContext context) { void _subscribeToReceiveRequestOfferMessages(BuildContext context) {
hubConnection!.on(SignalrConsts.receiveMessageRequestOffer, (List<Object?>? arguments) { hubConnection!.on(SignalrConsts.receiveMessageRequestOffer, (List<Object?>? arguments) {
logger.i(arguments);
if (arguments == null || arguments.isEmpty) return; if (arguments == null || arguments.isEmpty) return;
List<ChatMessageModel> chat = []; List<ChatMessageModel> chat = [];
for (var message in arguments) { for (var message in arguments) {
final chatMessage = ChatMessageModel.fromJson(message as Map<String, dynamic>, isForReqOfferImagesURLs: true); final chatMessage = ChatMessageModel.fromJson(message as Map<String, dynamic>, isForReqOfferImagesURLs: true);
log("chatMessagechatMessage: ${chatMessage.reqOffer!.reqOfferImages!.first.imageUrl}");
chat.add(chatMessage); chat.add(chatMessage);
} }
onNewMessageReceivedForRequestOffer(messages: chat, requestsVM: context.read<RequestsVM>()); onNewMessageReceivedForRequestOffer(messages: chat, requestsVM: context.read<RequestsVM>());
logger.i(arguments);
// Utils.showToast(arguments.toString()); // Utils.showToast(arguments.toString());
}); });
} }
@ -227,22 +243,67 @@ class ChatVM extends ChangeNotifier {
return status; return status;
} }
int _retryCount = 0;
final int _maxRetries = 5; // Maximum number of retries
bool _isReconnecting = false;
Future<void> _reconnectWithBackoff(BuildContext context) async {
if (_retryCount >= _maxRetries) {
logger.e("Maximum retry attempts reached. Stopping reconnection.");
return;
}
final delay = Duration(seconds: 2 * (_retryCount + 1)); // Exponential backoff
logger.i("Retrying connection in ${delay.inSeconds} seconds...");
await Future.delayed(delay);
_retryCount++;
await buildHubConnection(context); // Try reconnecting
}
Future<void> buildHubConnection(BuildContext context) async { Future<void> buildHubConnection(BuildContext context) async {
if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) { if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) {
if (_isReconnecting) {
logger.i("Reconnection already in progress");
return;
}
if (_isReconnecting) {
logger.i("Reconnection already in progress");
return;
}
try { try {
_isReconnecting = true;
hubConnection = await chatRepo.getHubConnection(); hubConnection = await chatRepo.getHubConnection();
await hubConnection!.start(); await hubConnection!.start();
subscribeToReceiveRequestOfferMessages(context);
subscribeToReceiveAdMessages(context); // Reset retry count on successful connection
subscribeToReceiveGeneralMessages(context); _retryCount = 0;
hubConnection!.onclose((exception) { _isReconnecting = false;
// Subscribe to messages
_subscribeToReceiveRequestOfferMessages(context);
_subscribeToReceiveAdMessages(context);
_subscribeToReceiveGeneralMessages(context);
// Configure handlers
hubConnection!.onclose((exception) async {
logger.i("onClose: ${exception.toString()}"); logger.i("onClose: ${exception.toString()}");
buildHubConnection(context); await _reconnectWithBackoff(context);
});
hubConnection!.onreconnecting((exception) {
logger.i("onReconnecting: ${exception?.toString()}");
});
hubConnection!.onreconnected((connectionId) {
logger.i("onReconnected: ${connectionId.toString()}");
}); });
hubConnection!.onreconnecting((exception) => () => logger.i("onReconnecting: ${exception.toString()}"));
hubConnection!.onreconnected((connectionId) => () => logger.i("onReconnected: ${connectionId.toString()}"));
} catch (e) { } catch (e) {
logger.i("Error: ${e.toString()}"); logger.e("Error during hub connection setup: ${e.toString()}");
_isReconnecting = false; // Reset on failure
} }
notifyListeners(); notifyListeners();
@ -251,6 +312,12 @@ class ChatVM extends ChangeNotifier {
} }
} }
Future<void> closeHubConnection() async {
if (hubConnection != null && hubConnection!.state == HubConnectionState.connected) {
hubConnection!.stop();
}
}
Future<bool> onOfferSendForRequest({ Future<bool> onOfferSendForRequest({
required String receiverId, required String receiverId,
required ChatMessageTypeEnum chatMessageType, required ChatMessageTypeEnum chatMessageType,
@ -424,18 +491,24 @@ class ChatVM extends ChangeNotifier {
List<ServiceProvidersOffers> serviceProviderOffersList = []; List<ServiceProvidersOffers> serviceProviderOffersList = [];
Future<void> getOffersFromProvidersByRequest({required int requestId, required BuildContext context}) async { Future<void> getOffersFromProvidersByRequest({required int requestId, bool isNeedLoading = true}) async {
try { try {
Utils.showLoading(context); if (isNeedLoading) {
setState(ViewState.busy);
}
ProviderOffersModel providerOffersModel = await requestRepo.getOffersFromProvidersByRequest(requestId: requestId); ProviderOffersModel providerOffersModel = await requestRepo.getOffersFromProvidersByRequest(requestId: requestId);
Utils.hideLoading(context); if (isNeedLoading) {
setState(ViewState.idle);
}
serviceProviderOffersList.clear(); serviceProviderOffersList.clear();
serviceProviderOffersList = providerOffersModel.serviceProviders ?? []; serviceProviderOffersList = providerOffersModel.serviceProviders ?? [];
notifyListeners(); notifyListeners();
} catch (e) { } catch (e) {
logger.i(e.toString()); logger.i(e.toString());
Utils.showToast(e.toString()); Utils.showToast(e.toString());
Utils.hideLoading(context); if (isNeedLoading) {
setState(ViewState.idle);
}
} }
} }
@ -611,7 +684,7 @@ class ChatVM extends ChangeNotifier {
} }
} }
void subscribeToReceiveAdMessages(BuildContext context) { void _subscribeToReceiveAdMessages(BuildContext context) {
hubConnection!.on(SignalrConsts.receiveMessageAds, (List<Object?>? arguments) { hubConnection!.on(SignalrConsts.receiveMessageAds, (List<Object?>? arguments) {
if (arguments == null || arguments.isEmpty) return; if (arguments == null || arguments.isEmpty) return;
List<ChatMessageModel> chat = []; List<ChatMessageModel> chat = [];
@ -727,7 +800,7 @@ class ChatVM extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void subscribeToReceiveGeneralMessages(BuildContext context) { void _subscribeToReceiveGeneralMessages(BuildContext context) {
hubConnection!.on(SignalrConsts.receiveMessageGeneral, (List<Object?>? arguments) { hubConnection!.on(SignalrConsts.receiveMessageGeneral, (List<Object?>? arguments) {
if (arguments == null || arguments.isEmpty) return; if (arguments == null || arguments.isEmpty) return;
List<ChatMessageModel> chat = []; List<ChatMessageModel> chat = [];

@ -73,7 +73,8 @@ class PaymentVM extends ChangeNotifier {
return; return;
} }
Future<void> verifyPayments({required BuildContext context, required int id, List<int>? appointmentIds, required int paymentTypeId, required Function() onVerified, bool isForAppointment = false}) async { Future<void> verifyPayments(
{required BuildContext context, required int id, List<int>? appointmentIds, required int paymentTypeId, required Function() onVerified, bool isForAppointment = false}) async {
try { try {
Utils.showLoading(context); Utils.showLoading(context);
bool isPaid = await paymentRepo.verifyPayment( bool isPaid = await paymentRepo.verifyPayment(
@ -85,12 +86,13 @@ class PaymentVM extends ChangeNotifier {
Utils.hideLoading(context); Utils.hideLoading(context);
// TODO: VERIFY THIS WITH ZAHOOR // TODO: VERIFY THIS WITH ZAHOOR
// if (!isPaid) { if (!isPaid) {
// Utils.showToast(LocaleKeys.paymentFailed.tr()); // Utils.showToast(LocaleKeys.paymentFailed.tr());
// pop(context); // pop(context);
// return; return;
// } } else {
Utils.showToast(LocaleKeys.paymentSuccessful.tr()); Utils.showToast(LocaleKeys.paymentSuccessful.tr());
}
onVerified(); onVerified();
} catch (e) { } catch (e) {
Utils.showToast(e.toString()); Utils.showToast(e.toString());

@ -86,6 +86,7 @@ class RequestsVM extends BaseVM {
Future<void> getRequests({bool isNeedToRebuild = false}) async { Future<void> getRequests({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest); applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
isOfferSent = false;
setState(ViewState.idle); setState(ViewState.idle);
} }
@ -111,7 +112,7 @@ class RequestsVM extends BaseVM {
requestStatusIdApi = requestStatusId.selectedId; requestStatusIdApi = requestStatusId.selectedId;
} }
// try { try {
myFilteredRequests = await requestRepo.getRequestsBasedOnFilters( myFilteredRequests = await requestRepo.getRequestsBasedOnFilters(
requestTypeId: requestTypeIdApi, requestTypeId: requestTypeIdApi,
cityId: requestCityIdApi, cityId: requestCityIdApi,
@ -124,12 +125,50 @@ class RequestsVM extends BaseVM {
); );
setState(ViewState.idle); setState(ViewState.idle);
return true; return true;
// } catch (e, s) { } catch (e, s) {
// logger.i("e: ${e.toString()}"); logger.i("e: ${e.toString()}");
// Utils.showToast("Need to ask Zahoor Bhai to add params for this API: /api/RequestManagement/Request_ServiceProvider"); setState(ViewState.idle);
// setState(ViewState.idle); return false;
// return false; }
// } }
List<RequestModel> providersAcceptedRequestsList = [];
List<FilterListModel> acceptedRequestsTypeFilterOptions = [];
Future<List<RequestModel>> getProvidersAcceptedRequests() async {
setState(ViewState.busy);
if (acceptedRequestsTypeFilterOptions.isEmpty) {
for (int i = 0; i < myRequestsTypeEnum.length; i++) {
acceptedRequestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue));
}
acceptedRequestsTypeFilterOptions[0].isSelected = true;
}
providersAcceptedRequestsList.clear();
try {
int requestTypeIdApi = acceptedRequestsTypeFilterOptions.firstWhere((element) => element.isSelected).id;
providersAcceptedRequestsList = await requestRepo.getRequestsBasedOnFilters(
requestTypeId: requestTypeIdApi,
reqOfferStatus: RequestOfferStatusEnum.accepted.getIdFromRequestOfferStatusEnum(),
);
setState(ViewState.idle);
return providersAcceptedRequestsList;
} catch (e) {
logger.e(e.toString());
setState(ViewState.idle);
return [];
}
}
applyFilterOnProvidersAcceptedRequests({required RequestsTypeEnum requestsTypeEnum}) async {
if (acceptedRequestsTypeFilterOptions.isEmpty) return;
for (var value in acceptedRequestsTypeFilterOptions) {
value.isSelected = false;
}
acceptedRequestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeEnum() - 1].isSelected = true; // -1 to match with the index
await getProvidersAcceptedRequests();
notifyListeners();
} }
Future<List<RequestModel>> getServiceRequestsForProviders() async { Future<List<RequestModel>> getServiceRequestsForProviders() async {
@ -166,8 +205,9 @@ class RequestsVM extends BaseVM {
for (var value in requestsTypeFilterOptions) { for (var value in requestsTypeFilterOptions) {
value.isSelected = false; value.isSelected = false;
} }
requestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeStatusEnum() - 1].isSelected = true; // -1 to match with the index requestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeEnum() - 1].isSelected = true; // -1 to match with the index
await getRequestsBasedOnFilters(); await getRequestsBasedOnFilters();
isOfferSent = false;
notifyListeners(); notifyListeners();
} }
@ -220,9 +260,10 @@ class RequestsVM extends BaseVM {
requestStatusesEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.requestStatusesFilterEnumId); requestStatusesEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.requestStatusesFilterEnumId);
} }
if (requestsTypeFilterOptions.isEmpty) { if (requestsTypeFilterOptions.isEmpty || acceptedRequestsTypeFilterOptions.isEmpty) {
for (int i = 0; i < myRequestsTypeEnum.length; i++) { for (int i = 0; i < myRequestsTypeEnum.length; i++) {
requestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue)); requestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue));
acceptedRequestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue));
} }
} }
@ -721,7 +762,8 @@ class RequestsVM extends BaseVM {
} }
} catch (e, s) { } catch (e, s) {
Utils.hideLoading(context); Utils.hideLoading(context);
log(s.toString()); log(e.toString());
Utils.showToast(e.toString());
} }
} }
} }
@ -904,6 +946,13 @@ class RequestsVM extends BaseVM {
return requestImages; return requestImages;
} }
bool isOfferSent = false;
updateIsOfferSent(var value) {
isOfferSent = value;
notifyListeners();
}
Future<void> onSendOfferPressed({ Future<void> onSendOfferPressed({
required BuildContext context, required BuildContext context,
required String receiverId, required String receiverId,
@ -946,6 +995,8 @@ class RequestsVM extends BaseVM {
return; return;
} }
updateIsOfferSent(true);
final senderName = AppState().getUser.data!.userInfo!.firstName; final senderName = AppState().getUser.data!.userInfo!.firstName;
final senderId = AppState().getUser.data!.userInfo!.userId; final senderId = AppState().getUser.data!.userInfo!.userId;
resetSendOfferBottomSheet(); resetSendOfferBottomSheet();

@ -304,6 +304,8 @@ class ServiceVM extends BaseVM {
branches = await branchRepo.getBranchAndServices(); branches = await branchRepo.getBranchAndServices();
if (branches!.data == null) { if (branches!.data == null) {
homePageBranches = []; homePageBranches = [];
} else if (branches!.data!.serviceProviderBranch == null) {
homePageBranches = [];
} else { } else {
homePageBranches = branches!.data!.serviceProviderBranch!.where((element) => element.branchStatus == BranchStatusEnum.approvedOrActive).toList(); homePageBranches = branches!.data!.serviceProviderBranch!.where((element) => element.branchStatus == BranchStatusEnum.approvedOrActive).toList();
} }

@ -42,7 +42,7 @@ class ShippingManagementVM extends BaseVM {
} }
Future<void> populateShippingRequestFilterList() async { Future<void> populateShippingRequestFilterList() async {
if (shippingRequestFilterOptions.isNotEmpty && shippingRequestStatusesList.isNotEmpty) return; // if (shippingRequestFilterOptions.isNotEmpty && shippingRequestStatusesList.isNotEmpty) return;
shippingStatusEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.shippingStatusEnumId); shippingStatusEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.shippingStatusEnumId);
shippingRequestFilterOptions.clear(); shippingRequestFilterOptions.clear();
@ -51,8 +51,8 @@ class ShippingManagementVM extends BaseVM {
shippingRequestFilterOptions.add(FilterListModel(title: shippingStatusEnums[i].enumValueStr, isSelected: false, id: shippingStatusEnums[i].enumValue)); shippingRequestFilterOptions.add(FilterListModel(title: shippingStatusEnums[i].enumValueStr, isSelected: false, id: shippingStatusEnums[i].enumValue));
shippingRequestStatusesList.add(FilterListModel(title: shippingStatusEnums[i].enumValueStr, isSelected: false, id: shippingStatusEnums[i].enumValue)); shippingRequestStatusesList.add(FilterListModel(title: shippingStatusEnums[i].enumValueStr, isSelected: false, id: shippingStatusEnums[i].enumValue));
} }
shippingRequestFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(0.toShippingStatusEnum()), isSelected: false, id: 0));
shippingRequestFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(0.toShippingStatusEnum()), isSelected: true, id: 0)); shippingRequestFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(ShippingRequestStatusEnum.allRequests), isSelected: true, id: -1));
notifyListeners(); notifyListeners();
} }
@ -66,7 +66,9 @@ class ShippingManagementVM extends BaseVM {
notifyListeners(); notifyListeners();
return; return;
} }
shippingRequestFilterOptions[shippingRequestStatusEnum.getIdFromShippingStatusEnum()].isSelected = true; // -1 to match with the index log("shippingRequestStatusEnum.getIdFromShippingStatusEnum(): ${shippingRequestStatusEnum.getIdFromShippingStatusEnum()}");
log("shippingRequestFilterOptions: ${shippingRequestFilterOptions[shippingRequestStatusEnum.getIdFromShippingStatusEnum() + 1].title}");
shippingRequestFilterOptions[shippingRequestStatusEnum.getIdFromShippingStatusEnum() + 1].isSelected = true; // +1 to match with the index 0 index has all requests
await getShippingRequestsListByFilters(shippingStatusEnum: shippingRequestStatusEnum); await getShippingRequestsListByFilters(shippingStatusEnum: shippingRequestStatusEnum);
notifyListeners(); notifyListeners();
} }
@ -93,12 +95,12 @@ class ShippingManagementVM extends BaseVM {
} }
Future<bool> onUpdateShippingStatusTapped({required BuildContext context, required ShippingRequestStatusEnum shippingStatusEnum, required int shippingRequestId}) async { Future<bool> onUpdateShippingStatusTapped({required BuildContext context, required ShippingRequestStatusEnum shippingStatusEnum, required int shippingRequestId}) async {
Utils.showLoading(context); Utils.showLoading(context);
try { try {
GenericRespModel? genericRespModel = await shippingRepo.updateShippingRequestStatus(shippingStatusEnum: shippingStatusEnum, shippingRequestId: shippingRequestId); GenericRespModel? genericRespModel = await shippingRepo.updateShippingRequestStatus(shippingStatusEnum: shippingStatusEnum, shippingRequestId: shippingRequestId, comment: requestStatusComments);
Utils.showToast(genericRespModel.message.toString()); Utils.showToast(genericRespModel.message.toString());
Utils.hideLoading(context); Utils.hideLoading(context);
requestStatusComments = "";
return genericRespModel.messageStatus == 1; return genericRespModel.messageStatus == 1;
} catch (e) { } catch (e) {
logger.i(e.toString()); logger.i(e.toString());

@ -36,6 +36,7 @@ import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/shared_prefrence.dart'; import 'package:mc_common_app/utils/shared_prefrence.dart';
import 'package:mc_common_app/utils/utils.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/base_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/service_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/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/views/location_views/map_selection_widget.dart'; import 'package:mc_common_app/views/location_views/map_selection_widget.dart';
@ -435,7 +436,6 @@ class UserVM extends BaseVM {
} }
} else { } else {
Utils.showToast("Please verify your credentials and role type."); Utils.showToast("Please verify your credentials and role type.");
} }
} else { } else {
Utils.showToast(verifiedUser.message ?? ""); Utils.showToast(verifiedUser.message ?? "");
@ -560,7 +560,8 @@ class UserVM extends BaseVM {
return await userRepo.getAllCountries(); return await userRepo.getAllCountries();
} }
Future<void> performBasicOtpRegisterPage(BuildContext context, {required String countryCode, required String phoneNum, required int role, bool isNeedToPassToken = false, VoidCallback? reloadPage}) async { Future<void> performBasicOtpRegisterPage(BuildContext context,
{required String countryCode, required String phoneNum, required int role, bool isNeedToPassToken = false, VoidCallback? reloadPage}) async {
Utils.showLoading(context); Utils.showLoading(context);
BasicOtpRespModel basicOtp = await userRepo.basicOtp(countryCode + phoneNum, roleId: role, isNeedToPassToken: isNeedToPassToken); BasicOtpRespModel basicOtp = await userRepo.basicOtp(countryCode + phoneNum, roleId: role, isNeedToPassToken: isNeedToPassToken);
Utils.hideLoading(context); Utils.hideLoading(context);
@ -676,8 +677,10 @@ class UserVM extends BaseVM {
print(value.body); print(value.body);
print("Logout"); print("Logout");
} }
SharedPrefManager.setPhoneOrEmail(""); SharedPrefManager.setPhoneOrEmail("");
SharedPrefManager.setUserPassword(""); SharedPrefManager.setUserPassword("");
context.read<ChatVM>().closeHubConnection();
if (AppState().getUser.data!.userInfo!.userLocalImage != null) { if (AppState().getUser.data!.userInfo!.userLocalImage != null) {
AppState().getUser.data!.userInfo!.userLocalImage = null; AppState().getUser.data!.userInfo!.userLocalImage = null;
AppState().getUser.data!.userInfo!.userImageUrl = null; AppState().getUser.data!.userInfo!.userImageUrl = null;

@ -17,7 +17,7 @@ import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class AdDuration extends StatelessWidget { class AdDuration extends StatelessWidget {
const AdDuration({Key? key}) : super(key: key); const AdDuration({super.key});
void onAddSpecialServiceButtonTapped(BuildContext context, AdVM adVM) { void onAddSpecialServiceButtonTapped(BuildContext context, AdVM adVM) {
showModalBottomSheet( showModalBottomSheet(

@ -1,11 +1,16 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/ad_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/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/advertisement/components/picked_images_container_widget.dart';
@ -26,7 +31,8 @@ class VehicleDetails extends StatelessWidget {
children: [ children: [
LocaleKeys.vehicleDetail.tr().toText(fontSize: 18, isBold: true), LocaleKeys.vehicleDetail.tr().toText(fontSize: 18, isBold: true),
8.height, 8.height,
Builder(builder: (context) { Builder(
builder: (context) {
List<DropValue> vehicleBrandsDrop = []; List<DropValue> vehicleBrandsDrop = [];
for (var element in adVM.vehicleBrands) { for (var element in adVM.vehicleBrands) {
vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", "")); vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", ""));
@ -38,7 +44,8 @@ class VehicleDetails extends StatelessWidget {
hint: LocaleKeys.vehicleBrand.tr(), hint: LocaleKeys.vehicleBrand.tr(),
errorValue: adVM.vehicleBrandId.errorValue, errorValue: adVM.vehicleBrandId.errorValue,
); );
}), },
),
if (adVM.vehicleBrandId.selectedId != -1) ...[ if (adVM.vehicleBrandId.selectedId != -1) ...[
if (adVM.isFetchingLists) ...[ if (adVM.isFetchingLists) ...[
const Row( const Row(
@ -49,6 +56,32 @@ class VehicleDetails extends StatelessWidget {
).paddingAll(10), ).paddingAll(10),
] else ...[ ] else ...[
8.height, 8.height,
if (AppState().currentAppType == AppType.provider) ...[
Builder(builder: (context) {
List<DropValue> vehicleSellerTypesDrop = [];
for (var element in adVM.vehicleSellerTypes) {
vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", ""));
}
DropValue? model;
if (AppState().userType == UserType.providerDealer) {
model = vehicleSellerTypesDrop.firstWhere((element) => element.id == 2);
} else {
model = vehicleSellerTypesDrop.firstWhere((element) => element.id == 1);
}
adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: model.id, selectedOption: model.value), needRefresh: false);
return DropdownField(
(DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)),
isSelectAble: false,
list: vehicleSellerTypesDrop,
dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null,
hint: LocaleKeys.vehicleSellerType.tr(),
errorValue: adVM.vehicleSellerTypeId.errorValue,
);
}),
8.height,
],
Builder(builder: (context) { Builder(builder: (context) {
List<DropValue> vehicleModelsDrop = []; List<DropValue> vehicleModelsDrop = [];
for (var element in adVM.vehicleModels) { for (var element in adVM.vehicleModels) {
@ -148,20 +181,7 @@ class VehicleDetails extends StatelessWidget {
); );
}), }),
8.height, 8.height,
Builder(builder: (context) {
List<DropValue> vehicleSellerTypesDrop = [];
for (var element in adVM.vehicleSellerTypes) {
vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", ""));
}
return DropdownField(
(DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)),
list: vehicleSellerTypesDrop,
dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null,
hint: LocaleKeys.vehicleSellerType.tr(),
errorValue: adVM.vehicleSellerTypeId.errorValue,
);
}),
8.height,
Builder(builder: (context) { Builder(builder: (context) {
List<DropValue> vehicleCountriesDrop = []; List<DropValue> vehicleCountriesDrop = [];
for (var element in adVM.vehicleCountries) { for (var element in adVM.vehicleCountries) {

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
@ -28,7 +29,7 @@ import 'package:easy_localization/easy_localization.dart';
class AdsDetailView extends StatefulWidget { class AdsDetailView extends StatefulWidget {
final AdDetailsModel adDetails; final AdDetailsModel adDetails;
const AdsDetailView({Key? key, required this.adDetails}) : super(key: key); const AdsDetailView({super.key, required this.adDetails});
@override @override
State<AdsDetailView> createState() => _AdsDetailViewState(); State<AdsDetailView> createState() => _AdsDetailViewState();
@ -130,6 +131,12 @@ class _AdsDetailViewState extends State<AdsDetailView> {
"${widget.adDetails.vehicle!.transmission!.label}".toText(fontSize: 12), "${widget.adDetails.vehicle!.transmission!.label}".toText(fontSize: 12),
], ],
), ),
Row(
children: [
("${LocaleKeys.financeAvailable.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
((widget.adDetails.vehicle!.isFinanceAvailable ?? false) ? LocaleKeys.yes.tr() : LocaleKeys.no.tr()).toText(fontSize: 12),
],
),
8.height, 8.height,
("${LocaleKeys.description.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.description.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
"${widget.adDetails.vehicle!.vehicleDescription}".toText(fontSize: 14), "${widget.adDetails.vehicle!.vehicleDescription}".toText(fontSize: 14),
@ -158,6 +165,43 @@ class _AdsDetailViewState extends State<AdsDetailView> {
).toWhiteContainer(width: double.infinity, allPading: 12); ).toWhiteContainer(width: double.infinity, allPading: 12);
} }
Widget showItem(String title, String value) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"$title: ".toText(color: MyColors.lightTextColor, letterSpacing: -0.48),
3.width,
Flexible(child: value.toText(isBold: true, overflow: TextOverflow.ellipsis)),
],
);
}
Widget buildPersonalInformationCard({required BuildContext context}) {
if (widget.adDetails.adOwnerDetails == null) {
return const SizedBox();
}
if ((widget.adDetails.adOwnerDetails!.name == null || widget.adDetails.adOwnerDetails!.name!.isEmpty) &&
(widget.adDetails.adOwnerDetails!.mobileNo == null || widget.adDetails.adOwnerDetails!.mobileNo!.isEmpty) &&
(widget.adDetails.adOwnerDetails!.email == null || widget.adDetails.adOwnerDetails!.email!.isEmpty)) {
return const SizedBox();
}
String name = widget.adDetails.adOwnerDetails!.name ?? "";
String phone = widget.adDetails.adOwnerDetails!.mobileNo ?? "";
String email = widget.adDetails.adOwnerDetails!.email ?? "";
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(LocaleKeys.ownerInformation.tr()).toText(fontSize: 16),
name.isNotEmpty ? showItem(LocaleKeys.name.tr(), "$name ") : const SizedBox(),
phone.isNotEmpty ? showItem(LocaleKeys.phoneNumber.tr(), "$phone ") : const SizedBox(),
email.isNotEmpty ? showItem(LocaleKeys.emailAddress.tr(), "$email ") : const SizedBox(),
],
).toWhiteContainer(width: double.infinity, allPading: 12);
}
Widget buildBankDetailsIfAvailable() { Widget buildBankDetailsIfAvailable() {
return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) {
if (adVM.adsBankDetailsModel != null) { if (adVM.adsBankDetailsModel != null) {
@ -294,36 +338,35 @@ class _AdsDetailViewState extends State<AdsDetailView> {
} }
Widget buildAdStartEndDates() { Widget buildAdStartEndDates() {
String startDate = "";
String endDate = "";
if (widget.adDetails.startdate != null) {
startDate = "${DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.startdate!))} at ${DateHelper.formatAsTime(DateTime.parse(widget.adDetails.startdate!))}";
}
if (widget.adDetails.enddate != null) {
endDate = "${DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.enddate!))} at ${DateHelper.formatAsTime(DateTime.parse(widget.adDetails.enddate!))}";
}
return Column( return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
children: [ children: [
("${LocaleKeys.startDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.startDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.startdate != null startDate.isNotEmpty ? startDate.toText(fontSize: 10) : const SizedBox(),
? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.startdate!)).toText(
fontSize: 10,
)
: const SizedBox(),
], ],
), ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row( Row(
children: [ children: [
("${LocaleKeys.endDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.endDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.enddate != null ? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.enddate!)).toText(fontSize: 10) : const SizedBox(), endDate.isNotEmpty ? endDate.toText(fontSize: 10) : const SizedBox(),
],
),
], ],
), ),
3.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
(LocaleKeys.extendAd.tr()).toText(fontSize: 12, color: MyColors.darkPrimaryColor, isUnderLine: true).onPress(() async => await onExtendAdPressed()), (LocaleKeys.extendAd.tr()).toText(fontSize: 12, color: MyColors.darkPrimaryColor, isUnderLine: true).onPress(() async => await onExtendAdPressed()),
], ],
) ),
], ],
).paddingOnly(top: 5, bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12); ).paddingOnly(top: 5, bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12);
} }
@ -331,7 +374,10 @@ class _AdsDetailViewState extends State<AdsDetailView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget actionWidget = const SizedBox(); Widget actionWidget = const SizedBox();
if ((widget.adDetails.isMyAd ?? false) && (widget.adDetails.adPostStatus != AdPostStatus.reserved) && (widget.adDetails.adPostStatus != AdPostStatus.active) && (widget.adDetails.adPostStatus != AdPostStatus.pendingForPost)) { if ((widget.adDetails.isMyAd ?? false) &&
(widget.adDetails.adPostStatus != AdPostStatus.reserved) &&
(widget.adDetails.adPostStatus != AdPostStatus.active) &&
(widget.adDetails.adPostStatus != AdPostStatus.pendingForPost)) {
actionWidget = IconButton( actionWidget = IconButton(
icon: const Icon(Icons.delete_outline, color: MyColors.redColor), icon: const Icon(Icons.delete_outline, color: MyColors.redColor),
onPressed: () { onPressed: () {
@ -351,7 +397,6 @@ class _AdsDetailViewState extends State<AdsDetailView> {
actionWidget.toContainer( actionWidget.toContainer(
margin: const EdgeInsets.fromLTRB(0, 8, 21, 8), margin: const EdgeInsets.fromLTRB(0, 8, 21, 8),
paddingAll: 0, paddingAll: 0,
padding: const EdgeInsets.only(right: 21),
borderRadius: 100, borderRadius: 100,
borderColor: MyColors.lightGreyEFColor, borderColor: MyColors.lightGreyEFColor,
isEnabledBorder: true, isEnabledBorder: true,
@ -375,6 +420,10 @@ class _AdsDetailViewState extends State<AdsDetailView> {
if (widget.adDetails.vehicle!.damagereport != null && widget.adDetails.vehicle!.damagereport!.isNotEmpty) ...[ if (widget.adDetails.vehicle!.damagereport != null && widget.adDetails.vehicle!.damagereport!.isNotEmpty) ...[
buildDamagePartDetails(), buildDamagePartDetails(),
], ],
if (!(widget.adDetails.isMyAd ?? false)) ...[
12.height,
buildPersonalInformationCard(context: context),
],
if (widget.adDetails.isMyAd ?? false) ...[ if (widget.adDetails.isMyAd ?? false) ...[
12.height, 12.height,
buildAdStartEndDates(), buildAdStartEndDates(),

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
@ -32,7 +33,7 @@ import 'package:easy_localization/easy_localization.dart';
class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
final AdDetailsModel adDetailsModel; final AdDetailsModel adDetailsModel;
const BuildAdDetailsActionButtonForExploreAds({Key? key, required this.adDetailsModel}) : super(key: key); const BuildAdDetailsActionButtonForExploreAds({super.key, required this.adDetailsModel});
void reserveAdPriceBreakDownClicked(BuildContext context, AdDetailsModel adDetailsModel) { void reserveAdPriceBreakDownClicked(BuildContext context, AdDetailsModel adDetailsModel) {
showModalBottomSheet( showModalBottomSheet(
@ -238,7 +239,13 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
), ),
if (adDetailsModel.whatsAppNo != null && adDetailsModel.whatsAppNo!.isNotEmpty) ...[ if (adDetailsModel.whatsAppNo != null && adDetailsModel.whatsAppNo!.isNotEmpty) ...[
8.width, 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(() { 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 ?? ""); Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? "");
}), }),
], ],
@ -264,12 +271,12 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget {
class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
final AdDetailsModel adDetailsModel; final AdDetailsModel adDetailsModel;
const BuildAdDetailsActionButtonForMyAds({Key? key, required this.adDetailsModel}) : super(key: key); const BuildAdDetailsActionButtonForMyAds({super.key, required this.adDetailsModel});
void onBookPhotographyServiceClicked(BuildContext context, {required AdDetailsModel adDetailsModel}) async { void onBookPhotographyServiceClicked(BuildContext context, {required AdDetailsModel adDetailsModel}) async {
AdVM adVM = context.read<AdVM>(); AdVM adVM = context.read<AdVM>();
if (adVM.photoOfficeSelectedId.selectedId == -1) { if (adVM.photoOfficeSelectedId.selectedId == -1) {
adVM.getPhotographyServiceScheduleListByOffices(latitude: 46.703430, longitude: 24.625720, isNeedToRebuild: true); // TODO: These Lat Long need to be dynamic adVM.getPhotographyServiceScheduleListByOffices(latitude: AppState().currentLocation.latitude, longitude: AppState().currentLocation.longitude, isNeedToRebuild: true);
} }
return showModalBottomSheet( return showModalBottomSheet(
@ -582,7 +589,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
return actionConfirmationBottomSheet( return actionConfirmationBottomSheet(
context: context, context: context,
title: LocaleKeys.markAsSold.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), title: LocaleKeys.markAsSold.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.markAsSold.tr(), subtitle: LocaleKeys.markAdAsSoldDesc.tr(),
actionButtonYes: Expanded( actionButtonYes: Expanded(
child: ShowFillButton( child: ShowFillButton(
maxHeight: 55, maxHeight: 55,
@ -655,15 +662,9 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
shrinkWrap: true, shrinkWrap: true,
itemCount: adVM.deActivateAdModelList.length, itemCount: adVM.deActivateAdModelList.length,
separatorBuilder: (BuildContext context, int index) { separatorBuilder: (BuildContext context, int index) {
if (adVM.deActivateAdModelList[index].index == 3) {
return const SizedBox();
}
return const Divider(thickness: 0.5); return const Divider(thickness: 0.5);
}, },
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
if (adVM.deActivateAdModelList[index].index == 3) {
return const SizedBox();
}
OfferRequestCommentModel offerRequestCommentModel = adVM.deActivateAdModelList[index]; OfferRequestCommentModel offerRequestCommentModel = adVM.deActivateAdModelList[index];
return CircleCheckBoxWithTitle( return CircleCheckBoxWithTitle(
isChecked: offerRequestCommentModel.isSelected ?? false, isChecked: offerRequestCommentModel.isSelected ?? false,
@ -948,7 +949,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
child: ShowFillButton( child: ShowFillButton(
fontSize: 16, fontSize: 16,
maxHeight: 55, maxHeight: 55,
title: LocaleKeys.extendAd.tr(), title: LocaleKeys.reactivateAd.tr(),
onPressed: () { onPressed: () {
final AdVM adVM = context.read<AdVM>(); final AdVM adVM = context.read<AdVM>();
return actionConfirmationBottomSheet( return actionConfirmationBottomSheet(
@ -1054,6 +1055,9 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
case AdPostStatus.sold: case AdPostStatus.sold:
return pendingForReviewAction(pendingText: LocaleKeys.sold.tr()); return pendingForReviewAction(pendingText: LocaleKeys.sold.tr());
case AdPostStatus.deActive:
return pendingForReviewAction(pendingText: LocaleKeys.deactivateAd.tr());
case AdPostStatus.expired: case AdPostStatus.expired:
return expiredAdAction(context); return expiredAdAction(context);
case AdPostStatus.allAds: case AdPostStatus.allAds:

@ -17,7 +17,7 @@ import 'package:sizer/sizer.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class BottomSheetAdDamagePartsContent extends StatefulWidget { class BottomSheetAdDamagePartsContent extends StatefulWidget {
const BottomSheetAdDamagePartsContent({Key? key}) : super(key: key); const BottomSheetAdDamagePartsContent({super.key});
@override @override
State<BottomSheetAdDamagePartsContent> createState() => _BottomSheetAdDamagePartsContentState(); State<BottomSheetAdDamagePartsContent> createState() => _BottomSheetAdDamagePartsContentState();
@ -147,7 +147,7 @@ class _BottomSheetAdDamagePartsContentState extends State<BottomSheetAdDamagePar
} }
class BottomSheetAdSpecialServiceContent extends StatelessWidget { class BottomSheetAdSpecialServiceContent extends StatelessWidget {
const BottomSheetAdSpecialServiceContent({Key? key}) : super(key: key); const BottomSheetAdSpecialServiceContent({super.key});
bool isButtonTappable(AdVM adVM) { bool isButtonTappable(AdVM adVM) {
bool status = (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) && (adVM.selectedVehicleAdsSpecialServicesId.selectedOption != ""); bool status = (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) && (adVM.selectedVehicleAdsSpecialServicesId.selectedOption != "");

@ -1,8 +1,13 @@
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/string_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/advertisment_models/ad_details_model.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/theme/colors.dart'; import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:sizer/sizer.dart'; import 'package:sizer/sizer.dart';
@ -17,7 +22,7 @@ class ImagesCorouselWidget extends StatefulWidget {
class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> { class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> {
int _current = 0; int _current = 0;
CarouselSliderController _controller = CarouselSliderController(); final CarouselSliderController _controller = CarouselSliderController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -28,7 +33,7 @@ class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
"No Images to Show".toText( LocaleKeys.noImagesToShow.tr().toText(
fontSize: 12, fontSize: 12,
color: MyColors.lightTextColor, color: MyColors.lightTextColor,
isBold: true, isBold: true,
@ -40,17 +45,30 @@ class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> {
} }
return SizedBox( return SizedBox(
height: 26.h, height: 26.h,
child: ListView(shrinkWrap: true, children: [ child: ListView(
shrinkWrap: true,
children: [
CarouselSlider( CarouselSlider(
items: widget.imagesList items: widget.imagesList
.map((item) => .map(
Container( (item) => Container(
margin: const EdgeInsets.all(5.0), margin: const EdgeInsets.all(5.0),
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(5.0)), borderRadius: const BorderRadius.all(Radius.circular(5.0)),
child: item.imageUrl.buildNetworkImage(), child: item.imageUrl.buildNetworkImage(),
), ),
)) ).onPress(() {
List<MessageImageModel> images = [];
for (var image in widget.imagesList) {
images.add(MessageImageModel(
id: image.id,
isFromNetwork: true,
imageUrl: image.imageUrl,
));
}
navigateWithName(context, AppRoutes.mediaViewerScreen, arguments: images);
}),
)
.toList(), .toList(),
carouselController: _controller, carouselController: _controller,
options: CarouselOptions( options: CarouselOptions(
@ -61,14 +79,12 @@ class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> {
setState(() { setState(() {
_current = index; _current = index;
}); });
}), },
),
), ),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: widget.imagesList children: widget.imagesList.asMap().entries.map((entry) {
.asMap()
.entries
.map((entry) {
return GestureDetector( return GestureDetector(
onTap: () => _controller.animateToPage(entry.key), onTap: () => _controller.animateToPage(entry.key),
child: Container( child: Container(
@ -83,7 +99,8 @@ class _CarouselWithIndicatorState extends State<ImagesCorouselWidget> {
); );
}).toList(), }).toList(),
), ),
]), ],
),
); );
} }
} }

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
@ -56,7 +58,7 @@ class BookAppointmentSchedulesView extends StatelessWidget {
Row( Row(
children: [ children: [
Expanded( Expanded(
child: ("${LocaleKeys.schedule.tr()} ${scheduleIndex + 1}").toText(fontSize: 20, isBold: true), child: (scheduleData.scheduleName ?? "").toText(fontSize: 20, isBold: true),
), ),
], ],
), ),
@ -65,7 +67,9 @@ class BookAppointmentSchedulesView extends StatelessWidget {
children: [ children: [
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), (LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
2.width, 2.width,
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.customerLocation.tr() : LocaleKeys.companyLocation.tr()).toText(fontSize: 12, isBold: true).expand(), (scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.customerLocation.tr() : LocaleKeys.companyLocation.tr())
.toText(fontSize: 12, isBold: true)
.expand(),
], ],
), ),
Column( Column(
@ -112,7 +116,9 @@ class BookAppointmentSchedulesView extends StatelessWidget {
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
child: BuildTimeSlots( child: BuildTimeSlots(
timeSlots: appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!].availableSlots ?? [], timeSlots: appointmentsVM.serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!].availableSlots ??
[],
onPressed: (slotIndex) { onPressed: (slotIndex) {
appointmentsVM.updateSelectedAppointmentSlotByDate(scheduleIndex: scheduleIndex, slotIndex: slotIndex); appointmentsVM.updateSelectedAppointmentSlotByDate(scheduleIndex: scheduleIndex, slotIndex: slotIndex);
}, },

@ -1,4 +1,7 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
@ -14,7 +17,7 @@ import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class BookAppointmentServicesView extends StatelessWidget { class BookAppointmentServicesView extends StatelessWidget {
const BookAppointmentServicesView({Key? key}) : super(key: key); const BookAppointmentServicesView({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -57,7 +60,7 @@ class BookAppointmentServicesView extends StatelessWidget {
Row( Row(
children: [ children: [
Expanded(child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true)), Expanded(child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true)),
IconButton(onPressed: () => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex), icon: const Icon(Icons.delete_outline, color: MyColors.redColor)) MyAssets.closeWithOrangeBg.buildSvg(height: 30, width: 30).onPress(() => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex))
], ],
), ),
if (true) ...[ if (true) ...[
@ -105,8 +108,7 @@ class BookAppointmentServicesView extends StatelessWidget {
maxHeight: 55, maxHeight: 55,
title: LocaleKeys.cancel.tr(), title: LocaleKeys.cancel.tr(),
onPressed: () { onPressed: () {
appointmentsVM.servicesInCurrentAppointment.clear(); appointmentsVM.resetAfterBookingAppointment();
appointmentsVM.allSelectedItemsInAppointments.clear();
Navigator.pop(context); Navigator.pop(context);
}, },
backgroundColor: MyColors.greyButtonColor, backgroundColor: MyColors.greyButtonColor,

@ -18,7 +18,7 @@ import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class BookAppointmentsItemView extends StatelessWidget { class BookAppointmentsItemView extends StatelessWidget {
const BookAppointmentsItemView({Key? key}) : super(key: key); const BookAppointmentsItemView({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

@ -287,7 +287,7 @@ class ReviewAppointment extends StatelessWidget {
]), ]),
Row(children: [ Row(children: [
("${LocaleKeys.location.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor), ("${LocaleKeys.location.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(fontSize: 12), (scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.homeLocation.tr() : LocaleKeys.companyLocation.tr()).toText(fontSize: 12),
]), ]),
], ],
), ),

@ -167,6 +167,7 @@ class _ChatViewState extends State<ChatView> {
chatMessageModel: chatMessageModel, chatMessageModel: chatMessageModel,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus, requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum, chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
); );
}, },
).horPaddingMain(), ).horPaddingMain(),
@ -176,7 +177,7 @@ class _ChatViewState extends State<ChatView> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
if (chatTypeEnum == ChatTypeEnum.requestOffer && if (chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestType.toRequestTypeStatusEnum() == RequestsTypeEnum.serviceRequest && requestVM.currentSelectedRequest!.requestType.toRequestTypeEnum() == RequestsTypeEnum.serviceRequest &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress && requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress &&
AppState().currentAppType == AppType.customer) ...[ AppState().currentAppType == AppType.customer) ...[
Expanded( Expanded(
@ -200,7 +201,7 @@ class _ChatViewState extends State<ChatView> {
// ), // ),
// ).paddingAll(15) // ).paddingAll(15)
] else if (chatTypeEnum == ChatTypeEnum.requestOffer && ] else if (chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestType.toRequestTypeStatusEnum() == RequestsTypeEnum.specialCarRequest && requestVM.currentSelectedRequest!.requestType.toRequestTypeEnum() == RequestsTypeEnum.specialCarRequest &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress && requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress &&
requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted && requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted &&
AppState().currentAppType == AppType.customer) ...[ AppState().currentAppType == AppType.customer) ...[

@ -28,8 +28,9 @@ class ChatMessageCustomWidget extends StatefulWidget {
final ChatMessageModel chatMessageModel; final ChatMessageModel chatMessageModel;
final RequestStatusEnum? requestStatusEnum; final RequestStatusEnum? requestStatusEnum;
final ChatTypeEnum chatTypeEnum; final ChatTypeEnum chatTypeEnum;
final RequestsTypeEnum requestsTypeEnum;
const ChatMessageCustomWidget({super.key, required this.chatMessageModel, required this.requestStatusEnum, required this.chatTypeEnum}); const ChatMessageCustomWidget({super.key, required this.chatMessageModel, required this.requestStatusEnum, required this.chatTypeEnum, this.requestsTypeEnum = RequestsTypeEnum.specialCarRequest});
@override @override
State<ChatMessageCustomWidget> createState() => _ChatMessageCustomWidgetState(); State<ChatMessageCustomWidget> createState() => _ChatMessageCustomWidgetState();
@ -43,8 +44,14 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
enableDrag: true, enableDrag: true,
builder: (BuildContext context) { builder: (BuildContext context) {
return Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) { return Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) {
String title = "";
if (requestOfferStatusEnum == RequestOfferStatusEnum.cancel) {
title = LocaleKeys.dealNotCompleted.tr();
} else {
title = LocaleKeys.pleaseSpecify.tr();
}
return InfoBottomSheet( return InfoBottomSheet(
title: LocaleKeys.pleaseSpecify.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), title: title.toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding( description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column( child: Column(
@ -58,26 +65,30 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
shrinkWrap: true, shrinkWrap: true,
itemCount: chatVM.offerRejectModelList.length, itemCount: chatVM.offerRejectModelList.length,
separatorBuilder: (BuildContext context, int index) { separatorBuilder: (BuildContext context, int index) {
if ((chatVM.offerRejectModelList[index].index == 1 || chatVM.offerRejectModelList[index].index == 2 || chatVM.offerRejectModelList[index].index == 3) && requestOfferStatusEnum == RequestOfferStatusEnum.cancel) { bool indexContainsInCancel = widget.requestsTypeEnum == RequestsTypeEnum.specialCarRequest
? (chatVM.indexesForCancelSpecialCarOffer.indexWhere((i) => i == index) != -1)
: (chatVM.indexesForCancelSparePartOffer.indexWhere((i) => i == index) != -1);
bool indexContainsInReject = chatVM.indexesForRejectOffer.indexWhere((i) => i == index) != -1;
if ((!indexContainsInCancel) && requestOfferStatusEnum == RequestOfferStatusEnum.cancel) {
return const SizedBox(); return const SizedBox();
} }
// 0 -> itemNoLongerAvailable if ((!indexContainsInReject) && requestOfferStatusEnum == RequestOfferStatusEnum.rejected) {
// 1 -> customerNotResponding
if ((chatVM.offerRejectModelList[index].index == 4 || chatVM.offerRejectModelList[index].index == 0) && requestOfferStatusEnum == RequestOfferStatusEnum.rejected) {
return const SizedBox(); return const SizedBox();
} }
return const Divider(thickness: 0.5); return const Divider(thickness: 0.5);
}, },
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
if ((chatVM.offerRejectModelList[index].index == 1 || chatVM.offerRejectModelList[index].index == 2 || chatVM.offerRejectModelList[index].index == 3) && requestOfferStatusEnum == RequestOfferStatusEnum.cancel) { bool indexContainsInCancel = widget.requestsTypeEnum == RequestsTypeEnum.specialCarRequest
? (chatVM.indexesForCancelSpecialCarOffer.indexWhere((i) => i == index) != -1)
: (chatVM.indexesForCancelSparePartOffer.indexWhere((i) => i == index) != -1);
bool indexContainsInReject = chatVM.indexesForRejectOffer.indexWhere((i) => i == index) != -1;
if ((!indexContainsInCancel) && requestOfferStatusEnum == RequestOfferStatusEnum.cancel) {
return const SizedBox(); return const SizedBox();
} }
// 0 -> itemNoLongerAvailable
// 1 -> customerNotResponding if ((!indexContainsInReject) && requestOfferStatusEnum == RequestOfferStatusEnum.rejected) {
// 2 -> veryHighPrice
// 3 -> alreadySold
if ((chatVM.offerRejectModelList[index].index == 4 || chatVM.offerRejectModelList[index].index == 0) && requestOfferStatusEnum == RequestOfferStatusEnum.rejected) {
return const SizedBox(); return const SizedBox();
} }
OfferRequestCommentModel offerRequestCommentModel = chatVM.offerRejectModelList[index]; OfferRequestCommentModel offerRequestCommentModel = chatVM.offerRejectModelList[index];
@ -136,7 +147,13 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
); );
if (status) { if (status) {
final requestVM = context.read<RequestsVM>();
chatMessageModel.reqOffer!.requestOfferStatusEnum = requestOfferStatusEnum; chatMessageModel.reqOffer!.requestOfferStatusEnum = requestOfferStatusEnum;
int index = chatVM.serviceProviderOffersList.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
if (index != -1) {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
}
setState(() {}); setState(() {});
// Navigator.pop(context); // Navigator.pop(context);
chatVM.updateRejectOfferDescription(''); chatVM.updateRejectOfferDescription('');
@ -184,11 +201,17 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
if (status) { if (status) {
final requestVM = context.read<RequestsVM>(); final requestVM = context.read<RequestsVM>();
ChatVM chatVM = context.read<ChatVM>();
chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted; chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted;
requestVM.currentSelectedRequest!.requestStatus = RequestStatusEnum.inProgress; requestVM.currentSelectedRequest!.requestStatus = RequestStatusEnum.inProgress;
requestVM.updateAcceptedReqOffer(chatMessageModel.reqOffer!); requestVM.updateAcceptedReqOffer(chatMessageModel.reqOffer!);
requestVM.updateAcceptedRequestOfferProviderName(chatMessageModel.senderName ?? ""); requestVM.updateAcceptedRequestOfferProviderName(chatMessageModel.senderName ?? "");
int index = chatVM.serviceProviderOffersList.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
if (index != -1) {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
}
setState(() {}); setState(() {});
// Navigator.pop(context); // Navigator.pop(context);
Utils.showToast("Offer Accepted"); Utils.showToast("Offer Accepted");
@ -447,7 +470,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Widget buildFreeTextDetailsInMessage({required ChatMessageTypeEnum chatMessageTypeEnum}) { Widget buildFreeTextDetailsInMessage({required ChatMessageTypeEnum chatMessageTypeEnum}) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true) && widget.chatMessageModel.isRead == true) ...[ if (chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true) && widget.chatMessageModel.isRead == true) ...[
Row( Row(
@ -460,7 +483,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
], ],
Expanded( Expanded(
child: Directionality( child: Directionality(
textDirection: TextDirection.ltr, textDirection: (widget.chatMessageModel.isMyMessage ?? false) ? TextDirection.ltr : TextDirection.rtl,
child: (widget.chatMessageModel.chatText ?? "").toText( child: (widget.chatMessageModel.chatText ?? "").toText(
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor, color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontSize: 12, fontSize: 12,
@ -588,11 +611,24 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
messageTypeWidget = Column( messageTypeWidget = Column(
children: [ children: [
buildFreeTextDetailsInMessage(chatMessageTypeEnum: chatMessageTypeEnum), buildFreeTextDetailsInMessage(chatMessageTypeEnum: chatMessageTypeEnum),
if (widget.requestsTypeEnum == RequestsTypeEnum.serviceRequest) ...[
2.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${LocaleKeys.deliveryAvailable.tr()} : ${(widget.chatMessageModel.reqOffer!.isDeliveryAvailable ?? false) ? LocaleKeys.yes.tr() : LocaleKeys.no.tr()}".toText(
fontSize: 10,
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontWeight: MyFonts.Medium,
),
],
),
],
if (widget.chatMessageModel.reqOffer!.reqOfferImages != null && widget.chatMessageModel.reqOffer!.reqOfferImages!.isNotEmpty) ...[ if (widget.chatMessageModel.reqOffer!.reqOfferImages != null && widget.chatMessageModel.reqOffer!.reqOfferImages!.isNotEmpty) ...[
5.height, 5.height,
buildImagesInOffer(widget.chatMessageModel.reqOffer!.reqOfferImages!, widget.chatMessageModel.isMyMessage ?? false), buildImagesInOffer(widget.chatMessageModel.reqOffer!.reqOfferImages!, widget.chatMessageModel.isMyMessage ?? false),
], ],
10.height, 4.height,
buildOfferDetailsInChatMessage(requestStatusEnum: widget.requestStatusEnum!, chatMessageModel: widget.chatMessageModel, context: context), buildOfferDetailsInChatMessage(requestStatusEnum: widget.requestStatusEnum!, chatMessageModel: widget.chatMessageModel, context: context),
], ],
); );

@ -104,7 +104,7 @@ class MyRequestsFragment extends StatelessWidget {
FiltersList( FiltersList(
filterList: requestsVM.requestsTypeFilterOptions, filterList: requestsVM.requestsTypeFilterOptions,
onFilterTapped: (index, selectedFilterId) { onFilterTapped: (index, selectedFilterId) {
requestsVM.applyFilterOnRequestsVM(requestsTypeEnum: selectedFilterId.toRequestTypeStatusEnum()); requestsVM.applyFilterOnRequestsVM(requestsTypeEnum: selectedFilterId.toRequestTypeEnum());
}, },
), ),
8.height, 8.height,

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/app_state.dart';
@ -32,7 +34,13 @@ class CreateRequestPage extends StatelessWidget {
pop(context); pop(context);
}, },
), ),
body: Consumer<RequestsVM>(builder: (context, requestsVM, widget) { body: PopScope(
onPopInvokedWithResult: (bool result, dynamic) {
if (result) {
context.read<RequestsVM>().resetRequestCreationForm();
}
},
child: Consumer<RequestsVM>(builder: (context, requestsVM, widget) {
return Column( return Column(
children: [ children: [
Expanded( Expanded(
@ -137,7 +145,8 @@ class CreateRequestPage extends StatelessWidget {
return DropdownField( return DropdownField(
(DropValue value) => requestsVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)), (DropValue value) => requestsVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)),
list: vehicleOwnerDrop, 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(), hint: LocaleKeys.condition.tr(),
errorValue: requestsVM.vehicleConditionId.errorValue, errorValue: requestsVM.vehicleConditionId.errorValue,
); );
@ -152,7 +161,8 @@ class CreateRequestPage extends StatelessWidget {
return DropdownField( return DropdownField(
(DropValue value) => requestsVM.updateSelectionVehicleCountryId(SelectionModel(selectedOption: value.value, selectedId: value.id)), (DropValue value) => requestsVM.updateSelectionVehicleCountryId(SelectionModel(selectedOption: value.value, selectedId: value.id)),
list: vehicleCountriesDrop, list: vehicleCountriesDrop,
dropdownValue: requestsVM.vehicleCountryId.selectedId != -1 ? DropValue(requestsVM.vehicleCountryId.selectedId, requestsVM.vehicleCountryId.selectedOption, "") : null, dropdownValue:
requestsVM.vehicleCountryId.selectedId != -1 ? DropValue(requestsVM.vehicleCountryId.selectedId, requestsVM.vehicleCountryId.selectedOption, "") : null,
hint: LocaleKeys.country.tr(), hint: LocaleKeys.country.tr(),
errorValue: requestsVM.vehicleCountryId.errorValue, errorValue: requestsVM.vehicleCountryId.errorValue,
); );
@ -269,6 +279,7 @@ class CreateRequestPage extends StatelessWidget {
], ],
); );
}), }),
),
); );
} }
} }

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -18,23 +19,52 @@ import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
class OfferListPage extends StatelessWidget { class OfferListPage extends StatefulWidget {
final OfferListPageArguments offerListPageArguments; final int requestId;
const OfferListPage({super.key, required this.offerListPageArguments}); const OfferListPage({super.key, required this.requestId});
@override
State<OfferListPage> createState() => _OfferListPageState();
}
class _OfferListPageState extends State<OfferListPage> {
@override
void initState() {
_onRefresh();
super.initState();
}
_onRefresh() async {
scheduleMicrotask(() async {
ChatVM chatVM = context.read<ChatVM>();
await chatVM.getOffersFromProvidersByRequest(requestId: widget.requestId);
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<ServiceProvidersOffers> serviceProviderOffers = offerListPageArguments.serviceProviderOffers; return Consumer<ChatVM>(builder: (context, ChatVM chatVM, Widget? child) {
return Scaffold( return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.offers.tr()), appBar: CustomAppBar(title: LocaleKeys.offers.tr()),
body: serviceProviderOffers.isEmpty body: RefreshIndicator(
? Center(child: LocaleKeys.noOffersShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor)) onRefresh: () async {
_onRefresh();
},
child: chatVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
: chatVM.serviceProviderOffersList.isEmpty
? Center(
child: LocaleKeys.noOffersShow.tr().toText(
fontSize: 16,
color: MyColors.lightTextColor,
),
)
: ListView.separated( : ListView.separated(
itemCount: serviceProviderOffers.length, itemCount: chatVM.serviceProviderOffersList.length,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
itemBuilder: (context, index) { itemBuilder: (context, index) {
ServiceProvidersOffers offersModel = serviceProviderOffers[index]; ServiceProvidersOffers offersModel = chatVM.serviceProviderOffersList[index];
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -46,7 +76,10 @@ class OfferListPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(offersModel.name ?? "").toText(fontSize: 16, isBold: true), (offersModel.name ?? "").toText(
fontSize: 16,
isBold: true,
),
Center( Center(
child: "${offersModel.offerCount}".toText( child: "${offersModel.offerCount}".toText(
color: Colors.white, color: Colors.white,
@ -73,10 +106,6 @@ class OfferListPage extends StatelessWidget {
if (offersModel.createdOn != null && offersModel.createdOn!.isNotEmpty) ...[ if (offersModel.createdOn != null && offersModel.createdOn!.isNotEmpty) ...[
" | ${DateTime.parse(offersModel.createdOn!).getTimeAgo()}".toText(color: MyColors.lightTextColor, fontSize: 14), " | ${DateTime.parse(offersModel.createdOn!).getTimeAgo()}".toText(color: MyColors.lightTextColor, fontSize: 14),
], ],
// " | 1 hour ago".toText(
// color: MyColors.lightTextColor,
// fontSize: 12,
// ),
], ],
), ),
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18), const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
@ -90,9 +119,10 @@ class OfferListPage extends StatelessWidget {
chatTypeEnum: ChatTypeEnum.requestOffer, chatTypeEnum: ChatTypeEnum.requestOffer,
receiverId: "${offersModel.providerUserId}", receiverId: "${offersModel.providerUserId}",
senderId: AppState().getUser.data!.userInfo!.userId.toString(), senderId: AppState().getUser.data!.userInfo!.userId.toString(),
requestId: offerListPageArguments.requestId, requestId: widget.requestId,
providerIndex: index, providerIndex: index,
requestIndex: -1, // This will be only send in case of provider requestModel: context.read<RequestsVM>().currentSelectedRequest,
requestIndex: -1,
); );
ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest); ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest);
@ -104,7 +134,7 @@ class OfferListPage extends StatelessWidget {
context: context, context: context,
providerId: offersModel.providerId ?? 0, providerId: offersModel.providerId ?? 0,
requestOfferId: 0, requestOfferId: 0,
requestId: offerListPageArguments.requestId ?? 0, requestId: widget.requestId,
providerOfferIndex: index, providerOfferIndex: index,
) )
.whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments)); .whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments));
@ -112,6 +142,8 @@ class OfferListPage extends StatelessWidget {
}, },
separatorBuilder: (context, index) => 16.height, separatorBuilder: (context, index) => 16.height,
), ),
),
); );
});
} }
} }

@ -48,7 +48,7 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
numbersOnly: true, numbersOnly: true,
onChanged: (v) => requestsVM.updateOfferPrice(v), onChanged: (v) => requestsVM.updateOfferPrice(v),
), ),
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeStatusEnum()) ...[ if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) ...[
12.height, 12.height,
TxtField( TxtField(
value: requestsVM.serviceItem, value: requestsVM.serviceItem,
@ -87,7 +87,7 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
onChanged: (v) => requestsVM.updateOfferDescription(v), onChanged: (v) => requestsVM.updateOfferDescription(v),
), ),
12.height, 12.height,
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeStatusEnum()) ...[ if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) ...[
LocaleKeys.deliveryAvailable.tr().toText(fontSize: 16), LocaleKeys.deliveryAvailable.tr().toText(fontSize: 16),
8.height, 8.height,
Container( Container(

@ -9,6 +9,7 @@ import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.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/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/components/ads_images_corousel_widget.dart'; import 'package:mc_common_app/views/advertisement/components/ads_images_corousel_widget.dart';
import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart'; import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart';
import 'package:mc_common_app/views/requests/request_bottomsheets.dart'; import 'package:mc_common_app/views/requests/request_bottomsheets.dart';
@ -21,9 +22,10 @@ import 'package:easy_localization/easy_localization.dart';
class RequestDetailPage extends StatelessWidget { class RequestDetailPage extends StatelessWidget {
final RequestDetailPageArguments requestDetailPageArguments; final RequestDetailPageArguments requestDetailPageArguments;
const RequestDetailPage({Key? key, required this.requestDetailPageArguments}) : super(key: key); const RequestDetailPage({super.key, required this.requestDetailPageArguments});
Widget buildRequestDetailActionFooter({required int requestId, required RequestStatusEnum requestStatus, required RequestsTypeEnum requestTypeEnum, required String statusText, required BuildContext context}) { Widget buildRequestDetailActionFooter(
{required int requestId, required RequestStatusEnum requestStatus, required RequestsTypeEnum requestTypeEnum, required String statusText, required BuildContext context}) {
// final requestsVM = context.read<RequestsVM>(); // final requestsVM = context.read<RequestsVM>();
switch (requestStatus) { switch (requestStatus) {
case RequestStatusEnum.submitted: case RequestStatusEnum.submitted:
@ -31,7 +33,7 @@ class RequestDetailPage extends StatelessWidget {
maxWidth: double.infinity, maxWidth: double.infinity,
margin: const EdgeInsets.all(15), margin: const EdgeInsets.all(15),
maxHeight: 55, maxHeight: 55,
title: LocaleKeys.viewChat.tr(), title: LocaleKeys.specialRequestChat.tr(),
isBold: false, isBold: false,
onPressed: () => onViewChatTapped(context), onPressed: () => onViewChatTapped(context),
); );
@ -115,7 +117,7 @@ class RequestDetailPage extends StatelessWidget {
appBar: CustomAppBar( appBar: CustomAppBar(
title: LocaleKeys.requestDetail.tr(), title: LocaleKeys.requestDetail.tr(),
actions: [ actions: [
(requestDetailPageArguments.requestModel.isChatted) (context.read<RequestsVM>().isOfferSent || requestDetailPageArguments.requestModel.isChatted)
? Padding( ? Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8, right: 21), padding: const EdgeInsets.only(top: 8, bottom: 8, right: 21),
child: const Icon(Icons.messenger_outline_rounded, color: Colors.black, size: 18).toContainer( child: const Icon(Icons.messenger_outline_rounded, color: Colors.black, size: 18).toContainer(
@ -144,7 +146,7 @@ class RequestDetailPage extends StatelessWidget {
allPading: 12, allPading: 12,
margin: const EdgeInsets.only(top: 21, right: 21, left: 21), margin: const EdgeInsets.only(top: 21, right: 21, left: 21),
), ),
if (!requestDetailPageArguments.requestModel.isChatted) ...[ if (!context.read<RequestsVM>().isOfferSent && !requestDetailPageArguments.requestModel.isChatted) ...[
ShowFillButton( ShowFillButton(
maxWidth: double.infinity, maxWidth: double.infinity,
margin: const EdgeInsets.all(15), margin: const EdgeInsets.all(15),
@ -160,7 +162,7 @@ class RequestDetailPage extends StatelessWidget {
requestStatus: requestDetailPageArguments.requestModel.requestStatus, requestStatus: requestDetailPageArguments.requestModel.requestStatus,
statusText: "Offer ${requestDetailPageArguments.requestModel.requestStatusName}", statusText: "Offer ${requestDetailPageArguments.requestModel.requestStatusName}",
context: context, context: context,
requestTypeEnum: requestDetailPageArguments.requestModel.requestType.toRequestTypeStatusEnum(), requestTypeEnum: requestDetailPageArguments.requestModel.requestType.toRequestTypeEnum(),
), ),
], ],
], ],

@ -106,10 +106,7 @@ class RequestItem extends StatelessWidget {
RequestDetailPageArguments requestDetailPageArguments = RequestDetailPageArguments(requestIndex: requestIndex, requestModel: request); RequestDetailPageArguments requestDetailPageArguments = RequestDetailPageArguments(requestIndex: requestIndex, requestModel: request);
navigateWithName(context, AppRoutes.requestsDetailPage, arguments: requestDetailPageArguments); navigateWithName(context, AppRoutes.requestsDetailPage, arguments: requestDetailPageArguments);
} else { } else {
ChatVM chatVM = context.read<ChatVM>(); navigateWithName(context, AppRoutes.offersListPage, arguments: request.id);
await chatVM.getOffersFromProvidersByRequest(requestId: request.id, context: context);
OfferListPageArguments offerListPageArguments = OfferListPageArguments(serviceProviderOffers: chatVM.serviceProviderOffersList, requestId: request.id);
navigateWithName(context, AppRoutes.offersListPage, arguments: offerListPageArguments);
} }
}); });
} }

@ -0,0 +1,98 @@
import 'dart:async';
import 'package:flutter/gestures.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/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/requests_view_model.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/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/views/requests/widget/request_item.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class ProviderAcceptedRequestsView extends StatefulWidget {
const ProviderAcceptedRequestsView({super.key});
@override
State<ProviderAcceptedRequestsView> createState() => _ProviderAcceptedRequestsViewState();
}
class _ProviderAcceptedRequestsViewState extends State<ProviderAcceptedRequestsView> {
@override
void initState() {
scheduleMicrotask(() async => context.read<RequestsVM>().applyFilterOnProvidersAcceptedRequests(requestsTypeEnum: RequestsTypeEnum.specialCarRequest));
super.initState();
}
@override
Widget build(BuildContext context) {
return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.acceptedRequests.tr()),
body: Container(
color: MyColors.backgroundColor,
width: double.infinity,
height: double.infinity,
child: Column(
children: [
16.height,
FiltersList(
filterList: requestsVM.acceptedRequestsTypeFilterOptions,
onFilterTapped: (index, selectedFilterId) {
requestsVM.applyFilterOnProvidersAcceptedRequests(requestsTypeEnum: selectedFilterId.toRequestTypeEnum());
},
),
8.height,
Expanded(
child: RefreshIndicator(
onRefresh: () async => await requestsVM.getProvidersAcceptedRequests(),
child: requestsVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
: requestsVM.providersAcceptedRequestsList.isEmpty
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LocaleKeys.noRequeststoShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor),
if (requestsVM.requestsFiltersCounter > 0) ...[
8.height,
InkWell(
onTap: () async {
requestsVM.clearRequestsFilters();
await requestsVM.getRequestsBasedOnFilters();
},
child: LocaleKeys.clearFilters.tr().toText(
fontSize: 14,
isBold: true,
color: MyColors.darkPrimaryColor,
),
),
],
],
)
: ListView.separated(
itemBuilder: (context, index) {
return RequestItem(request: requestsVM.providersAcceptedRequestsList[index], appType: AppState().currentAppType, requestIndex: index);
},
separatorBuilder: (context, index) {
return 16.height;
},
itemCount: requestsVM.providersAcceptedRequestsList.length,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
),
))
],
),
),
);
});
}
}

@ -87,6 +87,19 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
onTap: () => navigateWithName(context, AppRoutes.favoriteListView), onTap: () => navigateWithName(context, AppRoutes.favoriteListView),
), ),
] else ...[ ] else ...[
CustomSettingOptionsTile(
leadingWidget: SvgPicture.asset(
MyAssets.icRequests,
height: 20,
width: 20,
color: MyColors.darkIconColor,
),
titleText: LocaleKeys.acceptedRequests.tr(),
needBorderBelow: true,
onTap: () {
navigateWithName(context, AppRoutes.providerAcceptedRequestsView);
},
),
CustomSettingOptionsTile( CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.local_shipping, size: 20), leadingWidget: const Icon(Icons.local_shipping, size: 20),
titleText: LocaleKeys.shippingManagement.tr(), titleText: LocaleKeys.shippingManagement.tr(),

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
@ -43,7 +44,18 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
super.initState(); super.initState();
} }
Future buildUpdateShippingStatusBottomSheet({required int shippingRequestId}) { List<FilterListModel> getAvailableStatusesList(List<FilterListModel> list, ShippingRequestStatusEnum shippingRequestStatusEnum) {
List<FilterListModel> newList = [];
for (var element in list) {
if (element.id > shippingRequestStatusEnum.getIdFromShippingStatusEnum()) {
newList.add(element);
}
}
return newList;
}
Future buildUpdateShippingStatusBottomSheet({required int shippingRequestId, required ShippingRequestStatusEnum shippingRequestStatusEnum}) {
return showModalBottomSheet( return showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
@ -63,7 +75,7 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
12.height, 12.height,
ListView.separated( ListView.separated(
shrinkWrap: true, shrinkWrap: true,
itemCount: shippingManagementVM.shippingRequestStatusesList.length, itemCount: getAvailableStatusesList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum).length,
separatorBuilder: (BuildContext context, int index) { separatorBuilder: (BuildContext context, int index) {
return const Padding( return const Padding(
padding: EdgeInsets.symmetric(vertical: 3.0), padding: EdgeInsets.symmetric(vertical: 3.0),
@ -71,13 +83,18 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
); );
}, },
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
List<FilterListModel> list = shippingManagementVM.shippingRequestStatusesList; List<FilterListModel> list = getAvailableStatusesList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum);
FilterListModel shippingFilterListModel = list[index]; FilterListModel shippingFilterListModel = list[index];
int id = list[index].id;
return CircleCheckBoxWithTitle( return CircleCheckBoxWithTitle(
isChecked: shippingFilterListModel.isSelected, isChecked: shippingFilterListModel.isSelected,
title: shippingFilterListModel.title, title: shippingFilterListModel.title,
onSelected: () { onSelected: () {
shippingManagementVM.updateSelectionInShippingRequestStatuses(index); int i = shippingManagementVM.shippingRequestStatusesList.indexWhere((element) => element.id == id);
if (i == -1) {
return;
}
shippingManagementVM.updateSelectionInShippingRequestStatuses(i);
}, },
selectedColor: MyColors.darkPrimaryColor, selectedColor: MyColors.darkPrimaryColor,
); );
@ -103,7 +120,8 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
bool status = await shippingManagementVM.onUpdateShippingStatusTapped(shippingStatusEnum: shippingStatusEnum, shippingRequestId: shippingRequestId, context: context); bool status = await shippingManagementVM.onUpdateShippingStatusTapped(shippingStatusEnum: shippingStatusEnum, shippingRequestId: shippingRequestId, context: context);
if (status) { if (status) {
pop(context); pop(context);
await shippingManagementVM.getShippingRequestsListByFilters(); int index = shippingManagementVM.shippingRequestFilterOptions.indexWhere((element) => element.isSelected);
await shippingManagementVM.getShippingRequestsListByFilters(shippingStatusEnum: index.toShippingStatusEnum());
} }
}, },
maxWidth: double.infinity, maxWidth: double.infinity,
@ -166,26 +184,35 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
text: Utils.getNameByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated), text: Utils.getNameByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
chipColor: Utils.getChipColorByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated), chipColor: Utils.getChipColorByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
), ),
("Request Name | ${shippingRequest.id.toString()}").toText(fontSize: 16), ("${shippingRequest.request!.brand} ${shippingRequest.request!.model} | ${shippingRequest.id.toString()}").toText(fontSize: 16),
8.height, (shippingRequest.request!.description ?? "").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium),
if (shippingRequest.comment != null && shippingRequest.comment!.isNotEmpty) ...[
("${LocaleKeys.comment.tr()}: ${shippingRequest.comment ?? ""}").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium),
],
4.height,
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
children: [ children: [
"customer name".toText(color: MyColors.lightTextColor, fontSize: 14), (shippingRequest.customerName ?? "").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium),
if (shippingRequest.createdOn != null && shippingRequest.createdOn!.isNotEmpty) ...[ if (shippingRequest.createdOn != null && shippingRequest.createdOn!.isNotEmpty) ...[
" | ${DateTime.parse(shippingRequest.createdOn!).getTimeAgo()}".toText(color: MyColors.lightTextColor, fontSize: 14), " | ${DateTime.parse(shippingRequest.createdOn!).getTimeAgo()}".toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium),
], ],
], ],
), ),
if (shippingRequest.shippingStatusEnum != ShippingRequestStatusEnum.delivered) ...[
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18), const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
], ],
],
), ),
], ],
).onPress(() { ).onPress(() {
buildUpdateShippingStatusBottomSheet(shippingRequestId: shippingRequest.id!); if (shippingRequest.shippingStatusEnum == ShippingRequestStatusEnum.delivered) {
return;
}
buildUpdateShippingStatusBottomSheet(shippingRequestId: shippingRequest.id!, shippingRequestStatusEnum: shippingRequest.shippingStatusEnum!);
}).toContainer(isShadowEnabled: true); }).toContainer(isShadowEnabled: true);
}, },
separatorBuilder: (context, index) => 16.height, separatorBuilder: (context, index) => 16.height,

@ -69,7 +69,7 @@ class BranchDetailCard extends StatelessWidget {
if (providerName != null) if (providerName != null)
Row( Row(
children: [ children: [
("${LocaleKeys.providers.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12), ("${LocaleKeys.provider.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width, 4.width,
providerName!.toText(fontSize: 12, isBold: true), providerName!.toText(fontSize: 12, isBold: true),
], ],

@ -1,8 +1,5 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart'; import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/theme/colors.dart';
@ -21,36 +18,49 @@ class MediaViewerScreen extends StatefulWidget {
class MediaViewerScreenState extends State<MediaViewerScreen> { class MediaViewerScreenState extends State<MediaViewerScreen> {
int selectedIndex = 0; // Track selected image index int selectedIndex = 0; // Track selected image index
PageController pageController = PageController(initialPage: 0);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
debugPrint("loaded");
return Scaffold( return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.pictures.tr()), appBar: CustomAppBar(title: LocaleKeys.pictures.tr()),
body: Column( body: Column(
children: [ children: [
// Main Image Display (selected image) // Main Image Display in PageView
Expanded( Expanded(
child: Padding( child: PageView.builder(
itemCount: widget.images.length,
controller: pageController,
onPageChanged: (index) {
setState(() {
selectedIndex = index; // Update the selected index to reflect the current page
});
// Use proper duration and curve
pageController.animateToPage(
index,
duration: const Duration(milliseconds: 500), // Correct duration in milliseconds
curve: Curves.easeInOut, // Smooth easing curve
);
},
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Center( child: Center(
child: InteractiveViewer( child: InteractiveViewer(
panEnabled: true, panEnabled: true,
// Allow panning
scaleEnabled: true, scaleEnabled: true,
// Allow zooming
minScale: 1.0, minScale: 1.0,
// Minimum zoom level
maxScale: 4.0, maxScale: 4.0,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
child: (widget.images[selectedIndex].isFromNetwork ?? false) child: (widget.images[index].isFromNetwork ?? false)
? widget.images[selectedIndex].imageUrl.buildNetworkImage( ? widget.images[index].imageUrl.buildNetworkImage(
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
) )
: widget.images[selectedIndex].imagePath.buildFileImage( : widget.images[index].imagePath.buildFileImage(
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
@ -58,6 +68,8 @@ class MediaViewerScreenState extends State<MediaViewerScreen> {
), ),
), ),
), ),
);
},
), ),
), ),
// Thumbnail List at the bottom // Thumbnail List at the bottom
@ -71,8 +83,15 @@ class MediaViewerScreenState extends State<MediaViewerScreen> {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
selectedIndex = index; // Change the selected image selectedIndex = index; // Update the selected index to reflect the current page
}); });
// Use proper duration and curve
pageController.animateToPage(
index,
duration: const Duration(milliseconds: 100), // Correct duration in milliseconds
curve: Curves.easeInOut, // Smooth easing curve
);
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8.0),
@ -106,7 +125,6 @@ class MediaViewerScreenState extends State<MediaViewerScreen> {
}, },
), ),
), ),
10.height,
], ],
), ),
); );

Loading…
Cancel
Save