From 01d9ad68a25300700f84802a2ae4bbd02d6ab092 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 31 Dec 2023 14:27:48 +0300 Subject: [PATCH] Chat Implementation 1.0 --- assets/icons/whatsapp_icon.svg | 1 + lib/classes/consts.dart | 4 + lib/config/routes.dart | 15 +- lib/extensions/string_extensions.dart | 1 + .../chat_models/chat_message_model.dart | 13 +- .../provider_offers_model.dart | 2 +- lib/models/requests_models/request_model.dart | 6 + lib/repositories/chat_repo.dart | 40 ++- lib/view_models/appointments_view_model.dart | 322 +++++------------- lib/view_models/chat_view_model.dart | 87 +++-- lib/view_models/requests_view_model.dart | 29 +- lib/views/advertisement/ads_detail_view.dart | 17 +- .../appointments/appointment_detail_view.dart | 155 +++------ lib/views/chat/chat_view.dart | 221 ++++++++---- lib/views/requests/offer_list_page.dart | 13 +- .../setting_options_invite_friends.dart | 17 - lib/views/user/login_with_password_page.dart | 2 +- pubspec.lock | 102 ++---- 18 files changed, 482 insertions(+), 565 deletions(-) create mode 100644 assets/icons/whatsapp_icon.svg diff --git a/assets/icons/whatsapp_icon.svg b/assets/icons/whatsapp_icon.svg new file mode 100644 index 0000000..1fd7154 --- /dev/null +++ b/assets/icons/whatsapp_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 6d64cc1..6f660cd 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -260,6 +260,10 @@ class MyAssets { static String tamaraArPng = "${assetPath}icons/payments/tamara_ar.png"; static String tamaraEngPng = "${assetPath}icons/payments/tamara_en.png"; static String visaPng = "${assetPath}icons/payments/visa.png"; + + + + static String whatsAppIcon = "${assetPath}icons/whatsapp_icon.svg"; } RegExp numReg = RegExp(r".*[0-9].*"); diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 11f3232..30ea3a5 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -117,12 +117,19 @@ class ChatViewArguments { final String receiverId; final int providerIndex; final int requestIndex; - - ChatViewArguments({required this.chatTypeEnum, this.requestId, required this.senderId, required this.receiverId, required this.providerIndex, required this.requestIndex}); + final RequestModel? requestModel; + + ChatViewArguments({ + required this.chatTypeEnum, + this.requestId, + required this.senderId, + required this.receiverId, + required this.providerIndex, + required this.requestIndex, + this.requestModel, + }); } - - class OfferListPageArguments { final List serviceProviderOffers; final int? requestId; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 3431a3f..56b722e 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -28,6 +28,7 @@ extension EmailValidator on String { decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none, + fontSize: fontSize ?? 10, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600, color: color ?? MyColors.darkTextColor, diff --git a/lib/models/chat_models/chat_message_model.dart b/lib/models/chat_models/chat_message_model.dart index 4121541..a9d3f6c 100644 --- a/lib/models/chat_models/chat_message_model.dart +++ b/lib/models/chat_models/chat_message_model.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + 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'; @@ -35,8 +37,13 @@ class ChatMessageModel { this.isMyMessage, }); + @override + String toString() { + return 'ChatMessageModel{id: $id, senderUserID: $senderUserID, senderName: $senderName, messageType: $messageType, chatMessageTypeEnum: $chatMessageTypeEnum, chatText: $chatText, requestID: $requestID, reqOfferID: $reqOfferID, serviceProviderID: $serviceProviderID, offerStatus: $offerStatus, reqOffer: $reqOffer, isRead: $isRead, readOn: $readOn, isMyMessage: $isMyMessage}'; + } + ChatMessageModel.fromJson(Map json) { - final myUserId = AppState().getUser.data!.userInfo!.userId.toString(); + final myUserId = AppState().getUser.data!.userInfo!.userId.toString().toUpperCase(); id = json['id']; senderUserID = json['senderUserID']; senderName = json['senderName']; @@ -50,7 +57,8 @@ class ChatMessageModel { reqOffer = json['reqOffer'] != null ? ReqOffer.fromJson(json['reqOffer']) : null; isRead = json['isRead']; readOn = json['readOn']; - isMyMessage = (json['senderUserId']).toString() == myUserId; + isMyMessage = (json['senderUserID']).toString().toUpperCase()== myUserId; + } } @@ -76,6 +84,7 @@ class ReqOffer { }); ReqOffer.fromJson(Map json) { + log("the json: $json"); id = json['id']; requestID = json['requestID']; serviceProviderID = json['serviceProviderID']; diff --git a/lib/models/requests_models/provider_offers_model.dart b/lib/models/requests_models/provider_offers_model.dart index 2b68877..8c2cd3b 100644 --- a/lib/models/requests_models/provider_offers_model.dart +++ b/lib/models/requests_models/provider_offers_model.dart @@ -65,7 +65,7 @@ class ServiceProvidersOffers { ServiceProvidersOffers({this.providerId, this.name, this.mobileNo, this.email, this.companyName, this.offerCount, this.chatMessages, this.providerUserId}); ServiceProvidersOffers.fromJson(Map json) { - providerId = json['providerId']; + providerId = json['providerID']; providerUserId = json['providerUserId'] ?? "c680271c-b2a7-4ecf-7e95-08db545aec1b"; //TODO Remove this when parameter is added in backend name = json['name']; mobileNo = json['mobileNo']; diff --git a/lib/models/requests_models/request_model.dart b/lib/models/requests_models/request_model.dart index aedb089..68e12c2 100644 --- a/lib/models/requests_models/request_model.dart +++ b/lib/models/requests_models/request_model.dart @@ -16,6 +16,8 @@ class RequestModel { int offerCount; int id; int customerId; + bool isChatted; + String customerUserID; dynamic customer; String brand; String model; @@ -51,6 +53,8 @@ class RequestModel { required this.offerCount, required this.id, required this.customerId, + required this.isChatted, + required this.customerUserID, required this.customer, required this.brand, required this.model, @@ -88,6 +92,8 @@ class RequestModel { offerCount: json["offerCount"], id: json["id"], customerId: json["customerID"], + isChatted: json["isChatted"], + customerUserID: json["customerUserID"], customer: json["customer"], brand: json["brand"], model: json["model"], diff --git a/lib/repositories/chat_repo.dart b/lib/repositories/chat_repo.dart index 66f18e1..0e7f442 100644 --- a/lib/repositories/chat_repo.dart +++ b/lib/repositories/chat_repo.dart @@ -15,7 +15,7 @@ abstract class ChatRepo { Future markMessageAsRead({required int messageId}); - Future> getUsersChatMessages({required int providerId, required int requestOfferId, int pageIndex = 0, int pageSize = 0}); + Future> getUsersChatMessages({required int providerId, required int customerId, required int requestOfferId, required int requestId, int pageIndex = 0, int pageSize = 0}); } class ChatRepoImp implements ChatRepo { @@ -31,13 +31,14 @@ class ChatRepoImp implements ChatRepo { HubConnection hub; hub = HubConnectionBuilder() .withUrl( - hubUrl, - HttpConnectionOptions( - client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true), - logging: (level, message) { - log(message); - }, - )) + hubUrl, + HttpConnectionOptions( + client: IOClient(HttpClient() + ..badCertificateCallback = (x, y, z) => true), + logging: (level, message) { + log(message); + }, + )) .build(); return hub; } @@ -48,7 +49,7 @@ class ChatRepoImp implements ChatRepo { "id": messageId.toString(), }; await apiClient.postJsonForObject( - (json) => GenericRespModel.fromJson(json), + (json) => GenericRespModel.fromJson(json), ApiConsts.messageIsReadUpdate, queryParameters, token: appState.getUser.data!.accessToken, @@ -56,24 +57,29 @@ class ChatRepoImp implements ChatRepo { } @override - Future> getUsersChatMessages({required int providerId, required int requestOfferId, int pageIndex = 0, int pageSize = 0}) async { + Future> getUsersChatMessages( + {required int providerId, required int customerId, required int requestOfferId, required int requestId, int pageIndex = 0, int pageSize = 0}) async { var queryParameters = { "ReqOfferID": requestOfferId.toString(), + "RequestID": requestId.toString(), "ProviderID": providerId.toString(), + "CustomerID": customerId.toString(), "PageSize": pageSize.toString(), "PageIndex": pageIndex.toString(), }; GenericRespModel genericRespModel = await apiClient.getJsonForObject( - (json) => GenericRespModel.fromJson(json), + (json) => GenericRespModel.fromJson(json), ApiConsts.getChatMessages, queryParameters: queryParameters, token: appState.getUser.data!.accessToken, ); - - List chatMessages = List.generate( - genericRespModel.data.length, - (index) => ChatMessageModel.fromJson(genericRespModel.data[index]), - ); - return chatMessages; + if (genericRespModel.messageStatus == 1 && genericRespModel.data != null) { + List chatMessages = List.generate( + genericRespModel.data.length, + (index) => ChatMessageModel.fromJson(genericRespModel.data[index]), + ); + return chatMessages; + } + return []; } } diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index 2a9fb1b..95be75d 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -39,10 +39,7 @@ class AppointmentsVM extends BaseVM { 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; @@ -68,8 +65,7 @@ class AppointmentsVM extends BaseVM { List 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; } @@ -80,22 +76,16 @@ class AppointmentsVM extends BaseVM { 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)); + 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 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; @@ -116,14 +106,12 @@ class AppointmentsVM extends BaseVM { bool isSuccess = false; List 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; @@ -141,17 +129,13 @@ class AppointmentsVM extends BaseVM { } context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.booked); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked); Utils.hideLoading(context); resetAfterBookingAppointment(); if (isSuccess) { if (amountToPayForAppointment > 0) { - context - .read() - .updateAppointmentIdsForPayment(ids: appointmentIdsList); - navigateWithName(context, AppRoutes.paymentMethodsView, - arguments: PaymentTypes.appointment); + context.read().updateAppointmentIdsForPayment(ids: appointmentIdsList); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); } else { Utils.showToast("Your appointment has been booked successfully!"); getMyAppointments(); @@ -163,36 +147,28 @@ class AppointmentsVM extends BaseVM { } } - Future onConfirmAppointmentPressed( - {required BuildContext context, required appointmentId}) async { - context - .read() - .updateAppointmentIdsForPayment(ids: [appointmentId]); - navigateWithName(context, AppRoutes.paymentMethodsView, - arguments: PaymentTypes.appointment); + Future onConfirmAppointmentPressed({required BuildContext context, required appointmentId}) async { + context.read().updateAppointmentIdsForPayment(ids: [appointmentId]); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); } - Future onCancelAppointmentPressed({required BuildContext context, - required AppointmentListModel appointmentListModel}) async { + Future 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().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.cancelled); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast("${genericRespModel.message.toString()}"); await getMyAppointments(); Utils.hideLoading(context); @@ -223,8 +199,7 @@ 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; @@ -243,30 +218,23 @@ 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; } @@ -281,32 +249,24 @@ 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, - bool isNeedCustomerFilter = false}) { + applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { if (appointmentsFilterOptions.isEmpty) return; for (var value in appointmentsFilterOptions) { value.isSelected = false; } appointmentsFilterOptions.forEach((element) { - if (element.id == - appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { + if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { element.isSelected = true; } }); @@ -321,11 +281,7 @@ class AppointmentsVM extends BaseVM { return; } - myFilteredAppointments = myAppointments - .where((element) => - element.appointmentStatusID! == - appointmentStatusEnum.getIdFromAppointmentStatusEnum()) - .toList(); + myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList(); if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(); notifyListeners(); } @@ -341,9 +297,7 @@ class AppointmentsVM extends BaseVM { // Create a list of CustomerData instances myFilteredAppointments2 = uniqueCustomerIDs.map((id) { - List list = myFilteredAppointments - .where((item) => item.customerID == id) - .toList(); + List list = myFilteredAppointments.where((item) => item.customerID == id).toList(); AppointmentListModel model = list.first; model.customerAppointmentList = list; return model; @@ -368,10 +322,7 @@ class AppointmentsVM extends BaseVM { myAppointments = await commonRepo.getMyAppointments(); myFilteredAppointments = myAppointments; - myUpComingAppointments = myAppointments - .where((element) => - element.appointmentStatusEnum == AppointmentStatusEnum.booked) - .toList(); + myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList(); setState(ViewState.idle); // applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); notifyListeners(); @@ -379,9 +330,7 @@ class AppointmentsVM extends BaseVM { AppointmentSlots? appointmentSlots; - Future getAppointmentSlotsInfo({required Map map, - required BuildContext context, - bool isNeedToRebuild = false}) async { + Future getAppointmentSlotsInfo({required Map map, required BuildContext context, bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map); @@ -395,8 +344,7 @@ class AppointmentsVM extends BaseVM { } } - Future getProviderMyAppointments(Map map, - {bool isNeedToRebuild = false}) async { + Future getProviderMyAppointments(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); myAppointments = await scheduleRepo.getMyAppointments(map); @@ -406,9 +354,7 @@ class AppointmentsVM extends BaseVM { // element.appointmentStatusEnum == AppointmentStatusEnum.booked) // .toList(); setState(ViewState.idle); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.allAppointments, - isNeedCustomerFilter: true); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); notifyListeners(); } @@ -418,10 +364,10 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - updateAppointmentStatus(Map map,{bool isNeedToRebuild = false}) async { + updateAppointmentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map); + MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("appointment status updated"); @@ -433,10 +379,10 @@ class AppointmentsVM extends BaseVM { } } - updateAppointmentPaymentStatus(Map map,{bool isNeedToRebuild = false}) async { + updateAppointmentPaymentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map); + MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("payment status updated"); @@ -448,55 +394,32 @@ class AppointmentsVM extends BaseVM { } } - updateSelectedAppointmentDate( - {required int dateIndex, required int scheduleIndex}) { - for (var element in serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList!) { + 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(); } @@ -510,9 +433,7 @@ 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; @@ -527,28 +448,19 @@ 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(); } @@ -604,8 +516,7 @@ 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); @@ -618,16 +529,14 @@ 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 = ""; @@ -640,9 +549,7 @@ class AppointmentsVM extends BaseVM { } List getFilteredBranchServices({required int categoryId}) { - List filteredServices = selectedBranchModel!.branchServices! - .where((element) => element.categoryId == categoryId) - .toList(); + List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList(); return filteredServices; } @@ -684,8 +591,7 @@ class AppointmentsVM extends BaseVM { return totalPrice.toString(); } - void openTheAddServiceBottomSheet(BuildContext context, - AppointmentsVM appointmentsVM) { + void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -696,8 +602,7 @@ class AppointmentsVM extends BaseVM { ); } - void priceBreakDownClicked(BuildContext context, - ServiceModel selectedService) { + void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -713,27 +618,19 @@ 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) ...[ @@ -742,20 +639,15 @@ 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), ], ), ], @@ -768,18 +660,11 @@ 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), ], ) ], @@ -799,8 +684,7 @@ 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 { @@ -808,9 +692,7 @@ 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; @@ -819,8 +701,7 @@ 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); @@ -839,36 +720,30 @@ 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 onRescheduleAppointmentPressed({required BuildContext context, - required AppointmentListModel appointmentListModel}) async { + Future onRescheduleAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async { Utils.showLoading(context); List serviceItemIdsForHome = []; @@ -885,16 +760,14 @@ 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); @@ -902,36 +775,29 @@ 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 onRescheduleAppointmentConfirmPressed( - {required BuildContext context, - required int appointmentId, - required int selectedSlotId}) async { + Future 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().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.cancelled); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast("${genericRespModel.message.toString()}"); getMyAppointments(); Utils.hideLoading(context); diff --git a/lib/view_models/chat_view_model.dart b/lib/view_models/chat_view_model.dart index fa8273c..d3be4c2 100644 --- a/lib/view_models/chat_view_model.dart +++ b/lib/view_models/chat_view_model.dart @@ -24,7 +24,7 @@ class ChatVM extends ChangeNotifier { ChatVM({required this.chatRepo, required this.requestRepo}); - late HubConnection hubConnection; + HubConnection? hubConnection; String chatMessageText = ""; @@ -105,7 +105,9 @@ class ChatVM extends ChangeNotifier { } } else { for (var msg in messages) { - int providerIndex = context.read().myFilteredRequests.indexWhere((element) => element.customerID == msg.senderUserID); + int providerIndex = context.read().myFilteredRequests.indexWhere((element) => element.customerUserID == msg.senderUserID); + log("here is it: ${msg.senderUserID}"); + log("here is it: ${context.read().myFilteredRequests.first.customerUserID.toString()}"); if (providerIndex != -1) { context.read().addChatMessagesInRequestsModel(msg: msg, index: providerIndex); } @@ -116,26 +118,26 @@ class ChatVM extends ChangeNotifier { } Future buildHubConnection(BuildContext context) async { - // if (hubConnection.state != HubConnectionState.Connected) { - try { - hubConnection = await chatRepo.getHubConnection(); - await hubConnection.start(); - hubConnection.on("ReceiveMessageRequestOffer", (List? arguments) { - if (arguments == null || arguments.isEmpty) return; - List chat = []; - for (var message in arguments) { - final chatMessage = ChatMessageModel.fromJson(message as Map); - chat.add(chatMessage); - } - onNewMessageReceived(messages: chat, context: context); - logger.i("I received ping : ${arguments.toString()}"); - }); - } catch (e) { - logger.i("Error: ${e.toString()}"); - } + if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) { + try { + hubConnection = await chatRepo.getHubConnection(); + await hubConnection!.start(); + hubConnection!.on("ReceiveMessageRequestOffer", (List? arguments) { + if (arguments == null || arguments.isEmpty) return; + List chat = []; + for (var message in arguments) { + final chatMessage = ChatMessageModel.fromJson(message as Map); + chat.add(chatMessage); + } + onNewMessageReceived(messages: chat, context: context); + logger.i("I received ping : ${arguments.toString()}"); + }); + } catch (e) { + logger.i("Error: ${e.toString()}"); + } - notifyListeners(); - // } + notifyListeners(); + } } Future onSendMessageForRequestOffer({ @@ -146,12 +148,12 @@ class ChatVM extends ChangeNotifier { required String offerPrice, required BuildContext context, }) async { - if (hubConnection.state != HubConnectionState.connected) { + if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) { await buildHubConnection(context); } - if (hubConnection.state == HubConnectionState.connected) { + if (hubConnection!.state == HubConnectionState.connected) { final providerId = AppState().getUser.data!.userInfo!.providerId; - hubConnection.invoke( + hubConnection!.invoke( "SendMessageRequestOffer", args: [ { @@ -188,21 +190,19 @@ class ChatVM extends ChangeNotifier { }) async { if (message.isEmpty) return false; - if (hubConnection.state != HubConnectionState.connected) { + if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) { await buildHubConnection(context); } - if (hubConnection.state == HubConnectionState.connected) { + if (hubConnection!.state == HubConnectionState.connected) { final userId = AppState().getUser.data!.userInfo!.userId.toString(); final name = AppState().getUser.data!.userInfo!.firstName.toString(); - log("here the sender: $userId"); - log("here the receiver: $receiverId"); - - hubConnection.invoke( + hubConnection!.invoke( "SendMessageRequestOffer", args: [ { "ReceiverUserID": receiverId, + "SenderUserID": userId, "MessageType": chatMessageType.getIdFromChatMessageTypeEnum(), "ChatText": message, "RequestID": requestId, @@ -229,13 +229,14 @@ class ChatVM extends ChangeNotifier { serviceProviderOffersList[providerIndex].chatMessages!.add(chatMessageModel); } } else { - int providerIndex = context.read().myFilteredRequests.indexWhere((element) => element.customerID == userId); + int providerIndex = context.read().myFilteredRequests.indexWhere((element) => element.customerID == receiverId); if (providerIndex != -1) { context.read().addChatMessagesInRequestsModel(msg: chatMessageModel, index: providerIndex); } } + return true; } - return true; + return false; } List serviceProviderOffersList = []; @@ -255,10 +256,17 @@ class ChatVM extends ChangeNotifier { } } - Future getUsersChatMessagesForCustomer({required BuildContext context, required int providerId, required int requestOfferId, required int providerOfferIndex}) async { + Future getUsersChatMessagesForCustomer({ + required BuildContext context, + required int providerId, + required int requestOfferId, + required int requestId, + required int providerOfferIndex, + }) async { try { + int customerId = AppState().getUser.data!.userInfo!.customerId!; Utils.showLoading(context); - List chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, requestOfferId: requestOfferId); + List chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, customerId: customerId, requestOfferId: requestOfferId, requestId: requestId); serviceProviderOffersList[providerOfferIndex].chatMessages = chatMessages; Utils.hideLoading(context); notifyListeners(); @@ -269,10 +277,17 @@ class ChatVM extends ChangeNotifier { } } - Future getUsersChatMessagesForProvider({required BuildContext context, required int providerId, required int requestOfferId, required int customerRequestIndex}) async { + Future getUsersChatMessagesForProvider({ + required BuildContext context, + required int customerId, + required int requestOfferId, + required int requestId, + required int customerRequestIndex, + }) async { try { + int providerId = AppState().getUser.data!.userInfo!.providerId!; Utils.showLoading(context); - List chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, requestOfferId: requestOfferId); + List chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, customerId: customerId, requestOfferId: requestOfferId, requestId: requestId); context.read().overwriteChatMessagesInRequestsModel(messages: chatMessages, index: customerRequestIndex); Utils.hideLoading(context); } catch (e) { diff --git a/lib/view_models/requests_view_model.dart b/lib/view_models/requests_view_model.dart index 4ee5cab..616a17b 100644 --- a/lib/view_models/requests_view_model.dart +++ b/lib/view_models/requests_view_model.dart @@ -241,7 +241,8 @@ class RequestsVM extends BaseVM { } //Request Management - String price = "", description = ""; + String price = "", + description = ""; updatePrice(String v) { price = v; @@ -254,7 +255,9 @@ class RequestsVM extends BaseVM { Future convertFileToRequestPostingImages({required File file}) async { List imageBytes = await file.readAsBytes(); String image = base64Encode(imageBytes); - String fileName = file.path.split('/').last; + String fileName = file.path + .split('/') + .last; VehiclePostingImages vehiclePostingImages = VehiclePostingImages( imageName: fileName, imageStr: image, @@ -409,6 +412,7 @@ class RequestsVM extends BaseVM { required String offerPrice, required RequestModel requestModel, required int requestIndex, + required bool isFromChatScreen, }) async { if (isSendOfferValidated()) { final chatVM = context.read(); @@ -421,6 +425,7 @@ class RequestsVM extends BaseVM { context: context, ); + if (status) { final senderName = AppState().getUser.data!.userInfo!.firstName; final senderId = AppState().getUser.data!.userInfo!.userId; @@ -434,15 +439,17 @@ class RequestsVM extends BaseVM { senderUserID: senderId, ); context.read().onNewMessageReceived(messages: [chatMessageModel], context: context); - ChatViewArguments chatViewArguments = ChatViewArguments( - chatTypeEnum: ChatTypeEnum.requestOffer, - requestId: requestModel.id, - receiverId: requestModel.customerID, - senderId: senderId ?? "", - requestIndex: requestIndex, - providerIndex: -1, - ); - navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments); + if (!isFromChatScreen) { + ChatViewArguments chatViewArguments = ChatViewArguments( + chatTypeEnum: ChatTypeEnum.requestOffer, + requestId: requestModel.id, + receiverId: requestModel.customerID, + senderId: senderId ?? "", + requestIndex: requestIndex, + providerIndex: -1, + ); + navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments); + } } } } diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 9a955cf..8b609a0 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -434,20 +434,19 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { }, ), ), - if (adDetailsModel.whatsAppNo != null) ...[ + if (adDetailsModel.whatsAppNo != null && adDetailsModel.whatsAppNo!.isNotEmpty) ...[ 8.width, Container( - height: 55, - width: 55, - alignment: Alignment.center, - decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), - //TODO: It Will be replaced by a WhatsApp Icon - child: const Icon(Icons.message, color: MyColors.black), + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + child: MyAssets.whatsAppIcon.buildSvg() ).onPress(() { Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? ""); }), ], - if (adDetailsModel.phoneNo != null) ...[ + if (adDetailsModel.phoneNo != null && adDetailsModel.phoneNo!.isNotEmpty) ...[ 8.width, Container( height: 55, @@ -490,7 +489,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { alignment: Alignment.center, decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), //TODO: It Will be replaced by a WhatsApp Icon - child: const Icon(Icons.message, color: MyColors.black), + child: MyAssets.whatsAppIcon.buildSvg() ).onPress(() { Utils.openNumberViaWhatsApp(phoneNumber: adDetailsModel.whatsAppNo ?? ""); }), diff --git a/lib/views/appointments/appointment_detail_view.dart b/lib/views/appointments/appointment_detail_view.dart index 1d5f297..9069e4b 100644 --- a/lib/views/appointments/appointment_detail_view.dart +++ b/lib/views/appointments/appointment_detail_view.dart @@ -17,14 +17,9 @@ import 'package:provider/provider.dart'; class AppointmentDetailView extends StatelessWidget { final AppointmentListModel appointmentListModel; - AppointmentDetailView({Key? key, required this.appointmentListModel}) - : super(key: key); + const 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, @@ -37,26 +32,47 @@ class AppointmentDetailView extends StatelessWidget { ); } - Widget buildBottomActionButton( - {required AppointmentStatusEnum appointmentStatusEnum, - required BuildContext context}) { + Widget getArrivedBottomActionButton({required BuildContext context, required AppointmentPaymentStatusEnum appointmentPaymentStatusEnum}) { + switch (appointmentPaymentStatusEnum) { + case AppointmentPaymentStatusEnum.notConfirmed: + case AppointmentPaymentStatusEnum.paid: + case AppointmentPaymentStatusEnum.payLater: + case AppointmentPaymentStatusEnum.payPartial: + return Align( + alignment: Alignment.bottomCenter, + child: Row( + children: [ + getBaseActionButtonWidget(color: MyColors.grey98Color.withOpacity(0.3), textColor: MyColors.lightTextColor, onPressed: () {}, text: "In Progress"), + ], + ), + ); + case AppointmentPaymentStatusEnum.payNow: + return Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Pay Now", + onPressed: () {}, + backgroundColor: MyColors.darkPrimaryColor, + txtColor: MyColors.white, + fontSize: 18, + ), + ); + } + } + + 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().onConfirmAppointmentPressed( - context: context, - appointmentId: appointmentListModel.id); + context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, text: "Confirm"), ], @@ -67,36 +83,18 @@ 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"), ], ), ); case AppointmentStatusEnum.arrived: - return Align( - alignment: Alignment.bottomCenter, - child: Row( - children: [ - getBaseActionButtonWidget( - color: MyColors.grey98Color.withOpacity(0.3), - textColor: MyColors.lightTextColor, - onPressed: () {}, - text: "In Progress"), - ], - ), - ); + return getArrivedBottomActionButton(appointmentPaymentStatusEnum: appointmentListModel.appointmentPaymentStatusEnum ?? AppointmentPaymentStatusEnum.notConfirmed, context: context); case AppointmentStatusEnum.cancelled: return Align( 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"), ], ), ); @@ -107,17 +105,12 @@ 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().onConfirmAppointmentPressed( - context: context, - appointmentId: appointmentListModel.id); + context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, text: "Confirm"), ], @@ -132,10 +125,8 @@ class AppointmentDetailView extends StatelessWidget { final appointmentsVm = context.read(); 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, @@ -143,8 +134,7 @@ class AppointmentDetailView extends StatelessWidget { fontSize: 15, onPressed: () { Navigator.pop(context); - appointmentsVm.onCancelAppointmentPressed( - context: context, appointmentListModel: appointmentListModel); + appointmentsVm.onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel); }, ), ), @@ -182,8 +172,7 @@ 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: [ @@ -193,23 +182,14 @@ 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: [ @@ -221,18 +201,14 @@ 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, @@ -244,22 +220,15 @@ 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)), ], ); }), @@ -271,25 +240,16 @@ class AppointmentDetailView extends StatelessWidget { CardButtonWithIcon( title: "Reschedule Appointment", onCardTapped: () { - context - .read() - .onRescheduleAppointmentPressed( - context: context, - appointmentListModel: appointmentListModel); + context.read().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() - .onConfirmAppointmentPressed( - context: context, - appointmentId: appointmentListModel.id); + context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, icon: MyAssets.creditCardIcon.buildSvg(), ), @@ -299,10 +259,7 @@ class AppointmentDetailView extends StatelessWidget { 15.height, ], ).toWhiteContainer(width: double.infinity, allPading: 12), - buildBottomActionButton( - appointmentStatusEnum: - appointmentListModel.appointmentStatusEnum!, - context: context), + buildBottomActionButton(appointmentStatusEnum: appointmentListModel.appointmentStatusEnum!, context: context), ], ), ), diff --git a/lib/views/chat/chat_view.dart b/lib/views/chat/chat_view.dart index 1b07641..a27b0d3 100644 --- a/lib/views/chat/chat_view.dart +++ b/lib/views/chat/chat_view.dart @@ -7,6 +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/models/chat_models/chat_message_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/view_models/chat_view_model.dart'; @@ -24,6 +25,69 @@ class ChatView extends StatelessWidget { const ChatView({super.key, required this.chatViewArguments}); + Future buildSendOfferBottomSheet(BuildContext context) { + RequestModel requestDetail = chatViewArguments.requestModel!; + return showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { + return InfoBottomSheet( + title: "Make an offer".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( + value: requestsVM.offerPrice, + errorValue: requestsVM.offerPriceError, + keyboardType: TextInputType.number, + hint: "Enter amount", + onChanged: (v) => requestsVM.updateOfferPrice(v), + ), + 12.height, + TxtField( + maxLines: 5, + value: requestsVM.offerDescription, + errorValue: requestsVM.offerDescriptionError, + keyboardType: TextInputType.text, + hint: "Description", + onChanged: (v) => requestsVM.updateOfferDescription(v), + ), + ], + ), + 25.height, + ShowFillButton( + title: "Submit", + onPressed: () { + requestsVM.onSendOfferPressed( + context: context, + receiverId: requestDetail.customerID, + message: requestsVM.offerDescription, + requestId: requestDetail.id, + offerPrice: requestsVM.offerPrice, + requestModel: requestDetail, + requestIndex: chatViewArguments.requestIndex, + isFromChatScreen: true, + ); + }, + maxWidth: double.infinity, + ), + 19.height, + ], + ), + )); + }); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -38,19 +102,34 @@ class ChatView extends StatelessWidget { children: [ Expanded( child: ListView.separated( - itemCount: chatMessages.length, - separatorBuilder: (BuildContext context, int index) => 20.height, - itemBuilder: (BuildContext context, int index) { - ChatMessageModel chatMessageModel = chatMessages[index]; - return ChatMessageCustomWidget(chatMessageModel: chatMessageModel); - }).horPaddingMain(), + itemCount: chatMessages.length, + separatorBuilder: (BuildContext context, int index) => 20.height, + itemBuilder: (BuildContext context, int index) { + ChatMessageModel chatMessageModel = chatMessages[index]; + return ChatMessageCustomWidget(chatMessageModel: chatMessageModel); + }, + ).horPaddingMain(), ), - 10.width, + 10.height, Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (AppState().currentAppType == AppType.provider) ...[ + Expanded( + flex: 1, + child: const Icon( + Icons.local_offer_rounded, + color: MyColors.darkPrimaryColor, + size: 30, + ).onPress( + () async { + buildSendOfferBottomSheet(context); + }, + ), + ), + ], Expanded( - flex: 7, + flex: 8, child: TxtField( value: chatVM.chatMessageText, hint: "Type your message here..", @@ -67,6 +146,7 @@ class ChatView extends StatelessWidget { size: 30, ).onPress( () async { + log("chatViewArguments.receiverId:${chatViewArguments.receiverId}"); final status = await chatVM.onTextMessageSend( context: context, receiverId: chatViewArguments.receiverId, @@ -164,6 +244,7 @@ class _ChatMessageCustomWidgetState extends State { Widget buildOfferDetailsInChatMessage({required ChatMessageModel chatMessageModel, required BuildContext context}) { final requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum ?? RequestOfferStatusEnum.offer; + switch (requestOfferStatusEnum) { case RequestOfferStatusEnum.offer: return Column( @@ -172,75 +253,66 @@ class _ChatMessageCustomWidgetState extends State { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - chatMessageModel.reqOffer!.price.toString().toText(fontSize: 19, isBold: true), - 2.width, + "${chatMessageModel.reqOffer!.price}".toText(fontSize: 19, isBold: true, color: MyColors.white), + 5.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: () async { - log("message: ${chatMessageModel.reqOfferID}"); - int status = await context.read().onActionOfferTapped( - context: context, - requestOfferStatusEnum: RequestOfferStatusEnum.accepted, - reqOfferId: chatMessageModel.reqOfferID ?? -1, - ); + if (widget.chatMessageModel.isMyMessage == false) ...[ + 10.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 27, + title: "Accept", + fontSize: 9, + borderColor: MyColors.greenColor, + isFilled: false, + onPressed: () async { + int status = await context.read().onActionOfferTapped( + context: context, + requestOfferStatusEnum: RequestOfferStatusEnum.accepted, + reqOfferId: chatMessageModel.reqOfferID ?? -1, + ); - if (status != -1) { - log("accepted: $status"); - if (chatMessageModel.reqOfferID == status) { - chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted; - setState(() {}); + if (status != -1) { + log("accepted: $status"); + if (chatMessageModel.reqOfferID == status) { + chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted; + setState(() {}); + } } - } - }, - backgroundColor: MyColors.white, - txtColor: MyColors.greenColor, - ), - ), - 20.width, - Expanded( - child: ShowFillButton( - maxHeight: 27, - title: "Reject", - borderColor: MyColors.redColor, - isFilled: false, - backgroundColor: MyColors.white, - txtColor: MyColors.redColor, - fontSize: 9, - onPressed: () async { - buildRejectOfferBottomSheet(); - // int status = - // await context.read().onActionOfferTapped(context: context, requestOfferStatusEnum: RequestOfferStatusEnum.rejected, reqOfferId: chatMessageModel.reqOfferID ?? -1); - // - // if (status != -1) { - // log("rejected: $status"); - // if (chatMessageModel.reqOfferID == status) { - // chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.rejected; - // setState(() {}); - // } - // } - }, + }, + backgroundColor: MyColors.white, + txtColor: MyColors.greenColor, + ), ), - ) - ], - ), + 20.width, + Expanded( + child: ShowFillButton( + maxHeight: 27, + title: "Reject", + borderColor: MyColors.redColor, + isFilled: false, + backgroundColor: MyColors.white, + txtColor: MyColors.redColor, + fontSize: 9, + onPressed: () async { + buildRejectOfferBottomSheet(); + }, + ), + ) + ], + ), + ], ], ); case RequestOfferStatusEnum.negotiate: return Column( children: [ Center( - child: "You asked for the new offer.".toText( + child: "New Offer Required.".toText( color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true, @@ -252,7 +324,7 @@ class _ChatMessageCustomWidgetState extends State { return Column( children: [ Center( - child: "You have accepted the offer.".toText( + child: "Offer has been accepted.".toText( color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true, @@ -264,7 +336,7 @@ class _ChatMessageCustomWidgetState extends State { return Column( children: [ Center( - child: "You have rejected the offer.".toText( + child: "Offer has been rejected.".toText( color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true, @@ -276,7 +348,7 @@ class _ChatMessageCustomWidgetState extends State { return Column( children: [ Center( - child: "You have cancelled the offer.".toText( + child: "Offer has been cancelled.".toText( color: MyColors.adPendingStatusColor, fontSize: 12, isItalic: true, @@ -291,6 +363,7 @@ class _ChatMessageCustomWidgetState extends State { Widget build(BuildContext context) { return Directionality( textDirection: (widget.chatMessageModel.isMyMessage ?? false) ? TextDirection.rtl : TextDirection.ltr, + // textDirection: (widget.chatMessageModel.isMyMessage ?? false) ? TextDirection.rtl : TextDirection.ltr, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -322,10 +395,14 @@ class _ChatMessageCustomWidgetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: (widget.chatMessageModel.chatText ?? "").toText( - color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor, - fontSize: 12, - // isBold: true, + child: Directionality( + textDirection: TextDirection.ltr, + child: (widget.chatMessageModel.chatText ?? "").toText( + color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor, + + fontSize: 12, + // isBold: true, + ), ), ), ], diff --git a/lib/views/requests/offer_list_page.dart b/lib/views/requests/offer_list_page.dart index 43badc3..6b4652b 100644 --- a/lib/views/requests/offer_list_page.dart +++ b/lib/views/requests/offer_list_page.dart @@ -1,9 +1,12 @@ +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_models/provider_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/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -88,7 +91,15 @@ class OfferListPage extends StatelessWidget { final chatVM = context.read(); - await chatVM.getUsersChatMessagesForCustomer(context: context, providerId: offersModel.providerId ?? 0, requestOfferId: 0, providerOfferIndex: index).whenComplete( + await chatVM + .getUsersChatMessagesForCustomer( + context: context, + providerId: offersModel.providerId ?? 0, + requestOfferId: 0, + requestId: offerListPageArguments.requestId ?? 0, + providerOfferIndex: index, + ) + .whenComplete( () => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments), ); }).toContainer(isShadowEnabled: true); diff --git a/lib/views/setting_options/setting_options_invite_friends.dart b/lib/views/setting_options/setting_options_invite_friends.dart index 645ad34..91dfea3 100644 --- a/lib/views/setting_options/setting_options_invite_friends.dart +++ b/lib/views/setting_options/setting_options_invite_friends.dart @@ -34,26 +34,9 @@ class SettingOptionsInviteFriends extends StatelessWidget { CustomSettingOptionsTile(leadingWidget: const Icon(Icons.person, size: 20), titleText: "Account", onTap: () {}), ], ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), borderRadius: 0), - CustomSettingOptionsTile(leadingWidget: const Icon(Icons.translate, size: 20), titleText: "Language", isForLanguage: true, onTap: () {}) - .toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, marginAll: 21, borderRadius: 0), ], ), ), - Row( - children: [ - Expanded( - child: ShowFillButton( - borderColor: MyColors.redColor, - txtColor: MyColors.redColor, - isFilled: false, - fontSize: 16, - maxHeight: 55, - title: "Log Out", - onPressed: () {}, - ), - ), - ], - ).paddingAll(21), ], ), ); diff --git a/lib/views/user/login_with_password_page.dart b/lib/views/user/login_with_password_page.dart index 65a6a85..8b6c525 100644 --- a/lib/views/user/login_with_password_page.dart +++ b/lib/views/user/login_with_password_page.dart @@ -33,7 +33,7 @@ class _LoginWithPasswordState extends State { ClassType type = ClassType.EMAIL; //TODO: ONLY FOR DEVELOPMENT PURPOSE - String phoneNum = "966504278212", password = "Fa@123"; + String phoneNum = "966504278213", password = "Fa@1234"; String email = ""; String countryCode = ""; Country? _country; diff --git a/pubspec.lock b/pubspec.lock index e1d8bbd..e8ace14 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" country_code_picker: dependency: "direct main" description: @@ -513,10 +513,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.18.0" js: dependency: transitive description: @@ -601,34 +601,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" - message_pack_dart: - dependency: transitive - description: - name: message_pack_dart - sha256: "71b9f0ff60e5896e60b337960bb535380d7dba3297b457ac763ccae807385b59" - url: "https://pub.dev" - source: hosted - version: "2.0.1" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" mime: dependency: transitive description: @@ -725,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.7" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c + url: "https://pub.dev" + source: hosted + version: "4.2.3" permission_handler: dependency: "direct main" description: @@ -789,14 +789,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.6" - pool: - dependency: transitive - description: - name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" - source: hosted - version: "1.5.1" provider: dependency: "direct main" description: @@ -877,14 +869,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.dev" - source: hosted - version: "1.4.1" shimmer: dependency: "direct main" description: @@ -893,14 +877,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - signalr_netcore: + signalr_core: dependency: "direct main" description: - name: signalr_netcore - sha256: "8f84b4b516c03f3a6872f94e9729d1441d5d223a77c81d0a7d7dae5dd0ce1f2f" + name: signalr_core + sha256: dca676372a00c051511591ed0e24521ff7aa4e9320a7fa778a1007f7f522c8c0 url: "https://pub.dev" source: hosted - version: "1.3.6" + version: "1.1.1" simple_gesture_detector: dependency: transitive description: @@ -926,10 +910,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" sqflite: dependency: transitive description: @@ -946,38 +930,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.0" - sse: + sse_client: dependency: transitive description: - name: sse - sha256: "3ff9088cac3f45aa8b91336f1962e3ea6c81baaba0bbba361c05f8aa7fb59442" + name: sse_client + sha256: "71bd826430b41ab20a69d85bf2dfe9f11cfe222938e681ada1aea71fc8adf348" url: "https://pub.dev" source: hosted - version: "4.1.2" - sse_channel: - dependency: transitive - description: - name: sse_channel - sha256: ba2b1382b9423c58fa83e1f01a3a40fbaa16a0594aa984870c88bad0b45d4ca4 - url: "https://pub.dev" - source: hosted - version: "0.0.3" + version: "0.1.0" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -1022,10 +998,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.5.1" tuple: dependency: transitive description: @@ -1130,14 +1106,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1171,5 +1139,5 @@ packages: source: hosted version: "6.3.0" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0"