Merge branch 'mirza_development'

# Conflicts:
#	lib/view_models/appointments_view_model.dart
mirza_development
Mirza.Shafique@cloudsolutions.com.sa 2 years ago
commit a7ba63d281

@ -108,6 +108,7 @@ class ApiConsts {
static String getAppointmentSlots = "${baseUrlServices}api/ServiceProviders/ScheduleSlotsInfo_Get"; static String getAppointmentSlots = "${baseUrlServices}api/ServiceProviders/ScheduleSlotsInfo_Get";
static String updateAppointmentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentStatus_Update"; static String updateAppointmentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentStatus_Update";
static String updateAppointmentPaymentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointmentServiceItemPaymentStatus_Update"; static String updateAppointmentPaymentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointmentServiceItemPaymentStatus_Update";
static String createMergeAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderMergeAppointment_Create";
//Subscription //Subscription
static String getAllSubscriptions = "${baseUrlServices}api/Common/Subscription_Get"; static String getAllSubscriptions = "${baseUrlServices}api/Common/Subscription_Get";

@ -232,10 +232,10 @@ extension AppointmentStatusToInt on AppointmentStatusEnum {
case AppointmentStatusEnum.upcoming: case AppointmentStatusEnum.upcoming:
return 6; return 6;
case AppointmentStatusEnum.inProgress: case AppointmentStatusEnum.workStarted:
return 7; return 7;
case AppointmentStatusEnum.completed: case AppointmentStatusEnum.visitCompleted:
return 8; return 8;
default: default:
@ -244,7 +244,41 @@ extension AppointmentStatusToInt on AppointmentStatusEnum {
} }
} }
extension AppointmentStatusToString on AppointmentStatusEnum {
String getAppointmentNameFromEnum() {
switch (this) {
case AppointmentStatusEnum.booked:
return "Booked";
case AppointmentStatusEnum.confirmed:
return "Confirmed";
case AppointmentStatusEnum.arrived:
return "Arrived";
case AppointmentStatusEnum.cancelled:
return "Canceled";
case AppointmentStatusEnum.rescheduled:
return "Rescheduled";
case AppointmentStatusEnum.upcoming:
return "Upcoming";
case AppointmentStatusEnum.workStarted:
return "Work Started";
case AppointmentStatusEnum.visitCompleted:
return "Visit Completed";
default:
return "Booked";
}
}
}
//TODO: Need to verify Enum on upcoming and inprogress with the database //TODO: Need to verify Enum on upcoming and inprogress with the database
//TODO: 6 is service Deactivated
extension AppointmentEnum on int { extension AppointmentEnum on int {
AppointmentStatusEnum toAppointmentStatusEnum() { AppointmentStatusEnum toAppointmentStatusEnum() {
if (this == 1) { if (this == 1) {
@ -260,9 +294,9 @@ extension AppointmentEnum on int {
} else if (this == 6) { } else if (this == 6) {
return AppointmentStatusEnum.upcoming; return AppointmentStatusEnum.upcoming;
} else if (this == 7) { } else if (this == 7) {
return AppointmentStatusEnum.inProgress; return AppointmentStatusEnum.workStarted;
} else if (this == 8) { } else if (this == 8) {
return AppointmentStatusEnum.completed; return AppointmentStatusEnum.visitCompleted;
} else { } else {
return AppointmentStatusEnum.allAppointments; return AppointmentStatusEnum.allAppointments;
} }
@ -272,7 +306,7 @@ extension AppointmentEnum on int {
extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum { extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
int getIdFromAppointmentPaymentStatusEnum() { int getIdFromAppointmentPaymentStatusEnum() {
switch (this) { switch (this) {
case AppointmentPaymentStatusEnum.notConfirmed: case AppointmentPaymentStatusEnum.defaultStatus:
return 1; return 1;
case AppointmentPaymentStatusEnum.payNow: case AppointmentPaymentStatusEnum.payNow:
@ -296,7 +330,7 @@ extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
extension AppointmentPaymentEnum on int { extension AppointmentPaymentEnum on int {
AppointmentPaymentStatusEnum toAppointmentPaymentStatusEnum() { AppointmentPaymentStatusEnum toAppointmentPaymentStatusEnum() {
if (this == 1) { if (this == 1) {
return AppointmentPaymentStatusEnum.notConfirmed; return AppointmentPaymentStatusEnum.defaultStatus;
} else if (this == 2) { } else if (this == 2) {
return AppointmentPaymentStatusEnum.payNow; return AppointmentPaymentStatusEnum.payNow;
} else if (this == 3) { } else if (this == 3) {
@ -306,7 +340,7 @@ extension AppointmentPaymentEnum on int {
} else if (this == 5) { } else if (this == 5) {
return AppointmentPaymentStatusEnum.payPartial; return AppointmentPaymentStatusEnum.payPartial;
} else { } else {
return AppointmentPaymentStatusEnum.notConfirmed; return AppointmentPaymentStatusEnum.defaultStatus;
} }
} }
} }

@ -24,35 +24,38 @@ class AppointmentListModel {
int? servicePaymentStatus; int? servicePaymentStatus;
double? totalAmount; double? totalAmount;
double? remainingAmount; double? remainingAmount;
bool? isSelected;
bool? isMerged;
AppointmentStatusEnum? appointmentStatusEnum; AppointmentStatusEnum? appointmentStatusEnum;
AppointmentPaymentStatusEnum? appointmentPaymentStatusEnum; AppointmentPaymentStatusEnum? appointmentPaymentStatusEnum;
List<ServiceModel>? appointmentServicesList; List<ServiceModel>? appointmentServicesList;
List<AppointmentListModel>? customerAppointmentList; List<AppointmentListModel>? customerAppointmentList;
List<MergeAppointmentList>? mergeAppointmentList;
AppointmentListModel( AppointmentListModel({this.id,
{this.id, this.serviceSlotID,
this.serviceSlotID, this.appointmentStatusID,
this.appointmentStatusID, this.appointmentStatusText,
this.appointmentStatusText, this.serviceProviderID,
this.serviceProviderID, this.customerID,
this.customerID, this.isActive,
this.isActive, this.isPaymentRequired,
this.isPaymentRequired, this.paymentStatus,
this.paymentStatus, this.paymentStatusText,
this.paymentStatusText, this.customerName,
this.customerName, this.customerMobileNum,
this.customerMobileNum, this.appointmentType,
this.appointmentType, this.providerName,
this.providerName, this.duration,
this.duration, this.branchName,
this.branchName, this.branchId,
this.branchId, this.servicePaymentStatus,
this.servicePaymentStatus, this.totalAmount,
this.totalAmount, this.remainingAmount,
this.remainingAmount, this.isSelected,
this.appointmentDate, this.appointmentDate,
this.appointmentServicesList, this.appointmentServicesList,
this.customerAppointmentList}); this.customerAppointmentList, this.mergeAppointmentList,});
@override @override
String toString() { String toString() {
@ -81,6 +84,7 @@ class AppointmentListModel {
servicePaymentStatus = json['servicePaymentStatus']; servicePaymentStatus = json['servicePaymentStatus'];
totalAmount = json['amountTotal']; totalAmount = json['amountTotal'];
remainingAmount = json['amountRem']; remainingAmount = json['amountRem'];
isSelected = false;
appointmentStatusEnum = appointmentStatusEnum =
(json['appointmentStatusID'] as int).toAppointmentStatusEnum(); (json['appointmentStatusID'] as int).toAppointmentStatusEnum();
appointmentPaymentStatusEnum = appointmentPaymentStatusEnum =
@ -93,6 +97,10 @@ class AppointmentListModel {
.add(ServiceModel.fromJson(v, isForAppointment: true)); .add(ServiceModel.fromJson(v, isForAppointment: true));
}); });
} }
mergeAppointmentList =
json["mergeAppointmentList"] == null ? [] : List<MergeAppointmentList>.from(
json["mergeAppointmentList"]!.map((x) =>
MergeAppointmentList.fromJson(x)));
} }
} }
@ -102,11 +110,10 @@ class ServiceAppointmentItems {
String? serviceItemName; String? serviceItemName;
String? serviceItemDescription; String? serviceItemDescription;
ServiceAppointmentItems( ServiceAppointmentItems({this.id,
{this.id, this.serviceItemID,
this.serviceItemID, this.serviceItemName,
this.serviceItemName, this.serviceItemDescription});
this.serviceItemDescription});
ServiceAppointmentItems.fromJson(Map<String, dynamic> json) { ServiceAppointmentItems.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
@ -131,8 +138,34 @@ class CustomerData {
final String customerName; final String customerName;
final List<AppointmentListModel> appointmentList; final List<AppointmentListModel> appointmentList;
CustomerData( CustomerData({required this.customerID,
{required this.customerID, required this.customerName,
required this.customerName, required this.appointmentList});
required this.appointmentList});
} }
class MergeAppointmentList {
int? id;
int? mergeAppointmentId;
int? serviceAppointmentId;
MergeAppointmentList({
this.id,
this.mergeAppointmentId,
this.serviceAppointmentId,
});
factory MergeAppointmentList.fromJson(Map<String, dynamic> json) =>
MergeAppointmentList(
id: json["id"],
mergeAppointmentId: json["mergeAppointmentID"],
serviceAppointmentId: json["serviceAppointmentID"],
);
Map<String, dynamic> toJson() =>
{
"id": id,
"mergeAppointmentID": mergeAppointmentId,
"serviceAppointmentID": serviceAppointmentId,
};
}

@ -17,14 +17,14 @@ abstract class AppointmentRepo {
Future<List<AppointmentListModel>> getMyAppointments( Future<List<AppointmentListModel>> getMyAppointments(
Map<String, dynamic> map); Map<String, dynamic> map);
Future<MResponse> updateAppointmentStatus( Future<MResponse> updateAppointmentStatus(Map<String, dynamic> map);
Map<String, dynamic> map);
Future<MResponse> updateAppointmentPaymentStatus( Future<MResponse> updateAppointmentPaymentStatus(Map<String, dynamic> map);
Map<String, dynamic> map);
Future<MResponse> getAppointmentSlots(Map<String, dynamic> map); Future<MResponse> getAppointmentSlots(Map<String, dynamic> map);
Future<MResponse> createMergeAppointment(Map<String, dynamic> map);
Future<Services> getAllServices(String branchId); Future<Services> getAllServices(String branchId);
Future<MResponse> createSchedule(Map map); Future<MResponse> createSchedule(Map map);
@ -38,19 +38,19 @@ abstract class AppointmentRepo {
Future<MResponse> updateServicesInSchedule(Map map); Future<MResponse> updateServicesInSchedule(Map map);
Future<List<ServiceAppointmentScheduleModel>> Future<List<ServiceAppointmentScheduleModel>>
mergeServiceIntoAvailableSchedules({ mergeServiceIntoAvailableSchedules({
required List<String> serviceItemIdsForHome, required List<String> serviceItemIdsForHome,
required List<String> serviceItemIdsForWorkshop, required List<String> serviceItemIdsForWorkshop,
}); });
Future<GenericRespModel> createServiceAppointment( Future<GenericRespModel> createServiceAppointment(
{required List<ServiceAppointmentScheduleModel> schedules, {required List<ServiceAppointmentScheduleModel> schedules,
required int serviceProviderID}); required int serviceProviderID});
Future<GenericRespModel> cancelOrRescheduleServiceAppointment( Future<GenericRespModel> cancelOrRescheduleServiceAppointment(
{required int serviceAppointmentID, {required int serviceAppointmentID,
required int serviceSlotID, required int serviceSlotID,
required int appointmentScheduleAction}); required int appointmentScheduleAction});
} }
class AppointmentRepoImp implements AppointmentRepo { class AppointmentRepoImp implements AppointmentRepo {
@ -59,7 +59,7 @@ class AppointmentRepoImp implements AppointmentRepo {
Map<String, dynamic> map = {"ProviderBranchID": branchId}; Map<String, dynamic> map = {"ProviderBranchID": branchId};
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject( return await injector.get<ApiClient>().getJsonForObject(
(json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, (json) => Services.fromJson(json), ApiConsts.getServicesOfBranch,
token: t, queryParameters: map); token: t, queryParameters: map);
} }
@ -67,7 +67,7 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<MResponse> createSchedule(Map map) async { Future<MResponse> createSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, (json) => MResponse.fromJson(json), ApiConsts.createSchedule, map,
token: t); token: t);
} }
@ -75,7 +75,7 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<MResponse> addServicesInSchedule(Map map) async { Future<MResponse> addServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.createGroup, map, (json) => MResponse.fromJson(json), ApiConsts.createGroup, map,
token: t); token: t);
} }
@ -85,22 +85,22 @@ class AppointmentRepoImp implements AppointmentRepo {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = GenericRespModel adsGenericModel =
await injector.get<ApiClient>().getJsonForObject( await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.getSchedule, ApiConsts.getSchedule,
token: t, token: t,
queryParameters: map, queryParameters: map,
); );
return List.generate(adsGenericModel.data.length, return List.generate(adsGenericModel.data.length,
(index) => ScheduleData.fromJson(adsGenericModel.data[index])); (index) => ScheduleData.fromJson(adsGenericModel.data[index]));
} }
@override @override
Future<MResponse> updateSchedule(Map map) async { Future<MResponse> updateSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, (json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map,
token: t); token: t);
} }
@ -108,12 +108,12 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<MResponse> updateServicesInSchedule(Map map) async { Future<MResponse> updateServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, (json) => MResponse.fromJson(json), ApiConsts.updateGroup, map,
token: t); token: t);
} }
Future<List<ServiceAppointmentScheduleModel>> Future<List<ServiceAppointmentScheduleModel>>
mergeServiceIntoAvailableSchedules({ mergeServiceIntoAvailableSchedules({
required List<String> serviceItemIdsForHome, required List<String> serviceItemIdsForHome,
required List<String> serviceItemIdsForWorkshop, required List<String> serviceItemIdsForWorkshop,
}) async { }) async {
@ -129,19 +129,20 @@ class AppointmentRepoImp implements AppointmentRepo {
} }
]; ];
GenericRespModel adsGenericModel = GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject( await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.GetServiceItemAppointmentScheduleSlots, ApiConsts.GetServiceItemAppointmentScheduleSlots,
queryParameters, queryParameters,
token: t, token: t,
); );
if (adsGenericModel.data == null) { if (adsGenericModel.data == null) {
return []; return [];
} }
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel = List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel =
List.generate( List.generate(
adsGenericModel.data.length, adsGenericModel.data.length,
(index) => ServiceAppointmentScheduleModel.fromJson( (index) =>
ServiceAppointmentScheduleModel.fromJson(
adsGenericModel.data[index], adsGenericModel.data[index],
isForAppointment: true)); isForAppointment: true));
return serviceAppointmentScheduleModel; return serviceAppointmentScheduleModel;
@ -149,7 +150,7 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<GenericRespModel> createServiceAppointment( Future<GenericRespModel> createServiceAppointment(
{required List<ServiceAppointmentScheduleModel> schedules, {required List<ServiceAppointmentScheduleModel> schedules,
required int serviceProviderID}) async { required int serviceProviderID}) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
int customerId = AppState().getUser.data!.userInfo!.customerId ?? 0; int customerId = AppState().getUser.data!.userInfo!.customerId ?? 0;
@ -170,12 +171,12 @@ class AppointmentRepoImp implements AppointmentRepo {
}); });
GenericRespModel adsGenericModel = GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject( await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProvidersAppointmentCreate, ApiConsts.ServiceProvidersAppointmentCreate,
mapList, mapList,
token: t, token: t,
); );
return adsGenericModel; return adsGenericModel;
} }
@ -183,8 +184,8 @@ class AppointmentRepoImp implements AppointmentRepo {
@override @override
Future<GenericRespModel> cancelOrRescheduleServiceAppointment( Future<GenericRespModel> cancelOrRescheduleServiceAppointment(
{required int serviceAppointmentID, {required int serviceAppointmentID,
required int serviceSlotID, required int serviceSlotID,
required int appointmentScheduleAction}) async { required int appointmentScheduleAction}) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
final payload = { final payload = {
@ -194,12 +195,12 @@ class AppointmentRepoImp implements AppointmentRepo {
}; };
GenericRespModel adsGenericModel = GenericRespModel adsGenericModel =
await injector.get<ApiClient>().postJsonForObject( await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment, ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment,
payload, payload,
token: t, token: t,
); );
return adsGenericModel; return adsGenericModel;
} }
@ -210,15 +211,16 @@ class AppointmentRepoImp implements AppointmentRepo {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel = GenericRespModel genericRespModel =
await injector.get<ApiClient>().getJsonForObject( await injector.get<ApiClient>().getJsonForObject(
token: t, token: t,
(json) => GenericRespModel.fromJson(json), (json) => GenericRespModel.fromJson(json),
queryParameters: map, queryParameters: map,
ApiConsts.serviceProvidersAppointmentGet, ApiConsts.serviceProvidersAppointmentGet,
); );
List<AppointmentListModel> appointmentList = List.generate( List<AppointmentListModel> appointmentList = List.generate(
genericRespModel.data.length, genericRespModel.data.length,
(index) => AppointmentListModel.fromJson(genericRespModel.data[index])); (index) =>
AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList; return appointmentList;
} }
@ -227,21 +229,23 @@ class AppointmentRepoImp implements AppointmentRepo {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
MResponse adsGenericModel = MResponse adsGenericModel =
await injector.get<ApiClient>().getJsonForObject( await injector.get<ApiClient>().getJsonForObject(
(json) => MResponse.fromJson(json), (json) => MResponse.fromJson(json),
ApiConsts.getAppointmentSlots, ApiConsts.getAppointmentSlots,
token: t, token: t,
queryParameters: map, queryParameters: map,
); );
return adsGenericModel; return adsGenericModel;
} }
@override @override
Future<MResponse> updateAppointmentPaymentStatus(Map<String, dynamic> map) async { Future<MResponse> updateAppointmentPaymentStatus(
Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateAppointmentPaymentStatus, map, (json) => MResponse.fromJson(json),
ApiConsts.updateAppointmentPaymentStatus, map,
token: t); token: t);
} }
@ -249,7 +253,17 @@ class AppointmentRepoImp implements AppointmentRepo {
Future<MResponse> updateAppointmentStatus(Map<String, dynamic> map) async { Future<MResponse> updateAppointmentStatus(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? ""; String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject( return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.updateAppointmentStatus, map, (json) => MResponse.fromJson(json),
ApiConsts.updateAppointmentStatus, map,
token: t);
}
@override
Future<MResponse> createMergeAppointment(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.createMergeAppointment, map,
token: t); token: t);
} }
} }

