Compare commits

...

7 Commits

Author SHA1 Message Date
Mirza.Shafique@cloudsolutions.com.sa 04cfd408bd Merge branch 'mirza_development'
# Conflicts:
#	pubspec.lock
2 years ago
Mirza.Shafique@cloudsolutions.com.sa 9e3cc01302 Merge Conflict 2 years ago
Mirza.Shafique@cloudsolutions.com.sa 5999804bc6 Book Appointment 1.0 2 years ago
Faiz Hashmi 6245aa9ef4 fixed messages bug 2 years ago
Faiz Hashmi 98b35fbc61 Chat Module almost finished! 2 years ago
Faiz Hashmi c5cefa2309 models refinement 2 years ago
Faiz Hashmi 76fd46c654 models refinement 2 years ago

@ -10,8 +10,8 @@ import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/exceptions/api_exception.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/user/refresh_token.dart';
import 'package:mc_common_app/models/user/user.dart';
import 'package:mc_common_app/models/user_models/refresh_token.dart';
import 'package:mc_common_app/models/user_models/user.dart';
import 'package:mc_common_app/utils/shared_prefrence.dart';
typedef FactoryConstructor<U> = U Function(dynamic);

@ -1,6 +1,6 @@
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:mc_common_app/models/post_params_model.dart';
import 'package:mc_common_app/models/user/user.dart';
import 'package:mc_common_app/models/general_models/post_params_model.dart';
import 'package:mc_common_app/models/user_models/user.dart';
import 'package:mc_common_app/utils/enums.dart';
class AppState {

@ -46,6 +46,7 @@ class ApiConsts {
static String Services_Get = "${baseUrlServices}api/ServiceProviders/Services_Get";
static String ServiceProviderService_Create = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create";
static String ServiceProviderService_Update = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update";
static String GetProviderServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String ServiceProviderService_Get = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get";
@ -58,6 +59,7 @@ class ApiConsts {
static String GetServiceItemAppointmentScheduleSlots = "${baseUrlServices}api/ServiceProviders/ServiceItemAppointmentScheduleSlots_GetByAppointmentType";
static String ServiceProvidersAppointmentCreate = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentList_Create";
static String ServiceProviderAppointmentRescheduleCancelAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_RescheduleCancelAppointment";
static String AddNewServicesInAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_ServiceItemAdd";
//ServiceProvidersServiceID as params
// static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get";
@ -103,6 +105,9 @@ class ApiConsts {
static String adsPhotoOfficeAppointmentScheduleSlotGet = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointmentScheduleSlot_Get";
static String adsPhotoOfficeAppointmentCreate = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointment_Create";
static String adsMCBankAccountAdGet = "${baseUrlServices}api/Advertisement/MCBankAccountAd_Get";
static String getAppointmentSlots = "${baseUrlServices}api/ServiceProviders/ScheduleSlotsInfo_Get";
static String updateAppointmentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentStatus_Update";
static String updateAppointmentPaymentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointmentServiceItemPaymentStatus_Update";
//Subscription
static String getAllSubscriptions = "${baseUrlServices}api/Common/Subscription_Get";
@ -147,7 +152,8 @@ class GlobalConsts {
static String fontZoomSize = "font_zoom_size";
static String welcomeVideoUrl = "welcomeVideoUrl";
static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo";
static String demandAmountError = "Demand Amount Cannot be Empty";
static String demandAmountError = "Amount Cannot be Empty";
static String descriptionError = "Description Cannot be Empty";
static String vehicleVinError = "Vehicle VIN Cannot be Empty";
static String vehicleTitleError = "Vehicle Title Cannot be Empty";
static String warrantyError = "Warranty Duration Cannot be Empty";

@ -1,4 +1,7 @@
import 'package:mc_common_app/models/user/register_user.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/models/user_models/register_user.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/views/user/change_email_page.dart';
import 'package:mc_common_app/views/user/change_mobile_page.dart';
@ -71,6 +74,8 @@ class AppRoutes {
static const String myRequestsPage = "/myRequestsPage";
static const String createRequestPage = "/createRequestPage";
static const String offersListPage = "/offersListPage";
static const String requestsDetailPage = "/requestsDetailPage";
static const String sendOfferPage = "/sendOfferPage";
//Setting Options
static const String settingOptionsFaqs = "/settingOptionsFaqs";
@ -103,3 +108,19 @@ class AppRoutes {
editAccountPage: (context) => const EditAccountPage(),
};
}
class ChatViewArguments {
final RequestModel? requestModel;
final ChatTypeEnum chatTypeEnum;
final String senderId;
final String receiverId;
ChatViewArguments({required this.chatTypeEnum, this.requestModel, required this.senderId, required this.receiverId});
}
class OfferListPageArguments {
final List<OffersModel> offersList;
final RequestModel? requestModel;
OfferListPageArguments({required this.offersList, this.requestModel});
}

@ -25,7 +25,9 @@ extension EmailValidator on String {
style: TextStyle(
fontStyle: isItalic ? FontStyle.italic : null,
height: height,
decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none,
decoration: isUnderLine
? TextDecoration.underline
: textDecoration ?? TextDecoration.none,
fontSize: fontSize ?? 10,
fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600,
color: color ?? MyColors.darkTextColor,
@ -34,7 +36,9 @@ extension EmailValidator on String {
);
bool isValidEmail() {
return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this);
return RegExp(
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(this);
}
bool isNum() {
@ -206,6 +210,40 @@ extension AdPostEnum on int {
}
}
extension AppointmentStatusToInt on AppointmentStatusEnum {
int getIdFromAppointmentStatusEnum() {
switch (this) {
case AppointmentStatusEnum.booked:
return 1;
case AppointmentStatusEnum.confirmed:
return 2;
case AppointmentStatusEnum.arrived:
return 3;
case AppointmentStatusEnum.cancelled:
return 4;
case AppointmentStatusEnum.rescheduled:
return 5;
case AppointmentStatusEnum.upcoming:
return 6;
case AppointmentStatusEnum.inProgress:
return 7;
case AppointmentStatusEnum.completed:
return 8;
default:
return 0;
}
}
}
//TODO: Need to verify Enum on upcoming and inprogress with the database
extension AppointmentEnum on int {
AppointmentStatusEnum toAppointmentStatusEnum() {
if (this == 1) {
@ -218,12 +256,60 @@ extension AppointmentEnum on int {
return AppointmentStatusEnum.cancelled;
} else if (this == 5) {
return AppointmentStatusEnum.rescheduled;
} else if (this == 6) {
return AppointmentStatusEnum.upcoming;
} else if (this == 7) {
return AppointmentStatusEnum.inProgress;
} else if (this == 8) {
return AppointmentStatusEnum.completed;
} else {
return AppointmentStatusEnum.allAppointments;
}
}
}
extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
int getIdFromAppointmentPaymentStatusEnum() {
switch (this) {
case AppointmentPaymentStatusEnum.notConfirmed:
return 1;
case AppointmentPaymentStatusEnum.payNow:
return 2;
case AppointmentPaymentStatusEnum.paid:
return 3;
case AppointmentPaymentStatusEnum.payLater:
return 4;
case AppointmentPaymentStatusEnum.payPartial:
return 5;
default:
return 1;
}
}
}
extension AppointmentPaymentEnum on int {
AppointmentPaymentStatusEnum toAppointmentPaymentStatusEnum() {
if (this == 1) {
return AppointmentPaymentStatusEnum.notConfirmed;
} else if (this == 2) {
return AppointmentPaymentStatusEnum.payNow;
} else if (this == 3) {
return AppointmentPaymentStatusEnum.paid;
} else if (this == 4) {
return AppointmentPaymentStatusEnum.payLater;
} else if (this == 5) {
return AppointmentPaymentStatusEnum.payPartial;
} else {
return AppointmentPaymentStatusEnum.notConfirmed;
}
}
}
extension RequestTypeTypeEnum on int {
RequestsTypeEnum toRequestTypeStatusEnum() {
if (this == 1) {
@ -235,6 +321,21 @@ extension RequestTypeTypeEnum on int {
}
}
extension RequestTypeStatusToInt on RequestsTypeEnum {
int getIdFromRequestTypeStatusEnum() {
switch (this) {
case RequestsTypeEnum.specialCarRequest:
return 1;
case RequestsTypeEnum.serviceRequest:
return 2;
default:
return 0;
}
}
}
extension AdPostStatusToInt on AdPostStatus {
int getIdFromAdPostStatusEnum() {
switch (this) {
@ -299,45 +400,6 @@ extension PaymentTypesToInt on PaymentTypes {
}
}
extension AppointmentStatusToInt on AppointmentStatusEnum {
int getIdFromAppointmentStatusEnum() {
switch (this) {
case AppointmentStatusEnum.booked:
return 1;
case AppointmentStatusEnum.confirmed:
return 2;
case AppointmentStatusEnum.arrived:
return 3;
case AppointmentStatusEnum.cancelled:
return 4;
case AppointmentStatusEnum.rescheduled:
return 5;
default:
return 0;
}
}
}
extension RequestTypeStatusToInt on RequestsTypeEnum {
int getIdFromRequestTypeStatusEnum() {
switch (this) {
case RequestsTypeEnum.specialCarRequest:
return 1;
case RequestsTypeEnum.serviceRequest:
return 2;
default:
return 0;
}
}
}
extension CreatedByRoleEnumToInt on CreatedByRoleEnum {
int getIdFromCreatedByRoleEnum() {
switch (this) {
@ -548,3 +610,111 @@ extension FormatMonthByNumber on String {
}
}
}
extension ChatMessageTypeEnumExt on int {
//FreeText = 1,
// Image = 2,
// Audio = 3,
// Video = 4,
// Offer = 5
ChatMessageTypeEnum toChatMessageTypeEnum() {
if (this == 1) {
return ChatMessageTypeEnum.freeText;
} else if (this == 2) {
return ChatMessageTypeEnum.image;
} else if (this == 3) {
return ChatMessageTypeEnum.audio;
} else if (this == 4) {
return ChatMessageTypeEnum.video;
} else if (this == 5) {
return ChatMessageTypeEnum.offer;
}
return ChatMessageTypeEnum.freeText;
}
}
extension ChatMessageTypeToInt on ChatMessageTypeEnum {
int getIdFromChatMessageTypeEnum() {
switch (this) {
case ChatMessageTypeEnum.freeText:
return 1;
case ChatMessageTypeEnum.image:
return 2;
case ChatMessageTypeEnum.audio:
return 3;
case ChatMessageTypeEnum.video:
return 4;
case ChatMessageTypeEnum.offer:
return 5;
default:
return 1;
}
}
}
extension RequestOfferStatusEnumExt on int {
RequestOfferStatusEnum toRequestOfferStatusEnum() {
if (this == 1) {
return RequestOfferStatusEnum.offer;
} else if (this == 2) {
return RequestOfferStatusEnum.negotiate;
} else if (this == 3) {
return RequestOfferStatusEnum.accepted;
} else if (this == 4) {
return RequestOfferStatusEnum.rejected;
} else if (this == 5) {
return RequestOfferStatusEnum.cancel;
}
return RequestOfferStatusEnum.cancel;
}
}
extension RequestOfferStatusEnumToInt on RequestOfferStatusEnum {
int getIdFromRequestOfferStatusEnum() {
switch (this) {
case RequestOfferStatusEnum.offer:
return 1;
case RequestOfferStatusEnum.negotiate:
return 2;
case RequestOfferStatusEnum.accepted:
return 3;
case RequestOfferStatusEnum.rejected:
return 4;
case RequestOfferStatusEnum.cancel:
return 5;
default:
return 0;
}
}
}
extension ChatTypeEnumExt on int {
ChatTypeEnum toChatTypeEnum() {
if (this == 1) {
return ChatTypeEnum.general;
} else if (this == 2) {
return ChatTypeEnum.ads;
} else if (this == 3) {
return ChatTypeEnum.requestOffer;
}
return ChatTypeEnum.general;
}
}
extension ChatTypeEnumToInt on ChatTypeEnum {
int getIdFromChatTypeEnum() {
switch (this) {
case ChatTypeEnum.general:
return 1;
case ChatTypeEnum.ads:
return 2;
case ChatTypeEnum.requestOffer:
return 3;
default:
return 1;
}
}
}

@ -1,44 +0,0 @@
// To parse this JSON data, do
//
// final account = accountFromJson(jsonString);
import 'dart:convert';
import 'package:mc_common_app/models/parent_list.dart';
Account accountFromJson(String str) => Account.fromJson(json.decode(str));
String accountToJson(Account data) => json.encode(data.toJson());
class Account {
Account({
required this.parentList,
required this.selectedItem,
});
List<ParentList>? parentList;
int selectedItem;
factory Account.fromJson(Map<String, dynamic> json) => Account(
parentList: json["parentList"] == null
? null
: List<ParentList>.from(
json["parentList"].map((x) => ParentList.fromJson(x))),
selectedItem:
json["selectedItem"] == null ? null : json["selectedItem"],
);
Map<String, dynamic> toJson() => {
"parentList": parentList == null
? null
: List<dynamic>.from(parentList!.map((x) => x.toJson())),
"selectedItem": selectedItem == null ? null : selectedItem,
};
Map<String, dynamic> toJsonData() => {
"selectedItem": selectedItem == null ? null : selectedItem,
};
}

@ -1,5 +1,5 @@
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
class SSCarCheckScheduleModel {
int? serviceProviderID;

@ -1,6 +1,6 @@
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
class SSPhotoOfficeScheduleModel {
int? photoOfficeID;

@ -1,5 +1,5 @@
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/utils/enums.dart';
class AppointmentListModel {
@ -14,11 +14,20 @@ class AppointmentListModel {
int? paymentStatus;
String? paymentStatusText;
String? customerName;
String? customerMobileNum;
int? appointmentType;
String? providerName;
String? duration;
String? appointmentDate;
String? branchName;
int? branchId;
int? servicePaymentStatus;
double? totalAmount;
double? remainingAmount;
AppointmentStatusEnum? appointmentStatusEnum;
AppointmentPaymentStatusEnum? appointmentPaymentStatusEnum;
List<ServiceModel>? appointmentServicesList;
List<AppointmentListModel>? customerAppointmentList;
AppointmentListModel(
{this.id,
@ -32,10 +41,18 @@ class AppointmentListModel {
this.paymentStatus,
this.paymentStatusText,
this.customerName,
this.customerMobileNum,
this.appointmentType,
this.providerName,
this.duration,
this.branchName,
this.branchId,
this.servicePaymentStatus,
this.totalAmount,
this.remainingAmount,
this.appointmentDate,
this.appointmentServicesList});
this.appointmentServicesList,
this.customerAppointmentList});
@override
String toString() {
@ -54,15 +71,26 @@ class AppointmentListModel {
paymentStatus = json['paymentStatus'];
paymentStatusText = json['paymentStatusText'];
customerName = json['customerName'];
customerMobileNum = json['customerMobile'];
appointmentType = json['appointmentType'];
providerName = json['providerName'];
duration = json['duration'];
appointmentDate = json['appointmentDate'];
appointmentStatusEnum = (json['appointmentStatusID'] as int).toAppointmentStatusEnum();
branchName = json['branchName'];
branchId = json['branchID'];
servicePaymentStatus = json['servicePaymentStatus'];
totalAmount = json['amountTotal'];
remainingAmount = json['amountRem'];
appointmentStatusEnum =
(json['appointmentStatusID'] as int).toAppointmentStatusEnum();
appointmentPaymentStatusEnum =
(json['servicePaymentStatus'] as int).toAppointmentPaymentStatusEnum();
if (json['serviceList'] != null) {
appointmentServicesList = <ServiceModel>[];
json['serviceList'].forEach((v) {
appointmentServicesList!.add(ServiceModel.fromJson(v, isForAppointment: true));
appointmentServicesList!
.add(ServiceModel.fromJson(v, isForAppointment: true));
});
}
}
@ -74,7 +102,11 @@ class ServiceAppointmentItems {
String? serviceItemName;
String? serviceItemDescription;
ServiceAppointmentItems({this.id, this.serviceItemID, this.serviceItemName, this.serviceItemDescription});
ServiceAppointmentItems(
{this.id,
this.serviceItemID,
this.serviceItemName,
this.serviceItemDescription});
ServiceAppointmentItems.fromJson(Map<String, dynamic> json) {
id = json['id'];
@ -92,3 +124,15 @@ class ServiceAppointmentItems {
return data;
}
}
// Data Model Class with 'customerName' and 'customerID'
class CustomerData {
final int customerID;
final String customerName;
final List<AppointmentListModel> appointmentList;
CustomerData(
{required this.customerID,
required this.customerName,
required this.appointmentList});
}

@ -0,0 +1,24 @@
class AppointmentSlots {
int totalSlots;
int occupiedSlots;
int emptySlots;
AppointmentSlots({
required this.totalSlots,
required this.occupiedSlots,
required this.emptySlots,
});
factory AppointmentSlots.fromJson(Map<String, dynamic> json) =>
AppointmentSlots(
totalSlots: json["totalSlots"],
occupiedSlots: json["occupiedSlots"],
emptySlots: json["emptySlots"],
);
Map<String, dynamic> toJson() => {
"totalSlots": totalSlots,
"occupiedSlots": occupiedSlots,
"emptySlots": emptySlots,
};
}

@ -4,7 +4,7 @@
import 'dart:convert';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
Schedule scheduleFromJson(String str) => Schedule.fromJson(json.decode(str));

@ -1,6 +1,6 @@
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
class CustomTimeDateSlotModel {
TimeSlotModel? date;

@ -0,0 +1,103 @@
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/utils/enums.dart';
class ChatMessageModel {
String? senderUserID;
String? senderName;
int? messageType;
ChatMessageTypeEnum? messageTypeEnum;
String? message;
RequestOffer? requestOffer;
int? requestID;
int? requestOfferID;
bool? isMyMessage;
ChatMessageModel({
this.senderUserID,
this.senderName,
this.messageType,
this.message,
this.requestOffer,
this.requestID,
this.requestOfferID,
this.isMyMessage = true,
});
ChatMessageModel.fromJson(Map<String, dynamic> json) {
final myUserId = AppState().getUser.data!.userInfo!.userId.toString();
senderUserID = json['senderUserID'];
senderName = json['senderName'];
messageType = json['messageType'];
messageTypeEnum = (json['messageType'] as int).toChatMessageTypeEnum();
message = json['message'];
requestOffer = json['requestOffer'] != null ? RequestOffer.fromJson(json['requestOffer']) : null;
requestID = json['requestID'];
requestOfferID = json['requestOfferID'];
isMyMessage = (json['senderUserId']).toString() == myUserId;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['senderUserID'] = senderUserID;
data['senderName'] = senderName;
data['messageType'] = messageType;
data['message'] = message;
if (requestOffer != null) {
data['requestOffer'] = requestOffer!.toJson();
}
data['requestID'] = requestID;
data['requestOfferID'] = requestOfferID;
return data;
}
}
class RequestOffer {
int? id;
int? requestID;
int? serviceProviderID;
int? offerStatus;
RequestOfferStatusEnum? requestOfferStatusEnum;
String? comment;
double? price;
String? offeredItemCreatedBy;
String? offeredItemCreatedOn;
RequestOffer({
this.id,
this.requestID,
this.serviceProviderID,
this.offerStatus,
this.comment,
this.price,
this.offeredItemCreatedBy,
this.offeredItemCreatedOn,
this.requestOfferStatusEnum = RequestOfferStatusEnum.offer,
});
RequestOffer.fromJson(Map<String, dynamic> json) {
id = json['id'];
requestID = json['requestID'];
serviceProviderID = json['serviceProviderID'];
offerStatus = json['offerStatus'];
offerStatus = json['offerStatus'];
requestOfferStatusEnum = ((json['offerStatus']) as int).toRequestOfferStatusEnum();
comment = json['comment'];
price = json['price'];
offeredItemCreatedBy = json['offeredItemCreatedBy'];
offeredItemCreatedOn = json['offeredItemCreatedOn'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['requestID'] = requestID;
data['serviceProviderID'] = serviceProviderID;
data['offerStatus'] = offerStatus;
data['comment'] = comment;
data['price'] = price;
data['offeredItemCreatedBy'] = offeredItemCreatedBy;
data['offeredItemCreatedOn'] = offeredItemCreatedOn;
return data;
}
}

@ -1,12 +0,0 @@
class ConfigModel {
ConfigModel(this.endpoint, this.organizationName);
String endpoint;
String organizationName;
factory ConfigModel.fromJson(Map<String, dynamic> json) =>
ConfigModel("", "");
// Map<String, dynamic> toJson() => _$ConfigModelToJson(this);
}

@ -1,65 +0,0 @@
class ContentInfoModel {
int? totalItemsCount;
int? statusCode;
String? message;
List<ContentInfoDataModel>? data;
ContentInfoModel({this.totalItemsCount, this.statusCode, this.message, this.data});
ContentInfoModel.fromJson(Map<String, dynamic> json) {
totalItemsCount = json['totalItemsCount'];
statusCode = json['statusCode'];
message = json['message'];
if (json['data'] != null) {
data = [];
json['data'].forEach((v) {
data?.add(new ContentInfoDataModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['totalItemsCount'] = this.totalItemsCount;
data['statusCode'] = this.statusCode;
data['message'] = this.message;
if (this.data != null) {
data['data'] = this.data?.map((v) => v.toJson()).toList();
}
return data;
}
}
class ContentInfoDataModel {
int? contentInfoId;
int? contentTypeId;
String? content;
String? contentTypeNameEn;
String? contentTypeNameAr;
String? fileName;
String? exposeFilePath;
ContentInfoDataModel({this.contentInfoId, this.contentTypeId, this.content, this.contentTypeNameEn, this.contentTypeNameAr, this.fileName, this.exposeFilePath});
ContentInfoDataModel.fromJson(Map<String, dynamic> json) {
contentInfoId = json['contentInfoId'];
contentTypeId = json['contentTypeId'];
content = json['content'];
contentTypeNameEn = json['contentTypeNameEn'];
contentTypeNameAr = json['contentTypeNameAr'];
fileName = json['fileName'];
exposeFilePath = json['exposeFilePath'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['contentInfoId'] = this.contentInfoId;
data['contentTypeId'] = this.contentTypeId;
data['content'] = this.content;
data['contentTypeNameEn'] = this.contentTypeNameEn;
data['contentTypeNameAr'] = this.contentTypeNameAr;
data['fileName'] = this.fileName;
data['exposeFilePath'] = this.exposeFilePath;
return data;
}
}

@ -1,62 +0,0 @@
class MemberModel {
int? totalItemsCount;
int? statusCode;
String? message;
List<MemberDataModel>? data;
MemberModel({this.totalItemsCount, this.statusCode, this.message, this.data});
MemberModel.fromJson(Map<String, dynamic> json) {
totalItemsCount = json['totalItemsCount'];
statusCode = json['statusCode'];
message = json['message'];
if (json['data'] != null) {
data = [];
json['data'].forEach((v) {
data?.add(new MemberDataModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['totalItemsCount'] = this.totalItemsCount;
data['statusCode'] = this.statusCode;
data['message'] = this.message;
if (this.data != null) {
data['data'] = this.data?.map((v) => v.toJson()).toList();
}
return data;
}
}
class MemberDataModel {
int? committeeId;
String? firstName;
String? lastName;
String? description;
String? picture;
int? orderNo;
MemberDataModel({this.committeeId, this.firstName, this.lastName, this.description, this.picture, this.orderNo});
MemberDataModel.fromJson(Map<String, dynamic> json) {
committeeId = json['committeeId'];
firstName = json['firstName'];
lastName = json['lastName'];
description = json['description'];
picture = json['picture'];
orderNo = json['orderNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['committeeId'] = this.committeeId;
data['firstName'] = this.firstName;
data['lastName'] = this.lastName;
data['description'] = this.description;
data['picture'] = this.picture;
data['orderNo'] = this.orderNo;
return data;
}
}

@ -1,26 +0,0 @@
class ParentList {
ParentList({
required this.dbId,
required this.text,
required this.path,
required this.isSelected,
});
int dbId;
String text;
String path;
bool isSelected;
factory ParentList.fromJson(Map<String, dynamic> json) => ParentList(
dbId: json["dbId"] == null ? null : json["dbId"],
text: json["text"] == null ? null : json["text"],
path: json["path"] == null ? null : json["path"],
isSelected: false,
);
Map<String, dynamic> toJson() => {
"dbId": dbId == null ? null : dbId,
"text": text == null ? null : text,
"path": path == null ? null : path,
};
}

@ -1,6 +1,6 @@
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/utils/enums.dart';
class BranchDetailModel {

@ -6,7 +6,7 @@ import 'dart:convert';
import 'package:equatable/equatable.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
Category categoryFromJson(String str) => Category.fromJson(json.decode(str));

@ -10,6 +10,7 @@ class RequestModel {
String vehicleTypeName;
String countryName;
String customerName;
String customerID;
dynamic serviceProviders;
int offerCount;
int id;
@ -43,6 +44,7 @@ class RequestModel {
required this.vehicleTypeName,
required this.countryName,
required this.customerName,
required this.customerID,
required this.serviceProviders,
required this.offerCount,
required this.id,
@ -68,39 +70,42 @@ class RequestModel {
required this.modifiedOn,
});
factory RequestModel.fromJson(Map<String, dynamic> json) => RequestModel(
requestType: json["requestType"],
requestTypeName: json["requestTypeName"],
requestStatusName: json["requestStatusName"],
requestStatus: (json['requestStatus'] as int).toRequestStatusEnum(),
cityName: json["cityName"],
vehicleTypeName: json["vehicleTypeName"],
countryName: json["countryName"],
customerName: json["customerName"],
serviceProviders: json["serviceProviders"],
offerCount: json["offerCount"],
id: json["id"],
customerId: json["customerID"],
customer: json["customer"],
brand: json["brand"],
model: json["model"],
year: json["year"],
isNew: json["isNew"],
description: json["description"],
requestImages: List<dynamic>.from(json["requestImages"].map((x) => x)),
cityId: json["cityID"],
city: json["city"],
price: json["price"],
paymentStatus: json["paymentStatus"],
vehicleTypeId: json["vehicleTypeID"],
countryId: json["countryID"],
requestProviderItem: List<dynamic>.from(json["requestProviderItem"].map((x) => x)),
isActive: json["isActive"],
createdBy: json["createdBy"],
createdOn: DateTime.parse(json["createdOn"]),
modifiedBy: json["modifiedBy"],
modifiedOn: json["modifiedOn"],
);
factory RequestModel.fromJson(Map<String, dynamic> json) {
return RequestModel(
requestType: json["requestType"],
requestTypeName: json["requestTypeName"],
requestStatusName: json["requestStatusName"],
requestStatus: (json['requestStatus'] as int).toRequestStatusEnum(),
cityName: json["cityName"],
vehicleTypeName: json["vehicleTypeName"],
countryName: json["countryName"],
customerName: json["customerName"],
customerID: json["customerUserID"],
serviceProviders: json["serviceProviders"],
offerCount: json["offerCount"],
id: json["id"],
customerId: json["customerID"],
customer: json["customer"],
brand: json["brand"],
model: json["model"],
year: json["year"],
isNew: json["isNew"],
description: json["description"],
requestImages: List<dynamic>.from(json["requestImages"].map((x) => x)),
cityId: json["cityID"],
city: json["city"],
price: json["price"],
paymentStatus: json["paymentStatus"],
vehicleTypeId: json["vehicleTypeID"],
countryId: json["countryID"],
requestProviderItem: List<dynamic>.from(json["requestProviderItem"].map((x) => x)),
isActive: json["isActive"],
createdBy: json["createdBy"],
createdOn: DateTime.parse(json["createdOn"]),
modifiedBy: json["modifiedBy"],
modifiedOn: json["modifiedOn"],
);
}
Map<String, dynamic> toJson() => {
"requestType": requestType,

@ -1,34 +0,0 @@
///
/// This example was taken from
/// https://flutter.dev/docs/development/data-and-backend/json
///
/// This allows the `User` class to access private members in
/// the generated file. The value for this is *.g.dart, where
/// the star denotes the source file name.
/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
class BackendResponse {
BackendResponse({required this.id, required this.isOk, required this.result});
int id;
bool isOk;
dynamic result;
/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
/// The constructor is named after the source class, in this case, User.
factory BackendResponse.fromJson(Map<String, dynamic> json) =>
BackendResponse(
id: 1,
isOk: false,
result: null,
);
//
// /// `toJson` is the convention for a class to declare support for serialization
// /// to JSON. The implementation simply calls the private, generated
// /// helper method `_$UserToJson`.
// Map<String, dynamic> toJson() => _$BackendResponseToJson(this);
}

@ -1,4 +1,4 @@
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
class ServiceModel {
final int? serviceProviderServiceId;

@ -1,74 +0,0 @@
class SurahModel {
int? totalItemsCount;
int? statusCode;
String? message;
List<SurahModelData>? data;
SurahModel({this.totalItemsCount, this.statusCode, this.message, this.data});
SurahModel.fromJson(Map<String, dynamic> json) {
totalItemsCount = json['totalItemsCount'];
statusCode = json['statusCode'];
message = json['message'];
if (json['data'] != null) {
data = [];
json['data'].forEach((v) {
data?.add(SurahModelData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['totalItemsCount'] = totalItemsCount;
data['statusCode'] = statusCode;
data['message'] = message;
if (this.data != null) {
data['data'] = this.data?.map((v) => v.toJson()).toList();
}
return data;
}
}
class SurahModelData {
int? id;
int? surahID;
String? nameAR;
String? nameEN;
int? numberOfAyahs;
String? englishNameTranslation;
int? revelationID;
String? revelationType;
int? startPageNo;
int? endPageNo;
SurahModelData({this.id, this.surahID, this.nameAR, this.nameEN, this.numberOfAyahs, this.englishNameTranslation, this.revelationID, this.revelationType, this.startPageNo, this.endPageNo});
SurahModelData.fromJson(Map<String, dynamic> json) {
id = json['id'];
surahID = json['surahID'];
nameAR = json['nameAR'];
nameEN = json['nameEN'];
numberOfAyahs = json['numberOfAyahs'];
englishNameTranslation = json['englishNameTranslation'];
revelationID = json['revelation_ID'];
revelationType = json['revelationType'];
startPageNo = json['startPageNo'];
endPageNo = json['endPageNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['surahID'] = this.surahID;
data['nameAR'] = this.nameAR;
data['nameEN'] = this.nameEN;
data['numberOfAyahs'] = this.numberOfAyahs;
data['englishNameTranslation'] = this.englishNameTranslation;
data['revelation_ID'] = this.revelationID;
data['revelationType'] = this.revelationType;
data['startPageNo'] = this.startPageNo;
data['endPageNo'] = this.endPageNo;
return data;
}
}

@ -0,0 +1,44 @@
// // To parse this JSON data, do
// //
// // final account = accountFromJson(jsonString);
//
// import 'dart:convert';
//
// import 'package:mc_common_app/models/parent_list.dart';
//
//
//
//
// Account accountFromJson(String str) => Account.fromJson(json.decode(str));
//
// String accountToJson(Account data) => json.encode(data.toJson());
//
// class Account {
// Account({
// required this.parentList,
// required this.selectedItem,
// });
//
// List<ParentList>? parentList;
// int selectedItem;
//
// factory Account.fromJson(Map<String, dynamic> json) => Account(
// parentList: json["parentList"] == null
// ? null
// : List<ParentList>.from(
// json["parentList"].map((x) => ParentList.fromJson(x))),
// selectedItem:
// json["selectedItem"] == null ? null : json["selectedItem"],
// );
//
// Map<String, dynamic> toJson() => {
// "parentList": parentList == null
// ? null
// : List<dynamic>.from(parentList!.map((x) => x.toJson())),
// "selectedItem": selectedItem == null ? null : selectedItem,
// };
//
// Map<String, dynamic> toJsonData() => {
// "selectedItem": selectedItem == null ? null : selectedItem,
// };
// }

@ -0,0 +1,12 @@
// class ConfigModel {
// ConfigModel(this.endpoint, this.organizationName);
//
// String endpoint;
//
// String organizationName;
//
// factory ConfigModel.fromJson(Map<String, dynamic> json) =>
// ConfigModel("", "");
//
// // Map<String, dynamic> toJson() => _$ConfigModelToJson(this);
// }

@ -0,0 +1,65 @@
// class ContentInfoModel {
// int? totalItemsCount;
// int? statusCode;
// String? message;
// List<ContentInfoDataModel>? data;
//
// ContentInfoModel({this.totalItemsCount, this.statusCode, this.message, this.data});
//
// ContentInfoModel.fromJson(Map<String, dynamic> json) {
// totalItemsCount = json['totalItemsCount'];
// statusCode = json['statusCode'];
// message = json['message'];
// if (json['data'] != null) {
// data = [];
// json['data'].forEach((v) {
// data?.add(new ContentInfoDataModel.fromJson(v));
// });
// }
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['totalItemsCount'] = this.totalItemsCount;
// data['statusCode'] = this.statusCode;
// data['message'] = this.message;
// if (this.data != null) {
// data['data'] = this.data?.map((v) => v.toJson()).toList();
// }
// return data;
// }
// }
//
// class ContentInfoDataModel {
// int? contentInfoId;
// int? contentTypeId;
// String? content;
// String? contentTypeNameEn;
// String? contentTypeNameAr;
// String? fileName;
// String? exposeFilePath;
//
// ContentInfoDataModel({this.contentInfoId, this.contentTypeId, this.content, this.contentTypeNameEn, this.contentTypeNameAr, this.fileName, this.exposeFilePath});
//
// ContentInfoDataModel.fromJson(Map<String, dynamic> json) {
// contentInfoId = json['contentInfoId'];
// contentTypeId = json['contentTypeId'];
// content = json['content'];
// contentTypeNameEn = json['contentTypeNameEn'];
// contentTypeNameAr = json['contentTypeNameAr'];
// fileName = json['fileName'];
// exposeFilePath = json['exposeFilePath'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['contentInfoId'] = this.contentInfoId;
// data['contentTypeId'] = this.contentTypeId;
// data['content'] = this.content;
// data['contentTypeNameEn'] = this.contentTypeNameEn;
// data['contentTypeNameAr'] = this.contentTypeNameAr;
// data['fileName'] = this.fileName;
// data['exposeFilePath'] = this.exposeFilePath;
// return data;
// }
// }

@ -0,0 +1,62 @@
// class MemberModel {
// int? totalItemsCount;
// int? statusCode;
// String? message;
// List<MemberDataModel>? data;
//
// MemberModel({this.totalItemsCount, this.statusCode, this.message, this.data});
//
// MemberModel.fromJson(Map<String, dynamic> json) {
// totalItemsCount = json['totalItemsCount'];
// statusCode = json['statusCode'];
// message = json['message'];
// if (json['data'] != null) {
// data = [];
// json['data'].forEach((v) {
// data?.add(new MemberDataModel.fromJson(v));
// });
// }
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['totalItemsCount'] = this.totalItemsCount;
// data['statusCode'] = this.statusCode;
// data['message'] = this.message;
// if (this.data != null) {
// data['data'] = this.data?.map((v) => v.toJson()).toList();
// }
// return data;
// }
// }
//
// class MemberDataModel {
// int? committeeId;
// String? firstName;
// String? lastName;
// String? description;
// String? picture;
// int? orderNo;
//
// MemberDataModel({this.committeeId, this.firstName, this.lastName, this.description, this.picture, this.orderNo});
//
// MemberDataModel.fromJson(Map<String, dynamic> json) {
// committeeId = json['committeeId'];
// firstName = json['firstName'];
// lastName = json['lastName'];
// description = json['description'];
// picture = json['picture'];
// orderNo = json['orderNo'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['committeeId'] = this.committeeId;
// data['firstName'] = this.firstName;
// data['lastName'] = this.lastName;
// data['description'] = this.description;
// data['picture'] = this.picture;
// data['orderNo'] = this.orderNo;
// return data;
// }
// }

@ -0,0 +1,26 @@
// class ParentList {
// ParentList({
// required this.dbId,
// required this.text,
// required this.path,
// required this.isSelected,
// });
//
// int dbId;
// String text;
// String path;
// bool isSelected;
//
// factory ParentList.fromJson(Map<String, dynamic> json) => ParentList(
// dbId: json["dbId"] == null ? null : json["dbId"],
// text: json["text"] == null ? null : json["text"],
// path: json["path"] == null ? null : json["path"],
// isSelected: false,
// );
//
// Map<String, dynamic> toJson() => {
// "dbId": dbId == null ? null : dbId,
// "text": text == null ? null : text,
// "path": path == null ? null : path,
// };
// }

@ -63,3 +63,5 @@
// return 'ProviderServiceModel{id: $id, description: $description, descriptionN: $descriptionN, serviceIconUrl: $serviceIconUrl, serviceImageUrl: $serviceImageUrl, serviceCategoryID: $serviceCategoryID, isActive: $isActive, categoryName: $categoryName, ispartial: $ispartial, appointmentPricePercentage: $appointmentPricePercentage, refundAmountPercentage: $refundAmountPercentage, isSelected: $isSelected}';
// }
// }
// // test

@ -0,0 +1,34 @@
// ///
// /// This example was taken from
// /// https://flutter.dev/docs/development/data-and-backend/json
// ///
//
// /// This allows the `User` class to access private members in
// /// the generated file. The value for this is *.g.dart, where
// /// the star denotes the source file name.
//
// /// An annotation for the code generator to know that this class needs the
// /// JSON serialization logic to be generated.
//
// class BackendResponse {
// BackendResponse({required this.id, required this.isOk, required this.result});
//
// int id;
// bool isOk;
// dynamic result;
//
// /// A necessary factory constructor for creating a new User instance
// /// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
// /// The constructor is named after the source class, in this case, User.
// factory BackendResponse.fromJson(Map<String, dynamic> json) =>
// BackendResponse(
// id: 1,
// isOk: false,
// result: null,
// );
// //
// // /// `toJson` is the convention for a class to declare support for serialization
// // /// to JSON. The implementation simply calls the private, generated
// // /// helper method `_$UserToJson`.
// // Map<String, dynamic> toJson() => _$BackendResponseToJson(this);
// }

@ -0,0 +1,74 @@
// class SurahModel {
// int? totalItemsCount;
// int? statusCode;
// String? message;
// List<SurahModelData>? data;
//
// SurahModel({this.totalItemsCount, this.statusCode, this.message, this.data});
//
// SurahModel.fromJson(Map<String, dynamic> json) {
// totalItemsCount = json['totalItemsCount'];
// statusCode = json['statusCode'];
// message = json['message'];
// if (json['data'] != null) {
// data = [];
// json['data'].forEach((v) {
// data?.add(SurahModelData.fromJson(v));
// });
// }
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['totalItemsCount'] = totalItemsCount;
// data['statusCode'] = statusCode;
// data['message'] = message;
// if (this.data != null) {
// data['data'] = this.data?.map((v) => v.toJson()).toList();
// }
// return data;
// }
// }
//
// class SurahModelData {
// int? id;
// int? surahID;
// String? nameAR;
// String? nameEN;
// int? numberOfAyahs;
// String? englishNameTranslation;
// int? revelationID;
// String? revelationType;
// int? startPageNo;
// int? endPageNo;
//
// SurahModelData({this.id, this.surahID, this.nameAR, this.nameEN, this.numberOfAyahs, this.englishNameTranslation, this.revelationID, this.revelationType, this.startPageNo, this.endPageNo});
//
// SurahModelData.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// surahID = json['surahID'];
// nameAR = json['nameAR'];
// nameEN = json['nameEN'];
// numberOfAyahs = json['numberOfAyahs'];
// englishNameTranslation = json['englishNameTranslation'];
// revelationID = json['revelation_ID'];
// revelationType = json['revelationType'];
// startPageNo = json['startPageNo'];
// endPageNo = json['endPageNo'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['id'] = this.id;
// data['surahID'] = this.surahID;
// data['nameAR'] = this.nameAR;
// data['nameEN'] = this.nameEN;
// data['numberOfAyahs'] = this.numberOfAyahs;
// data['englishNameTranslation'] = this.englishNameTranslation;
// data['revelation_ID'] = this.revelationID;
// data['revelationType'] = this.revelationType;
// data['startPageNo'] = this.startPageNo;
// data['endPageNo'] = this.endPageNo;
// return data;
// }
// }

@ -11,7 +11,7 @@ import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart
import 'package:mc_common_app/models/advertisment_models/reserved_ads_models.dart';
import 'package:mc_common_app/models/advertisment_models/special_service_model.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/enums.dart';
abstract class AdsRepo {

@ -4,14 +4,27 @@ import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/m_response.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
import 'package:mc_common_app/models/schedule_model.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/appointments_models/schedule_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import '../models/appointments_models/appointment_list_model.dart';
abstract class AppointmentRepo {
Future<List<AppointmentListModel>> getMyAppointments(
Map<String, dynamic> map);
Future<MResponse> updateAppointmentStatus(
Map<String, dynamic> map);
Future<MResponse> updateAppointmentPaymentStatus(
Map<String, dynamic> map);
Future<MResponse> getAppointmentSlots(Map<String, dynamic> map);
Future<Services> getAllServices(String branchId);
Future<MResponse> createSchedule(Map map);
@ -24,14 +37,20 @@ abstract class AppointmentRepo {
Future<MResponse> updateServicesInSchedule(Map map);
Future<List<ServiceAppointmentScheduleModel>> mergeServiceIntoAvailableSchedules({
Future<List<ServiceAppointmentScheduleModel>>
mergeServiceIntoAvailableSchedules({
required List<String> serviceItemIdsForHome,
required List<String> serviceItemIdsForWorkshop,
});
Future<GenericRespModel> createServiceAppointment({required List<ServiceAppointmentScheduleModel> schedules, required int serviceProviderID});
Future<GenericRespModel> createServiceAppointment(
{required List<ServiceAppointmentScheduleModel> schedules,
required int serviceProviderID});
Future<GenericRespModel> cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction});
Future<GenericRespModel> cancelOrRescheduleServiceAppointment(
{required int serviceAppointmentID,
required int serviceSlotID,
required int appointmentScheduleAction});
}
class AppointmentRepoImp implements AppointmentRepo {
@ -39,19 +58,25 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<Services> getAllServices(String branchId) async {
Map<String, dynamic> map = {"ProviderBranchID": branchId};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map);
return await injector.get<ApiClient>().getJsonForObject(
(json) => Services.fromJson(json), ApiConsts.getServicesOfBranch,
token: t, queryParameters: map);
}
@override
Future<MResponse> createSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.createSchedule, map,
token: t);
}
@override
Future<MResponse> addServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.createGroup, map,
token: t);
}
@override
@ -59,29 +84,36 @@ class AppointmentRepoImp implements AppointmentRepo {
Map<String, dynamic> map = {"ServiceProviderBranchID": branchId};
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getSchedule,
token: t,
queryParameters: map,
);
GenericRespModel adsGenericModel =
await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getSchedule,
token: t,
queryParameters: map,
);
return List.generate(adsGenericModel.data.length, (index) => ScheduleData.fromJson(adsGenericModel.data[index]));
return List.generate(adsGenericModel.data.length,
(index) => ScheduleData.fromJson(adsGenericModel.data[index]));
}
@override
Future<MResponse> updateSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map,
token: t);
}
@override
Future<MResponse> updateServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateGroup, map,
token: t);
}
Future<List<ServiceAppointmentScheduleModel>> mergeServiceIntoAvailableSchedules({
Future<List<ServiceAppointmentScheduleModel>>
mergeServiceIntoAvailableSchedules({
required List<String> serviceItemIdsForHome,
required List<String> serviceItemIdsForWorkshop,
}) async {
@ -96,21 +128,28 @@ class AppointmentRepoImp implements AppointmentRepo {
"ServiceItemIDs": serviceItemIdsForWorkshop,
}
];
GenericRespModel adsGenericModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.GetServiceItemAppointmentScheduleSlots,
queryParameters,
token: t,
);
GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.GetServiceItemAppointmentScheduleSlots,
queryParameters,
token: t,
);
if (adsGenericModel.data == null) {
return [];
}
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel =
List.generate(adsGenericModel.data.length, (index) => ServiceAppointmentScheduleModel.fromJson(adsGenericModel.data[index], isForAppointment: true));
List.generate(
adsGenericModel.data.length,
(index) => ServiceAppointmentScheduleModel.fromJson(
adsGenericModel.data[index],
isForAppointment: true));
return serviceAppointmentScheduleModel;
}
Future<GenericRespModel> createServiceAppointment({required List<ServiceAppointmentScheduleModel> schedules, required int serviceProviderID}) async {
Future<GenericRespModel> createServiceAppointment(
{required List<ServiceAppointmentScheduleModel> schedules,
required int serviceProviderID}) async {
String t = AppState().getUser.data!.accessToken ?? "";
int customerId = AppState().getUser.data!.userInfo!.customerId ?? 0;
@ -130,18 +169,22 @@ class AppointmentRepoImp implements AppointmentRepo {
});
});
GenericRespModel adsGenericModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProvidersAppointmentCreate,
mapList,
token: t,
);
GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProvidersAppointmentCreate,
mapList,
token: t,
);
return adsGenericModel;
}
@override
Future<GenericRespModel> cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction}) async {
Future<GenericRespModel> cancelOrRescheduleServiceAppointment(
{required int serviceAppointmentID,
required int serviceSlotID,
required int appointmentScheduleAction}) async {
String t = AppState().getUser.data!.accessToken ?? "";
final payload = {
@ -150,13 +193,63 @@ class AppointmentRepoImp implements AppointmentRepo {
"appointmentScheduleAction": appointmentScheduleAction,
};
GenericRespModel adsGenericModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment,
payload,
token: t,
);
GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment,
payload,
token: t,
);
return adsGenericModel;
}
@override
Future<List<AppointmentListModel>> getMyAppointments(
Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel =
await injector.get<ApiClient>().getJsonForObject(
token: t,
(json) => GenericRespModel.fromJson(json),
queryParameters: map,
ApiConsts.serviceProvidersAppointmentGet,
);
List<AppointmentListModel> appointmentList = List.generate(
genericRespModel.data.length,
(index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList;
}
@override
Future<MResponse> getAppointmentSlots(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
MResponse adsGenericModel =
await injector.get<ApiClient>().getJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.getAppointmentSlots,
token: t,
queryParameters: map,
);
return adsGenericModel;
}
@override
Future<MResponse> updateAppointmentPaymentStatus(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateAppointmentPaymentStatus, map,
token: t);
}
@override
Future<MResponse> updateAppointmentStatus(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateAppointmentStatus, map,
token: t);
}
}

@ -1,60 +1,32 @@
import 'dart:io';
import 'package:http/io_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:signalr_netcore/http_connection_options.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:signalr_netcore/hub_connection_builder.dart';
import 'package:logging/logging.dart';
import 'package:signalr_core/signalr_core.dart';
abstract class ChatRepo {
Future<HubConnection?> buildChatHubConnection();
Future<HubConnection> getHubConnection();
}
class ChatRepoImp implements ChatRepo {
@override
Future<HubConnection?> buildChatHubConnection() async {
Future<HubConnection> getHubConnection() async {
final userId = AppState().getUser.data!.userInfo!.userId ?? "";
HttpConnectionOptions httpOptions = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
HubConnection hubConnection = HubConnectionBuilder()
final hubUrl = "https://ms.hmg.com/McHub?userID=$userId";
logger.i("Connecting with Hub ($hubUrl)");
HubConnection hub;
hub = HubConnectionBuilder()
.withUrl(
"${ApiConsts.chatHubUrl}?userID=$userId",
options: httpOptions,
)
.withAutomaticReconnect(
retryDelays: <int>[2000, 5000, 10000, 20000],
)
.configureLogging(
Logger("configureLogging"),
)
hubUrl,
HttpConnectionOptions(
client: IOClient(HttpClient()
..badCertificateCallback = (x, y, z) => true),
logging: (level, message) {
print(message);
},
))
.build();
hubConnection.onclose(
({Exception? error}) {
logger.i("onClose");
},
);
hubConnection.onreconnecting(
({Exception? error}) {
logger.i("onReconnecting");
},
);
hubConnection.onreconnected(
({String? connectionId}) {
logger.i("onReconnected");
},
);
if (hubConnection.state != HubConnectionState.Connected) {
await hubConnection.start();
logger.i("Started HubConnection");
try {
hubConnection.on("ReceiveMessageRequestOffer", (List<Object?>? arguments) {
Utils.showToast("I received ping : ${arguments.toString()}");
});
} catch (e) {
logger.i("Error in OnSendQuestionToParticipant");
}
}
return hubConnection;
return hub;
}
}

@ -4,14 +4,13 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/advertisment_models/ss_car_check_schedule_model.dart';
import 'package:mc_common_app/models/advertisment_models/ss_photo_schedule_model.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/user/cities.dart';
import 'package:mc_common_app/models/user/country.dart';
import 'package:mc_common_app/models/user/role.dart';
import '../models/advertisment_models/vehicle_details_models.dart';
import '../models/enums_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/user_models/cities.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/models/user_models/role.dart';
abstract class CommonRepo {
Future<Country> getAllCountries();
@ -25,9 +24,12 @@ abstract class CommonRepo {
Future<List<AppointmentListModel>> getMyAppointments();
Future<SSCarCheckScheduleModel> getCarCheckServiceScheduleDetails({required double lat, required double long});
Future<SSCarCheckScheduleModel> getCarCheckServiceScheduleDetails(
{required double lat, required double long});
Future<List<SSPhotoOfficeScheduleModel>> getPhotographyServiceScheduleListByOffices({required double lat, required double long});
Future<List<SSPhotoOfficeScheduleModel>>
getPhotographyServiceScheduleListByOffices(
{required double lat, required double long});
// Future<List<ProviderCategoryModel>> getProviderServiceCategories();
@ -36,9 +38,11 @@ abstract class CommonRepo {
Future<List<VehicleTypeModel>> getVehicleTypes();
//TODO: Needs to remove common methods from AD's repo and delete all repeated methods.
Future<VehicleDetailsModel> getVehicleDetails({int? vehicleTypeId, int? vehicleBrandId});
Future<VehicleDetailsModel> getVehicleDetails(
{int? vehicleTypeId, int? vehicleBrandId});
Future<List<EnumsModel>> getEnumTypeValues({int? enumTypeID, String? enumTypeName});
Future<List<EnumsModel>> getEnumTypeValues(
{int? enumTypeID, String? enumTypeName});
}
class CommonRepoImp implements CommonRepo {
@ -47,7 +51,8 @@ class CommonRepoImp implements CommonRepo {
@override
Future<Country> getAllCountries() async {
return await apiClient.getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry);
return await apiClient.getJsonForObject(
(json) => Country.fromJson(json), ApiConsts.GetAllCountry);
}
@override
@ -55,18 +60,22 @@ class CommonRepoImp implements CommonRepo {
var postParams = {
"CountryID": countryId,
};
return await apiClient.getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams);
return await apiClient.getJsonForObject(
(json) => Cities.fromJson(json), ApiConsts.GetAllCities,
queryParameters: postParams);
}
@override
Future<Role> getRoles() async {
return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles);
return await apiClient.getJsonForObject(
(json) => Role.fromJson(json), ApiConsts.GetProviderRoles);
}
@override
Future<List<AppointmentListModel>> getMyAppointments() async {
var params = {
"customerID": appState.getUser.data!.userInfo!.customerId.toString() ?? "",
"customerID":
appState.getUser.data!.userInfo!.customerId.toString() ?? "",
};
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
@ -74,12 +83,15 @@ class CommonRepoImp implements CommonRepo {
queryParameters: params,
ApiConsts.serviceProvidersAppointmentGet,
);
List<AppointmentListModel> appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
List<AppointmentListModel> appointmentList = List.generate(
genericRespModel.data.length,
(index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList;
}
@override
Future<SSCarCheckScheduleModel> getCarCheckServiceScheduleDetails({required double lat, required double long}) async {
Future<SSCarCheckScheduleModel> getCarCheckServiceScheduleDetails(
{required double lat, required double long}) async {
var params = {
"Latitude": lat.toString(),
"Longitude": long.toString(),
@ -90,12 +102,15 @@ class CommonRepoImp implements CommonRepo {
queryParameters: params,
ApiConsts.adsCarCheckupSPBranchScheduleSlotGet,
);
SSCarCheckScheduleModel ssCarCheckScheduleModel = SSCarCheckScheduleModel.fromJson(genericRespModel.data[0]);
SSCarCheckScheduleModel ssCarCheckScheduleModel =
SSCarCheckScheduleModel.fromJson(genericRespModel.data[0]);
return ssCarCheckScheduleModel;
}
@override
Future<List<SSPhotoOfficeScheduleModel>> getPhotographyServiceScheduleListByOffices({required double lat, required double long}) async {
Future<List<SSPhotoOfficeScheduleModel>>
getPhotographyServiceScheduleListByOffices(
{required double lat, required double long}) async {
var params = {
"Latitude": lat.toString(),
"Longitude": long.toString(),
@ -109,19 +124,28 @@ class CommonRepoImp implements CommonRepo {
if (genericRespModel.data == null) {
return [];
}
List<SSPhotoOfficeScheduleModel> ssPhotoScheduleModel = List.generate(genericRespModel.data.length, (index) => SSPhotoOfficeScheduleModel.fromJson(genericRespModel.data[index]));
List<SSPhotoOfficeScheduleModel> ssPhotoScheduleModel = List.generate(
genericRespModel.data.length,
(index) =>
SSPhotoOfficeScheduleModel.fromJson(genericRespModel.data[index]));
return ssPhotoScheduleModel ?? [];
}
@override
Future<List<VehicleTypeModel>> getVehicleTypes() async {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleTypeGet);
List<VehicleTypeModel> vehicleTypes = List.generate(adsGenericModel.data.length, (index) => VehicleTypeModel.fromJson(adsGenericModel.data[index]));
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleTypeGet);
List<VehicleTypeModel> vehicleTypes = List.generate(
adsGenericModel.data.length,
(index) => VehicleTypeModel.fromJson(adsGenericModel.data[index]));
return vehicleTypes;
}
@override
Future<VehicleDetailsModel> getVehicleDetails({int? vehicleTypeId, int? vehicleBrandId}) async {
Future<VehicleDetailsModel> getVehicleDetails(
{int? vehicleTypeId, int? vehicleBrandId}) async {
var postParams = {
"vehicleType": vehicleTypeId ?? 0,
"isVehicleBrand": "true",
@ -146,24 +170,35 @@ class CommonRepoImp implements CommonRepo {
postParams,
token: token,
);
VehicleDetailsModel vehicleDetails = VehicleDetailsModel.fromJson(adsGenericModel.data);
VehicleDetailsModel vehicleDetails =
VehicleDetailsModel.fromJson(adsGenericModel.data);
return vehicleDetails;
}
@override
Future<List<VehicleCityModel>> getVehicleCities({required int countryId}) async {
Future<List<VehicleCityModel>> getVehicleCities(
{required int countryId}) async {
var postParams = {
"CountryID": countryId.toString(),
};
GenericRespModel adsGenericModel =
await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCityGet, queryParameters: postParams);
List<VehicleCityModel> vehicleCities = List.generate(adsGenericModel.data.length, (index) => VehicleCityModel.fromJson(adsGenericModel.data[index]));
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleCityGet,
queryParameters: postParams);
List<VehicleCityModel> vehicleCities = List.generate(
adsGenericModel.data.length,
(index) => VehicleCityModel.fromJson(adsGenericModel.data[index]));
return vehicleCities;
}
@override
Future<List<EnumsModel>> getEnumTypeValues({int? enumTypeID, String? enumTypeName}) async {
var postParams = {"enumTypeID": (enumTypeID ?? 0).toString(), "enumTypeName": enumTypeName ?? ""};
Future<List<EnumsModel>> getEnumTypeValues(
{int? enumTypeID, String? enumTypeName}) async {
var postParams = {
"enumTypeID": (enumTypeID ?? 0).toString(),
"enumTypeName": enumTypeName ?? ""
};
GenericRespModel enumGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getEnumTypeValues,
@ -171,7 +206,8 @@ class CommonRepoImp implements CommonRepo {
token: appState.getUser.data!.accessToken,
);
List<EnumsModel> vehicleCities = List.generate(enumGenericModel.data.length, (index) => EnumsModel.fromJson(enumGenericModel.data[index]));
List<EnumsModel> vehicleCities = List.generate(enumGenericModel.data.length,
(index) => EnumsModel.fromJson(enumGenericModel.data[index]));
return vehicleCities;
}
//

@ -2,7 +2,7 @@ import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/payment_models/pay_order_detail_resp_model.dart';
abstract class PaymentsRepo {

@ -4,10 +4,10 @@ import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
abstract class ProviderRepo {
Future<List<BranchDetailModel>> getAllNearBranchAndServices();

@ -2,9 +2,9 @@ import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests/offers_model.dart';
import 'package:mc_common_app/models/requests/request_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
abstract class RequestRepo {
Future<GenericRespModel> createRequest(Map<String, dynamic> map);

@ -7,23 +7,23 @@ import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/m_response.dart';
import 'package:mc_common_app/models/user/basic_otp.dart';
import 'package:mc_common_app/models/user/change_email.dart';
import 'package:mc_common_app/models/user/change_mobile.dart';
import 'package:mc_common_app/models/user/cities.dart';
import 'package:mc_common_app/models/user/confirm_email.dart';
import 'package:mc_common_app/models/user/confirm_mobile.dart';
import 'package:mc_common_app/models/user/confirm_password.dart';
import 'package:mc_common_app/models/user/country.dart';
import 'package:mc_common_app/models/user/forget_password_otp_compare.dart';
import 'package:mc_common_app/models/user/image_response.dart';
import 'package:mc_common_app/models/user/login_password.dart';
import 'package:mc_common_app/models/user/refresh_token.dart';
import 'package:mc_common_app/models/user/register_user.dart';
import 'package:mc_common_app/models/user/role.dart';
import 'package:mc_common_app/models/user/user.dart';
import 'package:mc_common_app/models/user/verify_email.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/user_models/basic_otp.dart';
import 'package:mc_common_app/models/user_models/change_email.dart';
import 'package:mc_common_app/models/user_models/change_mobile.dart';
import 'package:mc_common_app/models/user_models/cities.dart';
import 'package:mc_common_app/models/user_models/confirm_email.dart';
import 'package:mc_common_app/models/user_models/confirm_mobile.dart';
import 'package:mc_common_app/models/user_models/confirm_password.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/models/user_models/forget_password_otp_compare.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/models/user_models/login_password.dart';
import 'package:mc_common_app/models/user_models/refresh_token.dart';
import 'package:mc_common_app/models/user_models/register_user.dart';
import 'package:mc_common_app/models/user_models/role.dart';
import 'package:mc_common_app/models/user_models/user.dart';
import 'package:mc_common_app/models/user_models/verify_email.dart';
import 'package:mc_common_app/utils/shared_prefrence.dart';
abstract class UserRepo {
@ -81,7 +81,7 @@ class UserRepoImp implements UserRepo {
String? t;
if (isNeedToPassToken) {
t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
}
return await injector.get<ApiClient>().postJsonForObject((json) => BasicOtpRespModel.fromJson(json), ApiConsts.BasicOTP, postParams, token: t);
}
@ -96,7 +96,7 @@ class UserRepoImp implements UserRepo {
String? t;
if (isNeedToPassToken) {
t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
}
return await injector.get<ApiClient>().postJsonForObject((json) => RegisterUserRespModel.fromJson(json), ApiConsts.BasicVerify, postParams, token: t);
}
@ -112,7 +112,7 @@ class UserRepoImp implements UserRepo {
String? t;
if (isNeedToPassToken) {
t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
}
return await injector.get<ApiClient>().postJsonForObject((json) => RegisterUserRespModel.fromJson(json), ApiConsts.BasicComplete, postParams, token: t);
}
@ -212,7 +212,7 @@ class UserRepoImp implements UserRepo {
// return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ChangePassword, postParams);
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ChangePassword, postParams, token: t);
}
@ -274,7 +274,7 @@ class UserRepoImp implements UserRepo {
// return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ChangePassword, postParams);
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t);
}
@ -284,7 +284,7 @@ class UserRepoImp implements UserRepo {
// return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.ChangePassword, postParams);
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t);
}

@ -149,9 +149,43 @@ enum AppointmentStatusEnum {
cancelled,
rescheduled,
allAppointments,
upcoming,
inProgress,
completed,
}
enum AppointmentPaymentStatusEnum {
notConfirmed,
payNow,
paid,
payLater,
payPartial,
}
enum RequestsTypeEnum {
specialCarRequest,
serviceRequest,
}
enum ChatMessageTypeEnum {
freeText,
image,
audio,
video,
file,
offer,
}
enum RequestOfferStatusEnum {
offer,
negotiate,
accepted,
rejected,
cancel,
}
enum ChatTypeEnum {
general,
ads,
requestOffer,
}

@ -15,10 +15,10 @@ import 'package:mc_common_app/models/advertisment_models/special_service_model.d
import 'package:mc_common_app/models/advertisment_models/ss_car_check_schedule_model.dart';
import 'package:mc_common_app/models/advertisment_models/ss_photo_schedule_model.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/models/enums_model.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/repositories/ads_repo.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/services/common_services.dart';

@ -4,14 +4,15 @@ import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/enums_model.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/repositories/appointment_repo.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/repositories/provider_repo.dart';
@ -30,20 +31,31 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import '../models/appointments_models/appointment_slots.dart';
class AppointmentsVM extends BaseVM {
final CommonRepo commonRepo;
final CommonAppServices commonServices;
final ProviderRepo providerRepo;
final AppointmentRepo scheduleRepo;
AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo});
AppointmentsVM({required this.commonServices,
required this.scheduleRepo,
required this.providerRepo,
required this.commonRepo});
bool isFetchingLists = false;
int selectedBranch = 0;
int selectedAppointmentIndex = 0;
int selectedAppointmentSubIndex = 0;
int selectedAppointmentId = 0;
List<AppointmentListModel> myAppointments = [];
List<AppointmentListModel> myUpComingAppointments = [];
List<AppointmentListModel> myFilteredAppointments = [];
List<FilterListModel> appointmentsFilterOptions = [];
List<CustomerData> customersAppointments = [];
List<AppointmentListModel> myFilteredAppointments2 = [];
// List<ScheduleData> availableSchedules = [];
@ -56,7 +68,8 @@ class AppointmentsVM extends BaseVM {
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = [];
bool ifItemAlreadySelected(int id) {
int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id);
int indexFound = allSelectedItemsInAppointments
.indexWhere((element) => element.id == id);
if (indexFound != -1) {
return true;
}
@ -65,9 +78,24 @@ class AppointmentsVM extends BaseVM {
List<ItemData> allSelectedItemsInAppointments = [];
setupProviderAppointmentFilter() {
appointmentsFilterOptions.clear();
appointmentsFilterOptions.add(
FilterListModel(id: 0, title: "All Appointments", isSelected: true));
appointmentsFilterOptions
.add(FilterListModel(id: 6, title: "Upcoming", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 3, title: "Arrived", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 7, title: "In Progress", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 8, title: "Completed", isSelected: false));
}
Future<void> onItemsSelectedInService() async {
if (currentServiceSelection != null) {
int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
int index = servicesInCurrentAppointment.indexWhere((element) =>
element.serviceId == currentServiceSelection!.serviceId!);
if (index == -1) {
double totalPrice = 0.0;
@ -88,12 +116,14 @@ class AppointmentsVM extends BaseVM {
bool isSuccess = false;
List<int> appointmentIdsList = [];
try {
GenericRespModel genericRespModel = await scheduleRepo.createServiceAppointment(
GenericRespModel genericRespModel =
await scheduleRepo.createServiceAppointment(
schedules: serviceAppointmentScheduleList,
serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0,
);
if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) {
if (genericRespModel.messageStatus == 2 ||
genericRespModel.data == null) {
Utils.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}");
return;
@ -111,13 +141,17 @@ class AppointmentsVM extends BaseVM {
}
context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked);
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.booked);
Utils.hideLoading(context);
resetAfterBookingAppointment();
if (isSuccess) {
if (amountToPayForAppointment > 0) {
context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: appointmentIdsList);
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
context
.read<PaymentVM>()
.updateAppointmentIdsForPayment(ids: appointmentIdsList);
navigateWithName(context, AppRoutes.paymentMethodsView,
arguments: PaymentTypes.appointment);
} else {
Utils.showToast("Your appointment has been booked successfully!");
getMyAppointments();
@ -129,28 +163,36 @@ class AppointmentsVM extends BaseVM {
}
}
Future<void> onConfirmAppointmentPressed({required BuildContext context, required appointmentId}) async {
context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: [appointmentId]);
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
Future<void> onConfirmAppointmentPressed(
{required BuildContext context, required appointmentId}) async {
context
.read<PaymentVM>()
.updateAppointmentIdsForPayment(ids: [appointmentId]);
navigateWithName(context, AppRoutes.paymentMethodsView,
arguments: PaymentTypes.appointment);
}
Future<void> onCancelAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async {
Future<void> onCancelAppointmentPressed({required BuildContext context,
required AppointmentListModel appointmentListModel}) async {
Utils.showLoading(context);
try {
GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment(
GenericRespModel genericRespModel =
await scheduleRepo.cancelOrRescheduleServiceAppointment(
serviceAppointmentID: appointmentListModel.id ?? 0,
serviceSlotID: appointmentListModel.serviceSlotID ?? 0,
appointmentScheduleAction: 2, // 1 for Reschedule and 2 for Cancel
);
if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) {
if (genericRespModel.messageStatus == 2 ||
genericRespModel.data == null) {
Utils.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}");
return;
}
if (genericRespModel.data == 1) {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast("${genericRespModel.message.toString()}");
await getMyAppointments();
Utils.hideLoading(context);
@ -181,7 +223,8 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel branchSelectedCategoryId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateProviderCategoryId(SelectionModel id) {
branchSelectedCategoryId = id;
@ -200,23 +243,30 @@ class AppointmentsVM extends BaseVM {
void updateBranchServiceId(SelectionModel id) async {
branchSelectedServiceId = id;
currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId);
currentServiceSelection = branchServices.firstWhere(
(element) => element.serviceProviderServiceId == id.selectedId);
notifyListeners();
}
void removeServiceInCurrentAppointment(int index) {
int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1;
allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId);
int serviceId = servicesInCurrentAppointment
.elementAt(index)
.serviceProviderServiceId ??
-1;
allSelectedItemsInAppointments.removeWhere(
(element) => element.serviceProviderServiceId == serviceId);
servicesInCurrentAppointment.removeAt(index);
notifyListeners();
}
resetCategorySelectionBottomSheet() {
selectedSubServicesCounter = 0;
branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
branchSelectedCategoryId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
currentServiceSelection = null;
}
@ -231,76 +281,222 @@ class AppointmentsVM extends BaseVM {
populateAppointmentsFilterList() async {
appointmentsFilterOptions.clear();
myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); //TODO: 13 is to get Appointments Filter Enums
myAppointmentsEnum = await commonRepo.getEnumTypeValues(
enumTypeID: 13); //TODO: 13 is to get Appointments Filter Enums
for (int i = 0; i < myAppointmentsEnum.length; i++) {
appointmentsFilterOptions.add(FilterListModel(title: myAppointmentsEnum[i].enumValueStr, isSelected: false, id: myAppointmentsEnum[i].enumValue));
appointmentsFilterOptions.add(FilterListModel(
title: myAppointmentsEnum[i].enumValueStr,
isSelected: false,
id: myAppointmentsEnum[i].enumValue));
}
appointmentsFilterOptions.insert(0, FilterListModel(title: "All Appointments", isSelected: true, id: 0));
appointmentsFilterOptions.insert(
0, FilterListModel(title: "All Appointments", isSelected: true, id: 0));
notifyListeners();
}
applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum}) {
applyFilterOnAppointmentsVM(
{required AppointmentStatusEnum appointmentStatusEnum,
bool isNeedCustomerFilter = false}) {
if (appointmentsFilterOptions.isEmpty) return;
for (var value in appointmentsFilterOptions) {
value.isSelected = false;
}
appointmentsFilterOptions[appointmentStatusEnum.getIdFromAppointmentStatusEnum()].isSelected = true;
appointmentsFilterOptions.forEach((element) {
if (element.id ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum()) {
element.isSelected = true;
}
});
// appointmentsFilterOptions[
// appointmentStatusEnum.getIdFromAppointmentStatusEnum()]
// .isSelected = true;
if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) {
myFilteredAppointments = myAppointments;
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners();
return;
}
myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList();
myFilteredAppointments = myAppointments
.where((element) =>
element.appointmentStatusID! ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum())
.toList();
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners();
}
findAppointmentsBasedOnCustomers() {
// Use a Set to ensure uniqueness of customerIDs
Set<int> uniqueCustomerIDs = Set<int>();
// Extract unique customerIDs
for (var item in myFilteredAppointments) {
uniqueCustomerIDs.add(item.customerID ?? 0);
}
// Create a list of CustomerData instances
myFilteredAppointments2 = uniqueCustomerIDs.map((id) {
List<AppointmentListModel> list = myFilteredAppointments
.where((item) => item.customerID == id)
.toList();
AppointmentListModel model = list.first;
model.customerAppointmentList = list;
return model;
}).toList();
// customersAppointments = uniqueCustomerIDs.map((id) {
// List<AppointmentListModel> list = myFilteredAppointments
// .where((item) => item.customerID == id)
// .toList();
// var customerItem =
// myFilteredAppointments.firstWhere((item) => item.customerID == id);
//
// return CustomerData(
// customerID: id,
// customerName: customerItem.customerName ?? "",
// appointmentList: list,
// );
// }).toList();
}
Future<void> getMyAppointments({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await commonRepo.getMyAppointments();
myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList();
myUpComingAppointments = myAppointments
.where((element) =>
element.appointmentStatusEnum == AppointmentStatusEnum.booked)
.toList();
setState(ViewState.idle);
// applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners();
}
AppointmentSlots? appointmentSlots;
Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map,
required BuildContext context,
bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map);
if (genericRespModel.messageStatus == 1) {
appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
Future<void> getProviderMyAppointments(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await scheduleRepo.getMyAppointments(map);
myFilteredAppointments = myAppointments;
// myUpComingAppointments = myAppointments
// .where((element) =>
// element.appointmentStatusEnum == AppointmentStatusEnum.booked)
// .toList();
setState(ViewState.idle);
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.allAppointments,
isNeedCustomerFilter: true);
notifyListeners();
}
updateSelectedBranch(BranchDetailModel branchDetailModel) {
selectedBranchModel = branchDetailModel;
getBranchCategories();
notifyListeners();
}
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) {
updateAppointmentStatus(Map<String, dynamic> map,{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("appointment status updated");
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
updateAppointmentPaymentStatus(Map<String, dynamic> map,{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("payment status updated");
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
updateSelectedAppointmentDate(
{required int dateIndex, required int scheduleIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList!) {
element.date!.isSelected = false;
}
serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.isSelected = true;
serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![dateIndex]
.date!
.isSelected = true;
serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex = dateIndex;
final date = TimeSlotModel(
date: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.date,
slotId: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.slotId,
date: serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![dateIndex]
.date!
.date,
slotId: serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![dateIndex]
.date!
.slotId,
isSelected: true,
slot: "",
);
serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date);
serviceAppointmentScheduleList[scheduleIndex]
.selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date);
notifyListeners();
}
updateSelectedAppointmentSlotByDate({required int scheduleIndex, required int slotIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) {
updateSelectedAppointmentSlotByDate(
{required int scheduleIndex, required int slotIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList!) {
for (var element in element.availableSlots!) {
element.isSelected = false;
}
}
int index = serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!;
serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots![slotIndex].isSelected = true;
serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel!.availableSlots = serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots!;
int index =
serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!;
serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![index]
.availableSlots![slotIndex]
.isSelected = true;
serviceAppointmentScheduleList[scheduleIndex]
.selectedCustomTimeDateSlotModel!
.availableSlots =
serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![index]
.availableSlots!;
notifyListeners();
}
@ -314,7 +510,9 @@ class AppointmentsVM extends BaseVM {
int selectedSubServicesCounter = 0;
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!);
// print("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
// if (serviceIndex == -1) {
// return;
@ -329,19 +527,28 @@ class AppointmentsVM extends BaseVM {
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
for (var element in allSelectedItemsInAppointments) {
if (!ifItemAlreadySelected(element.id!)) {
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 +
double.parse((serviceItemsFromApi[index].price) ?? "0.0");
}
}
}
if (!selected) {
selectedSubServicesCounter = selectedSubServicesCounter - 1;
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId);
currentServiceSelection!.serviceItems!
.removeWhere((element) => element.id == itemId);
allSelectedItemsInAppointments
.removeWhere((element) => element.id == itemId);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice -
double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex]
.serviceItems!
.removeWhere((element) => element.id == itemId);
}
notifyListeners();
}
@ -397,7 +604,8 @@ class AppointmentsVM extends BaseVM {
String pickHomeLocationError = "";
String selectSubServicesError = "";
SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
bool isCategoryAlreadyPresent(int id) {
final contain = branchCategories.where((element) => element.id == id);
@ -410,14 +618,16 @@ class AppointmentsVM extends BaseVM {
void getBranchCategories() async {
for (var value in selectedBranchModel!.branchServices!) {
if (!isCategoryAlreadyPresent(value.categoryId!)) {
branchCategories.add(DropValue(value.categoryId!, value.categoryName!, ""));
branchCategories
.add(DropValue(value.categoryId!, value.categoryName!, ""));
}
}
notifyListeners();
}
getBranchServices({required int categoryId}) async {
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
pickedHomeLocation = "";
pickHomeLocationError = "";
@ -430,7 +640,9 @@ class AppointmentsVM extends BaseVM {
}
List<ServiceModel> getFilteredBranchServices({required int categoryId}) {
List<ServiceModel> filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList();
List<ServiceModel> filteredServices = selectedBranchModel!.branchServices!
.where((element) => element.categoryId == categoryId)
.toList();
return filteredServices;
}
@ -472,7 +684,8 @@ class AppointmentsVM extends BaseVM {
return totalPrice.toString();
}
void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) {
void openTheAddServiceBottomSheet(BuildContext context,
AppointmentsVM appointmentsVM) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
@ -483,7 +696,8 @@ class AppointmentsVM extends BaseVM {
);
}
void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) {
void priceBreakDownClicked(BuildContext context,
ServiceModel selectedService) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
@ -499,19 +713,27 @@ class AppointmentsVM extends BaseVM {
Column(
children: List.generate(
selectedService.serviceItems!.length,
(index) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true),
],
),
(index) =>
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}"
.toText(
fontSize: 12,
color: MyColors.lightTextColor,
isBold: true),
"${selectedService.serviceItems![index]
.price} SAR"
.toText(fontSize: 12, isBold: true),
],
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${selectedService.currentTotalServicePrice} SAR".toText(fontSize: 16, isBold: true),
"${selectedService.currentTotalServicePrice} SAR"
.toText(fontSize: 16, isBold: true),
],
),
if (selectedService.isHomeSelected) ...[
@ -520,15 +742,20 @@ class AppointmentsVM extends BaseVM {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${totalKms}km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.rangePricePerKm} x $totalKms".toText(fontSize: 12, isBold: true),
"${totalKms}km ".toText(
fontSize: 12,
color: MyColors.lightTextColor,
isBold: true),
"${selectedService.rangePricePerKm} x $totalKms"
.toText(fontSize: 12, isBold: true),
],
),
8.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${selectedService.rangePricePerKm ?? 0 * totalKms} SAR".toText(fontSize: 16, isBold: true),
"${selectedService.rangePricePerKm ?? 0 * totalKms} SAR"
.toText(fontSize: 16, isBold: true),
],
),
],
@ -541,11 +768,18 @@ class AppointmentsVM extends BaseVM {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(selectedService.isHomeSelected
? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}"
: "${selectedService.currentTotalServicePrice}")
? "${(selectedService.currentTotalServicePrice) +
(double.parse((selectedService.rangePricePerKm ??
"0.0")) * totalKms)}"
: "${selectedService.currentTotalServicePrice}")
.toText(fontSize: 29, isBold: true),
2.width,
"SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
"SAR"
.toText(
color: MyColors.lightTextColor,
fontSize: 16,
isBold: true)
.paddingOnly(bottom: 5),
],
)
],
@ -565,7 +799,8 @@ class AppointmentsVM extends BaseVM {
isValidated = false;
break;
}
if (schedule.selectedCustomTimeDateSlotModel!.date == null || !schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) {
if (schedule.selectedCustomTimeDateSlotModel!.date == null ||
!schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) {
isValidated = false;
break;
} else {
@ -573,7 +808,9 @@ class AppointmentsVM extends BaseVM {
isValidated = false;
break;
} else {
TimeSlotModel slot = schedule.selectedCustomTimeDateSlotModel!.availableSlots!.firstWhere((element) => element.isSelected);
TimeSlotModel slot = schedule
.selectedCustomTimeDateSlotModel!.availableSlots!
.firstWhere((element) => element.isSelected);
if (slot.date.isNotEmpty) {
isValidated = true;
break;
@ -582,7 +819,8 @@ class AppointmentsVM extends BaseVM {
}
}
if (!isValidated) {
Utils.showToast("You must select appointment time for each schedule's appointment.");
Utils.showToast(
"You must select appointment time for each schedule's appointment.");
return;
}
navigateWithName(context, AppRoutes.reviewAppointmentView);
@ -601,30 +839,36 @@ class AppointmentsVM extends BaseVM {
}
}
serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceAppointmentScheduleList =
await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceItemIdsForHome: serviceItemIdsForHome,
serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
);
if (serviceAppointmentScheduleList.isEmpty) {
Utils.hideLoading(context);
Utils.showToast("There are no available appointments for selected Items.");
Utils.showToast(
"There are no available appointments for selected Items.");
return;
}
totalAmount = 0.0;
amountToPayForAppointment = 0.0;
for (var schedule in serviceAppointmentScheduleList) {
amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0);
amountToPayForAppointment =
amountToPayForAppointment + (schedule.amountToPay ?? 0.0);
totalAmount = totalAmount + (schedule.amountTotal ?? 0.0);
}
Utils.hideLoading(context);
navigateWithName(context, AppRoutes.bookAppointmenSchedulesView, arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 1, appointmentId: 0)); // 1 For Creating an Appointment
navigateWithName(context, AppRoutes.bookAppointmenSchedulesView,
arguments: ScreenArgumentsForAppointmentDetailPage(
routeFlag: 1, appointmentId: 0)); // 1 For Creating an Appointment
notifyListeners();
}
Future<void> onRescheduleAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async {
Future<void> onRescheduleAppointmentPressed({required BuildContext context,
required AppointmentListModel appointmentListModel}) async {
Utils.showLoading(context);
List<String> serviceItemIdsForHome = [];
@ -641,14 +885,16 @@ class AppointmentsVM extends BaseVM {
}
}
serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceAppointmentScheduleList =
await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceItemIdsForHome: serviceItemIdsForHome,
serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
);
if (serviceAppointmentScheduleList.isEmpty) {
Utils.hideLoading(context);
Utils.showToast("There are no available appointments for selected Items.");
Utils.showToast(
"There are no available appointments for selected Items.");
return;
}
Utils.hideLoading(context);
@ -656,29 +902,36 @@ class AppointmentsVM extends BaseVM {
navigateWithName(
context,
AppRoutes.bookAppointmenSchedulesView,
arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 2, appointmentId: appointmentListModel.id ?? 0),
arguments: ScreenArgumentsForAppointmentDetailPage(
routeFlag: 2, appointmentId: appointmentListModel.id ?? 0),
); // 2 For Rescheduling an Appointment
notifyListeners();
}
Future<void> onRescheduleAppointmentConfirmPressed({required BuildContext context, required int appointmentId, required int selectedSlotId}) async {
Future<void> onRescheduleAppointmentConfirmPressed(
{required BuildContext context,
required int appointmentId,
required int selectedSlotId}) async {
Utils.showLoading(context);
try {
GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment(
GenericRespModel genericRespModel =
await scheduleRepo.cancelOrRescheduleServiceAppointment(
serviceAppointmentID: appointmentId,
serviceSlotID: selectedSlotId,
appointmentScheduleAction: 1, // 1 for Reschedule and 2 for Cancel
);
if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) {
if (genericRespModel.messageStatus == 2 ||
genericRespModel.data == null) {
Utils.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}");
return;
}
if (genericRespModel.data == 1) {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast("${genericRespModel.message.toString()}");
getMyAppointments();
Utils.hideLoading(context);

@ -1,39 +1,141 @@
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/chat_models/cat_message_model.dart';
import 'package:mc_common_app/repositories/chat_repo.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:signalr_netcore/hub_connection.dart';
import 'package:signalr_core/signalr_core.dart';
class ChatVM extends ChangeNotifier {
class ChatVM extends ChangeNotifier {
final ChatRepo chatRepo;
ChatVM({required this.chatRepo});
HubConnection? hubConnection;
late HubConnection hubConnection;
List<ChatMessageModel> chatMessages = [];
String chatMessageText = "";
updateChatMessageText(String value) {
chatMessageText = value;
}
clearChatMessageText() {
chatMessageText = "";
notifyListeners();
}
Future<void> onNewMessageReceived({required List<ChatMessageModel> messages}) async {
chatMessages.addAll(messages);
notifyListeners();
}
Future<void> buildHubConnection() async {
hubConnection = await chatRepo.buildChatHubConnection();
// if (hubConnection.state != HubConnectionState.Connected) {
try {
hubConnection = await chatRepo.getHubConnection();
await hubConnection.start();
hubConnection.on("ReceiveMessageRequestOffer", (List<Object?>? arguments) {
if (arguments == null || arguments.isEmpty) return;
List<ChatMessageModel> chat = [];
for (var message in arguments) {
final chatMessage = ChatMessageModel.fromJson(message as Map<String, dynamic>);
chat.add(chatMessage);
}
onNewMessageReceived(messages: chat);
logger.i("I received ping : ${arguments.toString()}");
});
} catch (e) {
logger.i("Error: ${e.toString()}");
}
notifyListeners();
// }
}
Future<void> onSendMessageForRequestOffer() async {
if (hubConnection == null || hubConnection!.state != HubConnectionState.Connected) {
Future<bool> onSendMessageForRequestOffer({
required String receiverId,
required ChatMessageTypeEnum chatMessageType,
required String message,
required int requestId,
required String offerPrice,
}) async {
if (hubConnection.state != HubConnectionState.connected) {
await buildHubConnection();
}
if (hubConnection != null) {
hubConnection!.invoke(
if (hubConnection.state == HubConnectionState.connected) {
final providerId = AppState().getUser.data!.userInfo!.providerId;
hubConnection.invoke(
"SendMessageRequestOffer",
args: <Object>[
// <String, dynamic>{
// "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER ?? "",
// "employeeName": AppState().memberInformationList!.eMPLOYEENAME ?? "",
// "marathonId": AppState().getMarathonProjectId,
// "prizeId": "8577B2E8-5DD7-43F0-10DD-08DACB0AC064",
// }
<String, dynamic>{
"ReceiverUserID": receiverId,
"MessageType": chatMessageType.getIdFromChatMessageTypeEnum(),
"Message": message,
"RequestID": requestId,
"RequestOfferID": 0,
"RequestOffer": <String, dynamic>{
"RequestID": requestId,
"Price": double.parse(offerPrice),
"ServiceProviderID": providerId,
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
"Comment": message,
},
}
],
).catchError((e) {
logger.i("error in invoking SendMessageRequestOffer: ${e.toString()}");
Utils.showToast(e.toString());
return null;
return false;
});
}
return true;
}
Future<bool> onTextMessageSend({
required String receiverId,
required ChatMessageTypeEnum chatMessageType,
required String message,
required int requestId,
required String offerPrice,
}) async {
if (message.isEmpty) return false;
if (hubConnection.state != HubConnectionState.connected) {
await buildHubConnection();
}
if (hubConnection.state == HubConnectionState.connected) {
final userId = AppState().getUser.data!.userInfo!.userId.toString();
final name = AppState().getUser.data!.userInfo!.firstName.toString();
hubConnection.invoke(
"SendMessageRequestOffer",
args: <Object>[
<String, dynamic>{
"ReceiverUserID": receiverId,
"MessageType": chatMessageType.getIdFromChatMessageTypeEnum(),
"Message": message,
"RequestID": requestId,
}
],
).catchError((e) {
logger.i("error in invoking SendMessageRequestOffer: ${e.toString()}");
Utils.showToast(e.toString());
return false;
});
ChatMessageModel chatMessageModel = ChatMessageModel(
messageType: chatMessageType.getIdFromChatMessageTypeEnum(),
message: message,
isMyMessage: true,
requestID: requestId,
senderName: name,
senderUserID: userId,
);
onNewMessageReceived(messages: [chatMessageModel]);
}
return true;
}
}

@ -1,7 +1,7 @@
import 'dart:io';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/user/image_response.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/utils.dart';

@ -1,20 +1,29 @@
// ignore_for_file: use_build_context_synchronously, avoid_function_literals_in_foreach_calls
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/models/enums_model.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests/offers_model.dart';
import 'package:mc_common_app/models/requests/request_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/models/chat_models/cat_message_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/repositories/request_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:provider/provider.dart';
class RequestsVM extends BaseVM {
final CommonAppServices commonServices;
@ -33,26 +42,46 @@ class RequestsVM extends BaseVM {
populateRequestsFilterList() async {
requestsTypeFilterOptions.clear();
if (myRequestsTypeEnum.isEmpty) {
myRequestsTypeEnum = await commonRepo.getEnumTypeValues(enumTypeID: 16); //TODO: 13 is to get Requests Filter Enums
myRequestsTypeEnum = await commonRepo.getEnumTypeValues(enumTypeID: 16); //TODO: 16 is to get Requests Filter Enums
}
for (int i = 0; i < myRequestsTypeEnum.length; i++) {
requestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue));
}
log("requestsTypeFilterOptions: ${requestsTypeFilterOptions.toString()}");
notifyListeners();
}
Future<void> getMyRequests({bool isNeedToRebuild = false}) async {
Future<void> getRequests({bool isNeedToRebuild = false, required AppType appType}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myRequests = await requestRepo.getRequests(
{
"customerID": AppState().getUser.data!.userInfo!.customerId,
"pageSize": 100,
"pageIndex": 0,
"requestType": 0,
},
);
var paramsForGetRequests = <String, dynamic>{};
paramsForGetRequests = {
"pageSize": 100,
"pageIndex": 0,
"requestType": 0,
};
if (appType == AppType.provider) {
paramsForGetRequests.addEntries([MapEntry("providerID", AppState().getUser.data!.userInfo!.providerId)]);
// paramsForGetRequests = {
// "providerID": AppState().getUser.data!.userInfo!.providerId,
// "pageSize": 100,
// "pageIndex": 0,
// "requestType": 0,
// };
} else {
paramsForGetRequests.addEntries([MapEntry("customerID", AppState().getUser.data!.userInfo!.customerId)]);
// paramsForGetRequests = {
// "customerID": AppState().getUser.data!.userInfo!.customerId,
// "pageSize": 100,
// "pageIndex": 0,
// "requestType": 0,
// };
}
myRequests = await requestRepo.getRequests(paramsForGetRequests);
applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
setState(ViewState.idle);
notifyListeners();
@ -82,8 +111,8 @@ class RequestsVM extends BaseVM {
}
void pickMultipleImages() async {
List<File> Images = await commonServices.pickMultipleImages();
pickedVehicleImages.addAll(Images);
List<File> images = await commonServices.pickMultipleImages();
pickedVehicleImages.addAll(images);
if (pickedVehicleImages.isNotEmpty) vehicleImageError = "";
notifyListeners();
}
@ -252,13 +281,13 @@ class RequestsVM extends BaseVM {
if (respModel.messageStatus == 1) {
Utils.showToast("Request Successfully Created");
Navigator.pop(context);
await getMyRequests();
await getRequests(appType: AppType.customer);
} else {
Utils.showToast(respModel.message.toString());
}
} catch (e, s) {
Utils.hideLoading(context);
print(s);
log(s.toString());
}
}
}
@ -308,4 +337,97 @@ class RequestsVM extends BaseVM {
return [];
}
}
String offerPriceError = "";
String offerDescriptionError = "";
String offerPrice = "";
void updateOfferPrice(String value) {
offerPrice = value;
if (value.isNotEmpty) {
offerPriceError = "";
}
}
String offerDescription = "";
void updateOfferDescription(String value) {
offerDescription = value;
if (value.isNotEmpty) {
offerDescriptionError = "";
}
}
//SENDING OFFER
bool isSendOfferValidated() {
bool isValidated = true;
if (offerPrice.isEmpty) {
offerPriceError = GlobalConsts.demandAmountError;
isValidated = false;
notifyListeners();
} else {
offerPriceError = "";
}
if (offerDescription.isEmpty) {
offerDescriptionError = GlobalConsts.descriptionError;
isValidated = false;
notifyListeners();
} else {
offerDescriptionError = "";
}
notifyListeners();
return isValidated;
}
void resetSendOfferBottomSheet() {
offerPrice = "";
offerDescription = "";
offerDescriptionError = "";
offerDescription = "";
notifyListeners();
}
Future<void> onSendOfferPressed({
required BuildContext context,
required String receiverId,
required String message,
required int requestId,
required String offerPrice,
required RequestModel requestModel,
}) async {
if (isSendOfferValidated()) {
bool status = await context.read<ChatVM>().onSendMessageForRequestOffer(
receiverId: receiverId,
chatMessageType: ChatMessageTypeEnum.offer,
message: message,
requestId: requestId,
offerPrice: offerPrice,
);
if (status) {
final senderName = AppState().getUser.data!.userInfo!.firstName;
final senderId = AppState().getUser.data!.userInfo!.userId;
// resetSendOfferBottomSheet();
Navigator.pop(context);
ChatMessageModel chatMessageModel = ChatMessageModel(
isMyMessage: true,
message: message,
messageType: ChatMessageTypeEnum.freeText.getIdFromChatMessageTypeEnum(),
senderName: senderName,
senderUserID: senderId,
);
context.read<ChatVM>().onNewMessageReceived(messages: [chatMessageModel]);
ChatViewArguments chatViewArguments = ChatViewArguments(
chatTypeEnum: ChatTypeEnum.requestOffer,
requestModel: requestModel,
receiverId: requestModel.customerID,
senderId: senderId ?? "",
);
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
}
}
}
}

@ -8,20 +8,20 @@ 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/models/m_response.dart';
import 'package:mc_common_app/models/user/basic_otp.dart';
import 'package:mc_common_app/models/user/change_email.dart';
import 'package:mc_common_app/models/user/change_mobile.dart';
import 'package:mc_common_app/models/user/confirm_email.dart';
import 'package:mc_common_app/models/user/confirm_mobile.dart';
import 'package:mc_common_app/models/user/confirm_password.dart';
import 'package:mc_common_app/models/user/country.dart';
import 'package:mc_common_app/models/user/forget_password_otp_compare.dart';
import 'package:mc_common_app/models/user/forget_password_otp_request.dart';
import 'package:mc_common_app/models/user/login_password.dart';
import 'package:mc_common_app/models/user/register_user.dart';
import 'package:mc_common_app/models/user/user.dart';
import 'package:mc_common_app/models/user/verify_email.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/user_models/basic_otp.dart';
import 'package:mc_common_app/models/user_models/change_email.dart';
import 'package:mc_common_app/models/user_models/change_mobile.dart';
import 'package:mc_common_app/models/user_models/confirm_email.dart';
import 'package:mc_common_app/models/user_models/confirm_mobile.dart';
import 'package:mc_common_app/models/user_models/confirm_password.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/models/user_models/forget_password_otp_compare.dart';
import 'package:mc_common_app/models/user_models/forget_password_otp_request.dart';
import 'package:mc_common_app/models/user_models/login_password.dart';
import 'package:mc_common_app/models/user_models/register_user.dart';
import 'package:mc_common_app/models/user_models/user.dart';
import 'package:mc_common_app/models/user_models/verify_email.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';

@ -4,7 +4,7 @@ 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/string_extensions.dart';
import 'package:mc_common_app/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/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';

@ -3,7 +3,7 @@ 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/string_extensions.dart';
import 'package:mc_common_app/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/view_models/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';

@ -3,7 +3,7 @@ import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart';
import 'package:mc_common_app/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/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';

@ -9,7 +9,7 @@ import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/models/advertisment_models/special_service_model.dart';
import 'package:mc_common_app/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/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
@ -27,8 +27,8 @@ import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/common_widgets/time_slots.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
class AdsDetailView extends StatefulWidget {
final AdDetailsModel adDetails;
@ -892,6 +892,79 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
);
}
Future buildCancelReservationBottomSheet(BuildContext context, {required AdDetailsModel adDetails}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
title: "Cancel Reservation".toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
12.height,
TxtField(
maxLines: 5,
value: "",
errorValue: "",
keyboardType: TextInputType.text,
hint: "Reason for cancellation",
onChanged: (v) => () {},
),
],
),
25.height,
ShowFillButton(
title: "Submit",
onPressed: () {
Navigator.pop(context);
AdVM adVM = context.read<AdVM>();
return actionConfirmationBottomSheet(
context: context,
title: "Do you want to cancel the reservation?".toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: "Your ad reservation will be cancelled and this ad will be again visible to everyone to buy.",
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: "Yes",
fontSize: 15,
onPressed: () {
Navigator.pop(context);
adVM.cancelMyAdReservation(context, adId: adDetails.id!);
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: "No",
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
Navigator.pop(context);
},
),
),
);
},
maxWidth: double.infinity,
),
19.height,
],
),
));
},
);
}
Widget cancelReservationAction(BuildContext context, {required AdDetailsModel adDetails}) {
return Row(
children: [
@ -904,36 +977,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget {
maxHeight: 55,
title: "Cancel Reservation",
onPressed: () {
AdVM adVM = context.read<AdVM>();
return actionConfirmationBottomSheet(
context: context,
title: "Do you want to cancel the reservation?".toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: "Your ad reservation will be cancelled and this ad will be again visible to everyone to buy.",
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: "Yes",
fontSize: 15,
onPressed: () {
Navigator.pop(context);
adVM.cancelMyAdReservation(context, adId: adDetails.id!);
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: "No",
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
Navigator.pop(context);
},
),
),
);
buildCancelReservationBottomSheet(context, adDetails: adDetails);
}),
),
],

@ -1,7 +1,7 @@
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/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/view_models/ad_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';

@ -2,7 +2,7 @@ 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/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/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/view_models/ad_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';

@ -4,7 +4,7 @@ import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
import 'package:mc_common_app/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/utils/enums.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';

@ -3,7 +3,7 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
@ -17,9 +17,14 @@ import 'package:provider/provider.dart';
class AppointmentDetailView extends StatelessWidget {
final AppointmentListModel appointmentListModel;
AppointmentDetailView({Key? key, required this.appointmentListModel}) : super(key: key);
AppointmentDetailView({Key? key, required this.appointmentListModel})
: super(key: key);
Widget getBaseActionButtonWidget({required Color color, required String text, Color textColor = MyColors.white, required Function() onPressed}) {
Widget getBaseActionButtonWidget(
{required Color color,
required String text,
Color textColor = MyColors.white,
required Function() onPressed}) {
return Expanded(
child: ShowFillButton(
maxHeight: 55,
@ -32,19 +37,26 @@ class AppointmentDetailView extends StatelessWidget {
);
}
Widget buildBottomActionButton({required AppointmentStatusEnum appointmentStatusEnum, required BuildContext context}) {
Widget buildBottomActionButton(
{required AppointmentStatusEnum appointmentStatusEnum,
required BuildContext context}) {
switch (appointmentStatusEnum) {
case AppointmentStatusEnum.booked:
return Align(
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: "Cancel"),
getBaseActionButtonWidget(
color: MyColors.redColor,
onPressed: () => appointmentCancelConfirmationSheet(context),
text: "Cancel"),
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
onPressed: () {
context.read<AppointmentsVM>().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id);
context.read<AppointmentsVM>().onConfirmAppointmentPressed(
context: context,
appointmentId: appointmentListModel.id);
},
text: "Confirm"),
],
@ -55,7 +67,10 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: "Cancel"),
getBaseActionButtonWidget(
color: MyColors.redColor,
onPressed: () => appointmentCancelConfirmationSheet(context),
text: "Cancel"),
],
),
);
@ -64,7 +79,11 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.grey98Color.withOpacity(0.3), textColor: MyColors.lightTextColor, onPressed: () {}, text: "In Progress"),
getBaseActionButtonWidget(
color: MyColors.grey98Color.withOpacity(0.3),
textColor: MyColors.lightTextColor,
onPressed: () {},
text: "In Progress"),
],
),
);
@ -73,7 +92,11 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.grey98Color.withOpacity(0.3), textColor: MyColors.lightTextColor, onPressed: () {}, text: "Cancelled"),
getBaseActionButtonWidget(
color: MyColors.grey98Color.withOpacity(0.3),
textColor: MyColors.lightTextColor,
onPressed: () {},
text: "Cancelled"),
],
),
);
@ -84,17 +107,24 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: "Cancel"),
getBaseActionButtonWidget(
color: MyColors.redColor,
onPressed: () => appointmentCancelConfirmationSheet(context),
text: "Cancel"),
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
onPressed: () {
context.read<AppointmentsVM>().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id);
context.read<AppointmentsVM>().onConfirmAppointmentPressed(
context: context,
appointmentId: appointmentListModel.id);
},
text: "Confirm"),
],
),
);
default:
return SizedBox();
}
}
@ -102,8 +132,10 @@ class AppointmentDetailView extends StatelessWidget {
final appointmentsVm = context.read<AppointmentsVM>();
return actionConfirmationBottomSheet(
context: context,
title: "Do you want to cancel this appointment?".toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: "Your appointment will be cancelled and you cannot undo this action.",
title: "Do you want to cancel this appointment?"
.toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle:
"Your appointment will be cancelled and you cannot undo this action.",
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
@ -111,7 +143,8 @@ class AppointmentDetailView extends StatelessWidget {
fontSize: 15,
onPressed: () {
Navigator.pop(context);
appointmentsVm.onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
appointmentsVm.onCancelAppointmentPressed(
context: context, appointmentListModel: appointmentListModel);
},
),
),
@ -149,7 +182,8 @@ class AppointmentDetailView extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
appointmentListModel.providerName!.toText(fontSize: 16, isBold: true),
appointmentListModel.providerName!
.toText(fontSize: 16, isBold: true),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@ -159,14 +193,23 @@ class AppointmentDetailView extends StatelessWidget {
fit: BoxFit.fill,
),
5.width,
"${appointmentListModel.duration ?? ""} ${appointmentListModel.appointmentDate!.toFormattedDateWithoutTime()}".toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor),
"${appointmentListModel.duration ?? ""} ${appointmentListModel.appointmentDate!.toFormattedDateWithoutTime()}"
.toText(
fontSize: 12,
isBold: true,
color: MyColors.lightTextColor),
],
),
13.height,
if (appointmentListModel.appointmentServicesList != null && appointmentListModel.appointmentServicesList!.isNotEmpty) ...[
if (appointmentListModel.appointmentServicesList != null &&
appointmentListModel
.appointmentServicesList!.isNotEmpty) ...[
Column(
children: List.generate(appointmentListModel.appointmentServicesList!.length, (index) {
ServiceModel service = appointmentListModel.appointmentServicesList![index];
children: List.generate(
appointmentListModel.appointmentServicesList!.length,
(index) {
ServiceModel service =
appointmentListModel.appointmentServicesList![index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -178,14 +221,18 @@ class AppointmentDetailView extends StatelessWidget {
// fit: BoxFit.fill,
// ),
// 10.width,
"${index + 1}. ${service.providerServiceDescription}".toText(fontSize: 14, isBold: true),
"${index + 1}. ${service.providerServiceDescription}"
.toText(fontSize: 14, isBold: true),
],
),
if (service.serviceItems != null && service.serviceItems!.isNotEmpty) ...[
if (service.serviceItems != null &&
service.serviceItems!.isNotEmpty) ...[
Column(
children: List.generate(
service.serviceItems!.length,
(index) => "${service.serviceItems![index].name}".toText(
(index) =>
"${service.serviceItems![index].name}"
.toText(
textAlign: TextAlign.start,
fontSize: 12,
color: MyColors.lightTextColor,
@ -197,15 +244,22 @@ class AppointmentDetailView extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
((service.currentTotalServicePrice).toString()).toText(fontSize: 25, isBold: true),
((service.currentTotalServicePrice).toString())
.toText(fontSize: 25, isBold: true),
2.width,
"SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
"SAR"
.toText(
color: MyColors.lightTextColor,
fontSize: 16,
isBold: true)
.paddingOnly(bottom: 5),
Icon(
Icons.arrow_drop_down,
size: 30,
)
],
).onPress(() => appointmentsVM.priceBreakDownClicked(context, service)),
).onPress(() => appointmentsVM.priceBreakDownClicked(
context, service)),
],
);
}),
@ -217,16 +271,25 @@ class AppointmentDetailView extends StatelessWidget {
CardButtonWithIcon(
title: "Reschedule Appointment",
onCardTapped: () {
context.read<AppointmentsVM>().onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
context
.read<AppointmentsVM>()
.onRescheduleAppointmentPressed(
context: context,
appointmentListModel: appointmentListModel);
},
icon: MyAssets.scheduleAppointmentIcon.buildSvg(),
),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked) ...[
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.booked) ...[
10.width,
CardButtonWithIcon(
title: "Pay for Appointment",
onCardTapped: () {
context.read<AppointmentsVM>().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id);
context
.read<AppointmentsVM>()
.onConfirmAppointmentPressed(
context: context,
appointmentId: appointmentListModel.id);
},
icon: MyAssets.creditCardIcon.buildSvg(),
),
@ -236,7 +299,10 @@ class AppointmentDetailView extends StatelessWidget {
15.height,
],
).toWhiteContainer(width: double.infinity, allPading: 12),
buildBottomActionButton(appointmentStatusEnum: appointmentListModel.appointmentStatusEnum!, context: context),
buildBottomActionButton(
appointmentStatusEnum:
appointmentListModel.appointmentStatusEnum!,
context: context),
],
),
),

@ -1,9 +1,8 @@
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/string_extensions.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/appointments/widgets/custom_calender_widget.dart';

@ -1,8 +1,8 @@
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/models/services/item_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/advertisement/custom_add_button.dart';

@ -3,7 +3,7 @@ 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/string_extensions.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';

@ -5,9 +5,9 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/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/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/service_schedule_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';

@ -0,0 +1,266 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/chat_models/cat_message_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class ChatView extends StatelessWidget {
final ChatViewArguments chatViewArguments;
const ChatView({super.key, required this.chatViewArguments});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomAppBar(title: "Chat"),
body: Consumer<ChatVM>(builder: (BuildContext context, ChatVM chatVM, Widget? child) {
return Column(
children: [
Expanded(
child: ListView.separated(
itemCount: chatVM.chatMessages.length,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatVM.chatMessages[index];
return ChatMessageCustomWidget(
isSent: chatMessageModel.isMyMessage ?? false,
profileUrl: MyAssets.bnCar,
messageText: "${chatMessageModel.message}",
messageTypeEnum: chatMessageModel.messageTypeEnum ?? ChatMessageTypeEnum.freeText,
requestOfferStatusEnum:
(chatMessageModel.requestOffer != null ? chatMessageModel.requestOffer!.requestOfferStatusEnum : RequestOfferStatusEnum.offer) ?? RequestOfferStatusEnum.offer,
senderName: "${chatMessageModel.senderName}",
);
}).horPaddingMain(),
),
10.width,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 7,
child: TxtField(
value: chatVM.chatMessageText,
hint: "Type your message here..",
keyboardType: TextInputType.text,
isNeedBorder: false,
onChanged: (v) => chatVM.updateChatMessageText(v),
),
),
Expanded(
flex: 1,
child: const Icon(
Icons.send_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() async {
final status = await chatVM.onTextMessageSend(
receiverId: chatViewArguments.receiverId,
message: chatVM.chatMessageText,
requestId: chatViewArguments.chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArguments.requestModel!.id : 0,
offerPrice: "0.0",
chatMessageType: ChatMessageTypeEnum.freeText,
);
if (status) {
chatVM.clearChatMessageText();
}
},
),
)
],
).toContainer(isShadowEnabled: true),
],
);
}),
// body:
);
}
}
class ChatMessageCustomWidget extends StatelessWidget {
final String profileUrl;
final String senderName;
final String messageText;
final ChatMessageTypeEnum messageTypeEnum;
final RequestOfferStatusEnum requestOfferStatusEnum;
final bool isSent;
const ChatMessageCustomWidget({
super.key,
required this.profileUrl,
required this.senderName,
required this.messageText,
required this.messageTypeEnum,
this.requestOfferStatusEnum = RequestOfferStatusEnum.offer,
required this.isSent,
});
Widget buildOfferDetailsInChatMessage({required RequestOfferStatusEnum requestOfferStatusEnum}) {
switch (requestOfferStatusEnum) {
case RequestOfferStatusEnum.offer:
return Column(
children: [
5.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"40000".toText(fontSize: 19, isBold: true),
2.width,
"SAR".toText(color: MyColors.lightTextColor, height: 2.2, fontSize: 10, isBold: true),
],
),
10.height,
Row(
children: [
Expanded(
child: ShowFillButton(
maxHeight: 27,
title: "Accept",
fontSize: 9,
borderColor: MyColors.greenColor,
isFilled: false,
onPressed: () {},
backgroundColor: MyColors.white,
txtColor: MyColors.greenColor,
),
),
20.width,
Expanded(
child: ShowFillButton(
maxHeight: 27,
title: "Reject",
borderColor: MyColors.redColor,
isFilled: false,
onPressed: () {},
backgroundColor: MyColors.white,
txtColor: MyColors.redColor,
fontSize: 9,
),
)
],
),
],
);
case RequestOfferStatusEnum.negotiate:
return Column(
children: [
Center(
child: "You asked for the new offer.".toText(
color: MyColors.adPendingStatusColor,
fontSize: 12,
isItalic: true,
),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.accepted:
return Column(
children: [
Center(
child: "You have accepted the offer.".toText(
color: MyColors.adPendingStatusColor,
fontSize: 12,
isItalic: true,
),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.rejected:
return Column(
children: [
Center(
child: "You have rejected the offer.".toText(
color: MyColors.adPendingStatusColor,
fontSize: 12,
isItalic: true,
),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.cancel:
return Column(
children: [
Center(
child: "You have cancelled the offer.".toText(
color: MyColors.adPendingStatusColor,
fontSize: 12,
isItalic: true,
),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
}
}
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: isSent ? TextDirection.rtl : TextDirection.ltr,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Image.asset(
profileUrl,
width: 34,
height: 34,
fit: BoxFit.fill,
).toCircle(borderRadius: 100),
),
10.width,
Expanded(
flex: 10,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(isSent ? "You" : senderName).toText(fontSize: 16, isBold: true),
],
),
5.height,
Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: messageText.toText(
color: isSent ? MyColors.white : MyColors.lightTextColor,
fontSize: 12,
// isBold: true,
),
),
],
),
if (messageTypeEnum == ChatMessageTypeEnum.offer) ...[
buildOfferDetailsInChatMessage(requestOfferStatusEnum: requestOfferStatusEnum),
],
],
).toContainer(
isShadowEnabled: !isSent,
backgroundColor: isSent ? MyColors.darkIconColor : MyColors.white,
borderRadius: 0,
margin: EdgeInsets.fromLTRB(isSent ? 25 : 0, 0, !isSent ? 25 : 0, 0),
),
],
),
)
],
),
);
}
}