@ -150,12 +150,12 @@ enum AppointmentStatusEnum {
rescheduled, rescheduled,
allAppointments, allAppointments,
upcoming, upcoming,
inProgress, workStarted,
completed, visitCompleted,
} }
enum AppointmentPaymentStatusEnum { enum AppointmentPaymentStatusEnum {
notConfirmed, defaultStatus,
payNow, payNow,
paid, paid,
payLater, payLater,

@ -39,8 +39,12 @@ class AppointmentsVM extends BaseVM {
final ProviderRepo providerRepo; final ProviderRepo providerRepo;
final AppointmentRepo scheduleRepo; 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 isUpcommingEnabled = true;
bool isFetchingLists = false; bool isFetchingLists = false;
int selectedBranch = 0; int selectedBranch = 0;
int selectedAppointmentIndex = 0; int selectedAppointmentIndex = 0;
@ -65,7 +69,8 @@ class AppointmentsVM extends BaseVM {
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = []; List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = [];
bool ifItemAlreadySelected(int id) { bool ifItemAlreadySelected(int id) {
int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id); int indexFound = allSelectedItemsInAppointments
.indexWhere((element) => element.id == id);
if (indexFound != -1) { if (indexFound != -1) {
return true; return true;
} }
@ -76,16 +81,25 @@ class AppointmentsVM extends BaseVM {
setupProviderAppointmentFilter() { setupProviderAppointmentFilter() {
appointmentsFilterOptions.clear(); appointmentsFilterOptions.clear();
appointmentsFilterOptions.add(FilterListModel(id: 0, title: "All Appointments", isSelected: true)); appointmentsFilterOptions.add(
appointmentsFilterOptions.add(FilterListModel(id: 6, title: "Upcoming", isSelected: false)); FilterListModel(id: 0, title: "All Appointments", isSelected: true));
appointmentsFilterOptions.add(FilterListModel(id: 3, title: "Arrived", isSelected: false)); appointmentsFilterOptions
appointmentsFilterOptions.add(FilterListModel(id: 7, title: "In Progress", isSelected: false)); .add(FilterListModel(id: 2, title: "Confirmed", isSelected: false));
appointmentsFilterOptions.add(FilterListModel(id: 8, title: "Completed", isSelected: false)); appointmentsFilterOptions
.add(FilterListModel(id: 3, title: "Arrived", isSelected: false));
appointmentsFilterOptions
.add(
FilterListModel(id: 7, title: "Work In Progress", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 8, title: "Completed", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 4, title: "Canceled", isSelected: false));
} }
Future<void> onItemsSelectedInService() async { Future<void> onItemsSelectedInService() async {
if (currentServiceSelection != null) { if (currentServiceSelection != null) {
int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!); int index = servicesInCurrentAppointment.indexWhere((element) =>
element.serviceId == currentServiceSelection!.serviceId!);
if (index == -1) { if (index == -1) {
double totalPrice = 0.0; double totalPrice = 0.0;
@ -106,12 +120,14 @@ class AppointmentsVM extends BaseVM {
bool isSuccess = false; bool isSuccess = false;
List<int> appointmentIdsList = []; List<int> appointmentIdsList = [];
try { try {
GenericRespModel genericRespModel = await scheduleRepo.createServiceAppointment( GenericRespModel genericRespModel =
await scheduleRepo.createServiceAppointment(
schedules: serviceAppointmentScheduleList, schedules: serviceAppointmentScheduleList,
serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0, serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0,
); );
if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) { if (genericRespModel.messageStatus == 2 ||
genericRespModel.data == null) {
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}"); Utils.showToast("${genericRespModel.message.toString()}");
return; return;
@ -129,13 +145,17 @@ class AppointmentsVM extends BaseVM {
} }
context.read<DashboardVmCustomer>().onNavbarTapped(1); context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked); applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.booked);
Utils.hideLoading(context); Utils.hideLoading(context);
resetAfterBookingAppointment(); resetAfterBookingAppointment();
if (isSuccess) { if (isSuccess) {
if (amountToPayForAppointment > 0) { if (amountToPayForAppointment > 0) {
context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: appointmentIdsList); context
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); .read<PaymentVM>()
.updateAppointmentIdsForPayment(ids: appointmentIdsList);
navigateWithName(context, AppRoutes.paymentMethodsView,
arguments: PaymentTypes.appointment);
} else { } else {
Utils.showToast("Your appointment has been booked successfully!"); Utils.showToast("Your appointment has been booked successfully!");
getMyAppointments(); getMyAppointments();
@ -147,28 +167,36 @@ class AppointmentsVM extends BaseVM {
} }
} }
Future<void> onConfirmAppointmentPressed({required BuildContext context, required appointmentId}) async { Future<void> onConfirmAppointmentPressed(
context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: [appointmentId]); {required BuildContext context, required appointmentId}) async {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); 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); Utils.showLoading(context);
try { try {
GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( GenericRespModel genericRespModel =
await scheduleRepo.cancelOrRescheduleServiceAppointment(
serviceAppointmentID: appointmentListModel.id ?? 0, serviceAppointmentID: appointmentListModel.id ?? 0,
serviceSlotID: appointmentListModel.serviceSlotID ?? 0, serviceSlotID: appointmentListModel.serviceSlotID ?? 0,
appointmentScheduleAction: 2, // 1 for Reschedule and 2 for Cancel 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.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}"); Utils.showToast("${genericRespModel.message.toString()}");
return; return;
} }
if (genericRespModel.data == 1) { if (genericRespModel.data == 1) {
context.read<DashboardVmCustomer>().onNavbarTapped(1); context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast("${genericRespModel.message.toString()}"); Utils.showToast("${genericRespModel.message.toString()}");
await getMyAppointments(); await getMyAppointments();
Utils.hideLoading(context); Utils.hideLoading(context);
@ -199,7 +227,8 @@ class AppointmentsVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); SelectionModel branchSelectedCategoryId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateProviderCategoryId(SelectionModel id) { void updateProviderCategoryId(SelectionModel id) {
branchSelectedCategoryId = id; branchSelectedCategoryId = id;
@ -218,23 +247,30 @@ class AppointmentsVM extends BaseVM {
void updateBranchServiceId(SelectionModel id) async { void updateBranchServiceId(SelectionModel id) async {
branchSelectedServiceId = id; branchSelectedServiceId = id;
currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId); currentServiceSelection = branchServices.firstWhere(
(element) => element.serviceProviderServiceId == id.selectedId);
notifyListeners(); notifyListeners();
} }
void removeServiceInCurrentAppointment(int index) { void removeServiceInCurrentAppointment(int index) {
int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1; int serviceId = servicesInCurrentAppointment
allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId); .elementAt(index)
.serviceProviderServiceId ??
-1;
allSelectedItemsInAppointments.removeWhere(
(element) => element.serviceProviderServiceId == serviceId);
servicesInCurrentAppointment.removeAt(index); servicesInCurrentAppointment.removeAt(index);
notifyListeners(); notifyListeners();
} }
resetCategorySelectionBottomSheet() { resetCategorySelectionBottomSheet() {
selectedSubServicesCounter = 0; selectedSubServicesCounter = 0;
branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); branchSelectedCategoryId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false; isHomeTapped = false;
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
currentServiceSelection = null; currentServiceSelection = null;
} }
@ -249,24 +285,32 @@ class AppointmentsVM extends BaseVM {
populateAppointmentsFilterList() async { populateAppointmentsFilterList() async {
appointmentsFilterOptions.clear(); 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++) { 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(); notifyListeners();
} }
applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { applyFilterOnAppointmentsVM(
{required AppointmentStatusEnum appointmentStatusEnum,
bool isNeedCustomerFilter = false}) {
if (appointmentsFilterOptions.isEmpty) return; if (appointmentsFilterOptions.isEmpty) return;
for (var value in appointmentsFilterOptions) { for (var value in appointmentsFilterOptions) {
value.isSelected = false; value.isSelected = false;
} }
appointmentsFilterOptions.forEach((element) { appointmentsFilterOptions.forEach((element) {
if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { if (element.id ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum()) {
element.isSelected = true; element.isSelected = true;
} }
}); });
@ -281,11 +325,16 @@ class AppointmentsVM extends BaseVM {
return; return;
} }
myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList(); myFilteredAppointments = myAppointments
.where((element) =>
element.appointmentStatusID! ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum())
.toList();
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(); if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners(); notifyListeners();
} }
findAppointmentsBasedOnCustomers() { findAppointmentsBasedOnCustomers() {
// Use a Set to ensure uniqueness of customerIDs // Use a Set to ensure uniqueness of customerIDs
Set<int> uniqueCustomerIDs = Set<int>(); Set<int> uniqueCustomerIDs = Set<int>();
@ -297,7 +346,9 @@ class AppointmentsVM extends BaseVM {
// Create a list of CustomerData instances // Create a list of CustomerData instances
myFilteredAppointments2 = uniqueCustomerIDs.map((id) { myFilteredAppointments2 = uniqueCustomerIDs.map((id) {
List<AppointmentListModel> list = myFilteredAppointments.where((item) => item.customerID == id).toList(); List<AppointmentListModel> list = myFilteredAppointments
.where((item) => item.customerID == id)
.toList();
AppointmentListModel model = list.first; AppointmentListModel model = list.first;
model.customerAppointmentList = list; model.customerAppointmentList = list;
return model; return model;
@ -322,7 +373,10 @@ class AppointmentsVM extends BaseVM {
myAppointments = await commonRepo.getMyAppointments(); myAppointments = await commonRepo.getMyAppointments();
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList(); myUpComingAppointments = myAppointments
.where((element) =>
element.appointmentStatusEnum == AppointmentStatusEnum.confirmed)
.toList();
setState(ViewState.idle); setState(ViewState.idle);
// applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); // applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners(); notifyListeners();
@ -330,7 +384,9 @@ class AppointmentsVM extends BaseVM {
AppointmentSlots? appointmentSlots; AppointmentSlots? appointmentSlots;
Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map, required BuildContext context, bool isNeedToRebuild = false}) async { Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map,
required BuildContext context,
bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map); MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map);
@ -344,18 +400,21 @@ class AppointmentsVM extends BaseVM {
} }
} }
Future<void> getProviderMyAppointments(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async { Future<void> getProviderMyAppointments(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await scheduleRepo.getMyAppointments(map); myAppointments = await scheduleRepo.getMyAppointments(map);
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
// myUpComingAppointments = myAppointments myUpComingAppointments = myAppointments
// .where((element) => .where((element) =>
// element.appointmentStatusEnum == AppointmentStatusEnum.booked) element.appointmentStatusEnum == AppointmentStatusEnum.booked)
// .toList(); .toList();
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.allAppointments,
isNeedCustomerFilter: true);
setState(ViewState.idle); setState(ViewState.idle);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
notifyListeners();
} }
updateSelectedBranch(BranchDetailModel branchDetailModel) { updateSelectedBranch(BranchDetailModel branchDetailModel) {
@ -364,10 +423,12 @@ class AppointmentsVM extends BaseVM {
notifyListeners(); notifyListeners();
} }
updateAppointmentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async { updateAppointmentStatus(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map); MResponse genericRespModel =
await scheduleRepo.updateAppointmentStatus(map);
if (genericRespModel.messageStatus == 1) { if (genericRespModel.messageStatus == 1) {
Utils.showToast("appointment status updated"); Utils.showToast("appointment status updated");
@ -379,10 +440,12 @@ class AppointmentsVM extends BaseVM {
} }
} }
updateAppointmentPaymentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async { updateAppointmentPaymentStatus(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
try { try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map); MResponse genericRespModel =
await scheduleRepo.updateAppointmentPaymentStatus(map);
if (genericRespModel.messageStatus == 1) { if (genericRespModel.messageStatus == 1) {
Utils.showToast("payment status updated"); Utils.showToast("payment status updated");
@ -394,32 +457,91 @@ class AppointmentsVM extends BaseVM {
} }
} }
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) { Future<MResponse> createMergeAppointment(Map<String, dynamic> map,
for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) { {bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
MResponse genericRespModel =
await scheduleRepo.createMergeAppointment(map);
return genericRespModel;
}
bool inNeedToEnableMergeButton = false;
updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointments2[selectedAppointmentIndex]
.customerAppointmentList![currentIndex]
.isSelected = !(myFilteredAppointments2[selectedAppointmentIndex]
.customerAppointmentList?[currentIndex]
.isSelected ??
false);
int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex]
.customerAppointmentList ??
[]);
if (count > 1)
inNeedToEnableMergeButton = true;
else
inNeedToEnableMergeButton = false;
notifyListeners();
}
int countSelected(List<AppointmentListModel> appointments) {
return appointments
.where((appointment) => appointment.isSelected == true)
.toList()
.length;
}
updateSelectedAppointmentDate(
{required int dateIndex, required int scheduleIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList!) {
element.date!.isSelected = false; element.date!.isSelected = false;
} }
serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.isSelected = true; serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![dateIndex]
.date!
.isSelected = true;
serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex = dateIndex; serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex = dateIndex;
final date = TimeSlotModel( final date = TimeSlotModel(
date: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.date, date: serviceAppointmentScheduleList[scheduleIndex]
slotId: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.slotId, .customTimeDateSlotList![dateIndex]
.date!
.date,
slotId: serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![dateIndex]
.date!
.slotId,
isSelected: true, isSelected: true,
slot: "", slot: "",
); );
serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date); serviceAppointmentScheduleList[scheduleIndex]
.selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date);
notifyListeners(); notifyListeners();
} }
updateSelectedAppointmentSlotByDate({required int scheduleIndex, required int slotIndex}) { updateSelectedAppointmentSlotByDate(
for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) { {required int scheduleIndex, required int slotIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList!) {
for (var element in element.availableSlots!) { for (var element in element.availableSlots!) {
element.isSelected = false; element.isSelected = false;
} }
} }
int index = serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!; int index =
serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots![slotIndex].isSelected = true; serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!;
serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel!.availableSlots = serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots!; serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![index]
.availableSlots![slotIndex]
.isSelected = true;
serviceAppointmentScheduleList[scheduleIndex]
.selectedCustomTimeDateSlotModel!
.availableSlots =
serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![index]
.availableSlots!;
notifyListeners(); notifyListeners();
} }
@ -433,7 +555,9 @@ class AppointmentsVM extends BaseVM {
int selectedSubServicesCounter = 0; int selectedSubServicesCounter = 0;
onItemUpdateOrSelected(int index, bool selected, int itemId) { 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}"); // print("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
// if (serviceIndex == -1) { // if (serviceIndex == -1) {
// return; // return;
@ -448,19 +572,28 @@ class AppointmentsVM extends BaseVM {
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]); allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
for (var element in allSelectedItemsInAppointments) { for (var element in allSelectedItemsInAppointments) {
if (!ifItemAlreadySelected(element.id!)) { if (!ifItemAlreadySelected(element.id!)) {
servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]); servicesInCurrentAppointment[serviceIndex]
.serviceItems!
.add(serviceItemsFromApi[index]);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = 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) { if (!selected) {
selectedSubServicesCounter = selectedSubServicesCounter - 1; selectedSubServicesCounter = selectedSubServicesCounter - 1;
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId); currentServiceSelection!.serviceItems!
allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId); .removeWhere((element) => element.id == itemId);
allSelectedItemsInAppointments
.removeWhere((element) => element.id == itemId);
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0"); servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice -
servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId); double.parse((serviceItemsFromApi[index].price) ?? "0.0");
servicesInCurrentAppointment[serviceIndex]
.serviceItems!
.removeWhere((element) => element.id == itemId);
} }
notifyListeners(); notifyListeners();
} }
@ -516,7 +649,8 @@ class AppointmentsVM extends BaseVM {
String pickHomeLocationError = ""; String pickHomeLocationError = "";
String selectSubServicesError = ""; String selectSubServicesError = "";
SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); SelectionModel branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
bool isCategoryAlreadyPresent(int id) { bool isCategoryAlreadyPresent(int id) {
final contain = branchCategories.where((element) => element.id == id); final contain = branchCategories.where((element) => element.id == id);
@ -529,14 +663,16 @@ class AppointmentsVM extends BaseVM {
void getBranchCategories() async { void getBranchCategories() async {
for (var value in selectedBranchModel!.branchServices!) { for (var value in selectedBranchModel!.branchServices!) {
if (!isCategoryAlreadyPresent(value.categoryId!)) { if (!isCategoryAlreadyPresent(value.categoryId!)) {
branchCategories.add(DropValue(value.categoryId!, value.categoryName!, "")); branchCategories
.add(DropValue(value.categoryId!, value.categoryName!, ""));
} }
} }
notifyListeners(); notifyListeners();
} }
getBranchServices({required int categoryId}) async { getBranchServices({required int categoryId}) async {
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); branchSelectedServiceId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false; isHomeTapped = false;
pickedHomeLocation = ""; pickedHomeLocation = "";
pickHomeLocationError = ""; pickHomeLocationError = "";
@ -549,7 +685,9 @@ class AppointmentsVM extends BaseVM {
} }
List<ServiceModel> getFilteredBranchServices({required int categoryId}) { 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; return filteredServices;
} }
@ -591,7 +729,8 @@ class AppointmentsVM extends BaseVM {
return totalPrice.toString(); return totalPrice.toString();
} }
void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) { void openTheAddServiceBottomSheet(BuildContext context,
AppointmentsVM appointmentsVM) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
@ -602,7 +741,8 @@ class AppointmentsVM extends BaseVM {
); );
} }
void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) { void priceBreakDownClicked(BuildContext context,
ServiceModel selectedService) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
@ -618,19 +758,27 @@ class AppointmentsVM extends BaseVM {
Column( Column(
children: List.generate( children: List.generate(
selectedService.serviceItems!.length, selectedService.serviceItems!.length,
(index) => Row( (index) =>
mainAxisAlignment: MainAxisAlignment.spaceBetween, Row(
children: [ mainAxisAlignment: MainAxisAlignment.spaceBetween,
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), children: [
"${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true), "${selectedService.serviceItems![index].name}"
], .toText(
), fontSize: 12,
color: MyColors.lightTextColor,
isBold: true),
"${selectedService.serviceItems![index]
.price} SAR"
.toText(fontSize: 12, isBold: true),
],
),
), ),
), ),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
"${selectedService.currentTotalServicePrice} SAR".toText(fontSize: 16, isBold: true), "${selectedService.currentTotalServicePrice} SAR"
.toText(fontSize: 16, isBold: true),
], ],
), ),
if (selectedService.isHomeSelected) ...[ if (selectedService.isHomeSelected) ...[
@ -639,15 +787,20 @@ class AppointmentsVM extends BaseVM {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"${totalKms}km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), "${totalKms}km ".toText(
"${selectedService.rangePricePerKm} x $totalKms".toText(fontSize: 12, isBold: true), fontSize: 12,
color: MyColors.lightTextColor,
isBold: true),
"${selectedService.rangePricePerKm} x $totalKms"
.toText(fontSize: 12, isBold: true),
], ],
), ),
8.height, 8.height,
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
"${selectedService.rangePricePerKm ?? 0 * totalKms} SAR".toText(fontSize: 16, isBold: true), "${selectedService.rangePricePerKm ?? 0 * totalKms} SAR"
.toText(fontSize: 16, isBold: true),
], ],
), ),
], ],
@ -660,11 +813,18 @@ class AppointmentsVM extends BaseVM {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
(selectedService.isHomeSelected (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), .toText(fontSize: 29, isBold: true),
2.width, 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),
], ],
) )
], ],
@ -684,7 +844,8 @@ class AppointmentsVM extends BaseVM {
isValidated = false; isValidated = false;
break; break;
} }
if (schedule.selectedCustomTimeDateSlotModel!.date == null || !schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) { if (schedule.selectedCustomTimeDateSlotModel!.date == null ||
!schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) {
isValidated = false; isValidated = false;
break; break;
} else { } else {
@ -692,7 +853,9 @@ class AppointmentsVM extends BaseVM {
isValidated = false; isValidated = false;
break; break;
} else { } else {
TimeSlotModel slot = schedule.selectedCustomTimeDateSlotModel!.availableSlots!.firstWhere((element) => element.isSelected); TimeSlotModel slot = schedule
.selectedCustomTimeDateSlotModel!.availableSlots!
.firstWhere((element) => element.isSelected);
if (slot.date.isNotEmpty) { if (slot.date.isNotEmpty) {
isValidated = true; isValidated = true;
break; break;
@ -701,7 +864,8 @@ class AppointmentsVM extends BaseVM {
} }
} }
if (!isValidated) { 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; return;
} }
navigateWithName(context, AppRoutes.reviewAppointmentView); navigateWithName(context, AppRoutes.reviewAppointmentView);
@ -720,30 +884,36 @@ class AppointmentsVM extends BaseVM {
} }
} }
serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( serviceAppointmentScheduleList =
await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForHome: serviceItemIdsForHome,
serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
); );
if (serviceAppointmentScheduleList.isEmpty) { if (serviceAppointmentScheduleList.isEmpty) {
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.showToast("There are no available appointments for selected Items."); Utils.showToast(
"There are no available appointments for selected Items.");
return; return;
} }
totalAmount = 0.0; totalAmount = 0.0;
amountToPayForAppointment = 0.0; amountToPayForAppointment = 0.0;
for (var schedule in serviceAppointmentScheduleList) { for (var schedule in serviceAppointmentScheduleList) {
amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0); amountToPayForAppointment =
amountToPayForAppointment + (schedule.amountToPay ?? 0.0);
totalAmount = totalAmount + (schedule.amountTotal ?? 0.0); totalAmount = totalAmount + (schedule.amountTotal ?? 0.0);
} }
Utils.hideLoading(context); 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(); notifyListeners();
} }
Future<void> onRescheduleAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async { Future<void> onRescheduleAppointmentPressed({required BuildContext context,
required AppointmentListModel appointmentListModel}) async {
Utils.showLoading(context); Utils.showLoading(context);
List<String> serviceItemIdsForHome = []; List<String> serviceItemIdsForHome = [];
@ -760,14 +930,16 @@ class AppointmentsVM extends BaseVM {
} }
} }
serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( serviceAppointmentScheduleList =
await scheduleRepo.mergeServiceIntoAvailableSchedules(
serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForHome: serviceItemIdsForHome,
serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
); );
if (serviceAppointmentScheduleList.isEmpty) { if (serviceAppointmentScheduleList.isEmpty) {
Utils.hideLoading(context); Utils.hideLoading(context);
Utils.showToast("There are no available appointments for selected Items."); Utils.showToast(
"There are no available appointments for selected Items.");
return; return;
} }
Utils.hideLoading(context); Utils.hideLoading(context);
@ -775,29 +947,36 @@ class AppointmentsVM extends BaseVM {
navigateWithName( navigateWithName(
context, context,
AppRoutes.bookAppointmenSchedulesView, AppRoutes.bookAppointmenSchedulesView,
arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 2, appointmentId: appointmentListModel.id ?? 0), arguments: ScreenArgumentsForAppointmentDetailPage(
routeFlag: 2, appointmentId: appointmentListModel.id ?? 0),
); // 2 For Rescheduling an Appointment ); // 2 For Rescheduling an Appointment
notifyListeners(); 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); Utils.showLoading(context);
try { try {
GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( GenericRespModel genericRespModel =
await scheduleRepo.cancelOrRescheduleServiceAppointment(
serviceAppointmentID: appointmentId, serviceAppointmentID: appointmentId,
serviceSlotID: selectedSlotId, serviceSlotID: selectedSlotId,
appointmentScheduleAction: 1, // 1 for Reschedule and 2 for Cancel 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.hideLoading(context);
Utils.showToast("${genericRespModel.message.toString()}"); Utils.showToast("${genericRespModel.message.toString()}");
return; return;
} }
if (genericRespModel.data == 1) { if (genericRespModel.data == 1) {
context.read<DashboardVmCustomer>().onNavbarTapped(1); context.read<DashboardVmCustomer>().onNavbarTapped(1);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.cancelled);
Utils.showToast("${genericRespModel.message.toString()}"); Utils.showToast("${genericRespModel.message.toString()}");
getMyAppointments(); getMyAppointments();
Utils.hideLoading(context); Utils.hideLoading(context);

@ -13,14 +13,23 @@ import 'package:mc_common_app/views/advertisement/custom_add_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
//TODO: Need to make onTapped dynamic
class CustomerAppointmentSliderWidget extends StatelessWidget { class CustomerAppointmentSliderWidget extends StatelessWidget {
final List<AppointmentListModel> myUpComingAppointments; final List<AppointmentListModel> myUpComingAppointments;
bool isNeedToShowEmptyMessage;
Function()? onAppointmentClick;
const CustomerAppointmentSliderWidget({Key? key, required this.myUpComingAppointments}) : super(key: key); CustomerAppointmentSliderWidget({Key? key,
required this.myUpComingAppointments,
this.isNeedToShowEmptyMessage = false,
this.onAppointmentClick})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (myUpComingAppointments.isEmpty) { if (myUpComingAppointments.isEmpty) {
if (isNeedToShowEmptyMessage)
return "No Upcoming Appointment Available".toText().paddingAll(21);
return CustomAddButton( return CustomAddButton(
needsBorder: true, needsBorder: true,
bgColor: MyColors.white, bgColor: MyColors.white,
@ -29,7 +38,8 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
icon: Container( icon: Container(
height: 24, height: 24,
width: 24, width: 24,
decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), decoration: const BoxDecoration(
shape: BoxShape.circle, color: MyColors.darkTextColor),
child: const Icon(Icons.add, color: MyColors.white), child: const Icon(Icons.add, color: MyColors.white),
), ),
).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21)); ).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21));
@ -41,7 +51,8 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
Container( Container(
height: 24, height: 24,
width: 24, width: 24,
decoration: BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), decoration: BoxDecoration(
shape: BoxShape.circle, color: MyColors.darkTextColor),
child: Icon( child: Icon(
Icons.add, Icons.add,
color: MyColors.white, color: MyColors.white,
@ -55,7 +66,9 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
), ),
], ],
), ),
).onPress(() {}).toWhiteContainer(width: double.infinity, margin: EdgeInsets.symmetric(horizontal: 21, vertical: 10)); ).onPress(() {}).toWhiteContainer(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 21, vertical: 10));
} }
return CarouselSlider.builder( return CarouselSlider.builder(
options: CarouselOptions( options: CarouselOptions(
@ -65,11 +78,16 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
enableInfiniteScroll: false, enableInfiniteScroll: false,
), ),
itemCount: myUpComingAppointments.length, itemCount: myUpComingAppointments.length,
itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) => BuildAppointmentContainerForCustomer( itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) =>
isForHome: true, BuildAppointmentContainerForCustomer(
appointmentListModel: myUpComingAppointments[itemIndex], isForHome: true,
onTapped: () => navigateWithName(context, AppRoutes.appointmentDetailView, arguments: myUpComingAppointments[itemIndex]), appointmentListModel: myUpComingAppointments[itemIndex],
), onTapped: isNeedToShowEmptyMessage
? onAppointmentClick!
: () =>
navigateWithName(context, AppRoutes.appointmentDetailView,
arguments: myUpComingAppointments[itemIndex]),
),
); );
} }
} }
@ -79,7 +97,11 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
final AppointmentListModel? appointmentListModel; final AppointmentListModel? appointmentListModel;
final Function() onTapped; final Function() onTapped;
const BuildAppointmentContainerForCustomer({Key? key, this.isForHome = false, required this.onTapped, required this.appointmentListModel}) : super(key: key); const BuildAppointmentContainerForCustomer({Key? key,
this.isForHome = false,
required this.onTapped,
required this.appointmentListModel})
: super(key: key);
Widget showServices(String title, String icon, {bool isMoreText = false}) { Widget showServices(String title, String icon, {bool isMoreText = false}) {
return Row( return Row(
@ -99,15 +121,18 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
); );
} }
List<Widget> buildServicesFromAppointment({required AppointmentListModel appointmentListModel}) { List<Widget> buildServicesFromAppointment(
if (appointmentListModel.appointmentServicesList == null || appointmentListModel.appointmentServicesList!.isEmpty) { {required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null ||
appointmentListModel.appointmentServicesList!.isEmpty) {
return [SizedBox()]; return [SizedBox()];
} }
if (appointmentListModel.appointmentServicesList!.length == 1) { if (appointmentListModel.appointmentServicesList!.length == 1) {
return [ return [
showServices( showServices(
appointmentListModel.appointmentServicesList![0].providerServiceDescription, appointmentListModel
.appointmentServicesList![0].providerServiceDescription,
MyAssets.modificationsIcon, MyAssets.modificationsIcon,
) )
]; ];
@ -115,7 +140,11 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
List<Widget> servicesList = List.generate( List<Widget> servicesList = List.generate(
2, 2,
(index) => showServices(appointmentListModel.appointmentServicesList![index].providerServiceDescription, MyAssets.modificationsIcon), (index) =>
showServices(
appointmentListModel
.appointmentServicesList![index].providerServiceDescription,
MyAssets.modificationsIcon),
); );
if (appointmentListModel.appointmentServicesList!.length > 1) { if (appointmentListModel.appointmentServicesList!.length > 1) {
@ -141,29 +170,33 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
children: [ children: [
isForHome != null && isForHome! isForHome != null && isForHome!
? Image.asset( ? Image.asset(
MyAssets.bnCar, MyAssets.bnCar,
width: 56, width: 56,
height: 56, height: 56,
fit: BoxFit.fill, fit: BoxFit.fill,
).toCircle(borderRadius: 100) ).toCircle(borderRadius: 100)
: Image.asset( : Image.asset(
MyAssets.bnCar, MyAssets.bnCar,
width: 80, width: 80,
height: 85, height: 85,
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
8.width, 8.width,
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
(appointmentListModel!.providerName ?? "").toText(color: MyColors.black, isBold: true, fontSize: 16), (appointmentListModel!.providerName ?? "").toText(
color: MyColors.black, isBold: true, fontSize: 16),
Row( Row(
children: [ children: [
MyAssets.miniClock.buildSvg(height: 12), MyAssets.miniClock.buildSvg(height: 12),
2.width, 2.width,
"${appointmentListModel!.duration ?? ""} ${appointmentListModel!.appointmentDate!.toFormattedDateWithoutTime()}".toText( "${appointmentListModel!.duration ??
""} ${appointmentListModel!.appointmentDate!
.toFormattedDateWithoutTime()}"
.toText(
color: MyColors.lightTextColor, color: MyColors.lightTextColor,
fontSize: 12, fontSize: 12,
), ),
@ -172,38 +205,42 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
9.height, 9.height,
isForHome != null && isForHome! isForHome != null && isForHome!
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
"Appointment Details".toText( "Appointment Details".toText(
color: MyColors.primaryColor, color: MyColors.primaryColor,
isUnderLine: true, isUnderLine: true,
isBold: true, isBold: true,
fontSize: 14, fontSize: 14,
), ),
const Icon(Icons.arrow_forward), const Icon(Icons.arrow_forward),
], ],
) )
: Row( : Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Expanded( Expanded(
child: Column( child: Column(
children: buildServicesFromAppointment(appointmentListModel: appointmentListModel!), children: buildServicesFromAppointment(
), appointmentListModel:
), appointmentListModel!),
const Icon(
Icons.arrow_forward,
),
],
), ),
),
const Icon(
Icons.arrow_forward,
),
],
),
], ],
), ),
), ),
], ],
), ),
], ],
).onPress(onTapped).toWhiteContainer(width: double.infinity, allPading: 12), )
.onPress(onTapped)
.toWhiteContainer(width: double.infinity, allPading: 12),
); );
} }
} }

Loading…
Cancel
Save