@ -3,7 +3,7 @@ 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/string_extensions.dart';
import 'package:mc_common_app/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/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';
import 'package:mc_common_app/views/advertisement/picked_images_container.dart';

@ -1,27 +1,32 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/requests/offers_model.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
class OfferListPage extends StatelessWidget {
final List<OffersModel> offersList;
final OfferListPageArguments offerListPageArguments;
OfferListPage({required this.offersList});
const OfferListPage({super.key, required this.offerListPageArguments});
@override
Widget build(BuildContext context) {
final List<OffersModel> offersList = offerListPageArguments.offersList;
return Scaffold(
appBar: CustomAppBar(title: "Offers"),
appBar: const CustomAppBar(title: "Offers"),
body: offersList.isEmpty
? Center(child: "No Requests to show.".toText(fontSize: 16, color: MyColors.lightTextColor))
: ListView.separated(
itemCount: offersList.length,
padding: EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
OffersModel offersModel = offersList[index];
return Stack(
@ -33,7 +38,7 @@ class OfferListPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${offersModel.serviceProvider!.companyName ?? ""}".toText(fontSize: 16, isBold: true),
(offersModel.serviceProvider!.companyName ?? "").toText(fontSize: 16, isBold: true),
//Un read offers count
@ -70,14 +75,20 @@ class OfferListPage extends StatelessWidget {
),
],
),
Icon(
const Icon(
Icons.arrow_forward,
color: MyColors.darkIconColor,
size: 18,
),
],
).onPress(() {
navigateWithName(context, AppRoutes.chatView);
log("here: ${offersModel.serviceProvider!.providerGUID}");
ChatViewArguments chatViewArguments = ChatViewArguments(
chatTypeEnum: ChatTypeEnum.requestOffer,
receiverId: "${offersModel.serviceProvider!.providerGUID}",
senderId: AppState().getUser.data!.userInfo!.userId.toString(),
requestModel: offerListPageArguments.requestModel);
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
}).toContainer(isShadowEnabled: true);
},
separatorBuilder: (context, index) => 16.height,

@ -1,10 +1,13 @@
// ignore_for_file: use_build_context_synchronously
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/requests/offers_model.dart';
import 'package:mc_common_app/models/requests/request_model.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
@ -13,8 +16,9 @@ import 'package:provider/provider.dart';
class RequestItem extends StatelessWidget {
final RequestModel request;
final AppType appType;
RequestItem({required this.request});
const RequestItem({super.key, required this.request, required this.appType});
@override
Widget build(BuildContext context) {
@ -32,7 +36,7 @@ class RequestItem extends StatelessWidget {
6.height,
"${request.brand} ${request.model}".toText(fontSize: 16, isBold: true),
showItem("Model:", "${request.year}"),
showItem("Customer Name:", "${request.customerName}"),
showItem("Customer Name:", request.customerName),
],
),
),
@ -91,7 +95,7 @@ class RequestItem extends StatelessWidget {
),
],
),
Icon(
const Icon(
Icons.arrow_forward,
color: MyColors.darkIconColor,
size: 18,
@ -100,8 +104,13 @@ class RequestItem extends StatelessWidget {
),
],
).toContainer(isShadowEnabled: true).onPress(() async {
List<OffersModel> offers = await context.read<RequestsVM>().getOffersByRequest(requestId: request.id, context: context);
navigateWithName(context, AppRoutes.offersListPage, arguments: offers);
if (appType == AppType.provider) {
navigateWithName(context, AppRoutes.requestsDetailPage, arguments: request);
} else {
List<OffersModel> offers = await context.read<RequestsVM>().getOffersByRequest(requestId: request.id, context: context);
OfferListPageArguments offerListPageArguments = OfferListPageArguments(offersList: offers, requestModel: request);
navigateWithName(context, AppRoutes.offersListPage, arguments: offerListPageArguments);
}
});
}

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/requests/request_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';

@ -2,7 +2,7 @@ import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/user/register_user.dart';
import 'package:mc_common_app/models/user_models/register_user.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';

@ -1,5 +1,5 @@
import 'dart:async';
import 'package:mc_common_app/models/user/country.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';

@ -7,7 +7,7 @@ import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/user/country.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save