Merge branch 'master' into faiz_development_common

mirza_development
Faiz Hashmi 2 years ago
commit a76b8d8244

@ -46,6 +46,7 @@ class ApiConsts {
static String Services_Get = "${baseUrlServices}api/ServiceProviders/Services_Get"; static String Services_Get = "${baseUrlServices}api/ServiceProviders/Services_Get";
static String ServiceProviderService_Create = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create"; static String ServiceProviderService_Create = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Create";
static String ServiceProviderService_Update = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update"; static String ServiceProviderService_Update = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Update";
static String GetProviderServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String ServiceProviderService_Get = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get"; static String ServiceProviderService_Get = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get";
static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get"; static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get";
@ -58,6 +59,7 @@ class ApiConsts {
static String GetServiceItemAppointmentScheduleSlots = "${baseUrlServices}api/ServiceProviders/ServiceItemAppointmentScheduleSlots_GetByAppointmentType"; static String GetServiceItemAppointmentScheduleSlots = "${baseUrlServices}api/ServiceProviders/ServiceItemAppointmentScheduleSlots_GetByAppointmentType";
static String ServiceProvidersAppointmentCreate = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentList_Create"; static String ServiceProvidersAppointmentCreate = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentList_Create";
static String ServiceProviderAppointmentRescheduleCancelAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_RescheduleCancelAppointment"; static String ServiceProviderAppointmentRescheduleCancelAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_RescheduleCancelAppointment";
static String AddNewServicesInAppointment = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointment_ServiceItemAdd";
//ServiceProvidersServiceID as params //ServiceProvidersServiceID as params
// static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get"; // static String servicesGet = "${baseUrlServices}api/ServiceProviders/Services_Get";
@ -103,6 +105,9 @@ class ApiConsts {
static String adsPhotoOfficeAppointmentScheduleSlotGet = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointmentScheduleSlot_Get"; static String adsPhotoOfficeAppointmentScheduleSlotGet = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointmentScheduleSlot_Get";
static String adsPhotoOfficeAppointmentCreate = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointment_Create"; static String adsPhotoOfficeAppointmentCreate = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointment_Create";
static String adsMCBankAccountAdGet = "${baseUrlServices}api/Advertisement/MCBankAccountAd_Get"; static String adsMCBankAccountAdGet = "${baseUrlServices}api/Advertisement/MCBankAccountAd_Get";
static String getAppointmentSlots = "${baseUrlServices}api/ServiceProviders/ScheduleSlotsInfo_Get";
static String updateAppointmentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentStatus_Update";
static String updateAppointmentPaymentStatus = "${baseUrlServices}api/ServiceProviders/ServiceProviderAppointmentServiceItemPaymentStatus_Update";
//Subscription //Subscription
static String getAllSubscriptions = "${baseUrlServices}api/Common/Subscription_Get"; static String getAllSubscriptions = "${baseUrlServices}api/Common/Subscription_Get";

@ -25,7 +25,9 @@ extension EmailValidator on String {
style: TextStyle( style: TextStyle(
fontStyle: isItalic ? FontStyle.italic : null, fontStyle: isItalic ? FontStyle.italic : null,
height: height, height: height,
decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none, decoration: isUnderLine
? TextDecoration.underline
: textDecoration ?? TextDecoration.none,
fontSize: fontSize ?? 10, fontSize: fontSize ?? 10,
fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600,
color: color ?? MyColors.darkTextColor, color: color ?? MyColors.darkTextColor,
@ -34,7 +36,9 @@ extension EmailValidator on String {
); );
bool isValidEmail() { bool isValidEmail() {
return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this); return RegExp(
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(this);
} }
bool isNum() { bool isNum() {
@ -206,6 +210,40 @@ extension AdPostEnum on int {
} }
} }
extension AppointmentStatusToInt on AppointmentStatusEnum {
int getIdFromAppointmentStatusEnum() {
switch (this) {
case AppointmentStatusEnum.booked:
return 1;
case AppointmentStatusEnum.confirmed:
return 2;
case AppointmentStatusEnum.arrived:
return 3;
case AppointmentStatusEnum.cancelled:
return 4;
case AppointmentStatusEnum.rescheduled:
return 5;
case AppointmentStatusEnum.upcoming:
return 6;
case AppointmentStatusEnum.inProgress:
return 7;
case AppointmentStatusEnum.completed:
return 8;
default:
return 0;
}
}
}
//TODO: Need to verify Enum on upcoming and inprogress with the database
extension AppointmentEnum on int { extension AppointmentEnum on int {
AppointmentStatusEnum toAppointmentStatusEnum() { AppointmentStatusEnum toAppointmentStatusEnum() {
if (this == 1) { if (this == 1) {
@ -218,12 +256,60 @@ extension AppointmentEnum on int {
return AppointmentStatusEnum.cancelled; return AppointmentStatusEnum.cancelled;
} else if (this == 5) { } else if (this == 5) {
return AppointmentStatusEnum.rescheduled; return AppointmentStatusEnum.rescheduled;
} else if (this == 6) {
return AppointmentStatusEnum.upcoming;
} else if (this == 7) {
return AppointmentStatusEnum.inProgress;
} else if (this == 8) {
return AppointmentStatusEnum.completed;
} else { } else {
return AppointmentStatusEnum.allAppointments; return AppointmentStatusEnum.allAppointments;
} }
} }
} }
extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
int getIdFromAppointmentPaymentStatusEnum() {
switch (this) {
case AppointmentPaymentStatusEnum.notConfirmed:
return 1;
case AppointmentPaymentStatusEnum.payNow:
return 2;
case AppointmentPaymentStatusEnum.paid:
return 3;
case AppointmentPaymentStatusEnum.payLater:
return 4;
case AppointmentPaymentStatusEnum.payPartial:
return 5;
default:
return 1;
}
}
}
extension AppointmentPaymentEnum on int {
AppointmentPaymentStatusEnum toAppointmentPaymentStatusEnum() {
if (this == 1) {
return AppointmentPaymentStatusEnum.notConfirmed;
} else if (this == 2) {
return AppointmentPaymentStatusEnum.payNow;
} else if (this == 3) {
return AppointmentPaymentStatusEnum.paid;
} else if (this == 4) {
return AppointmentPaymentStatusEnum.payLater;
} else if (this == 5) {
return AppointmentPaymentStatusEnum.payPartial;
} else {
return AppointmentPaymentStatusEnum.notConfirmed;
}
}
}
extension RequestTypeTypeEnum on int { extension RequestTypeTypeEnum on int {
RequestsTypeEnum toRequestTypeStatusEnum() { RequestsTypeEnum toRequestTypeStatusEnum() {
if (this == 1) { if (this == 1) {
@ -314,30 +400,6 @@ extension PaymentTypesToInt on PaymentTypes {
} }
} }
extension AppointmentStatusToInt on AppointmentStatusEnum {
int getIdFromAppointmentStatusEnum() {
switch (this) {
case AppointmentStatusEnum.booked:
return 1;
case AppointmentStatusEnum.confirmed:
return 2;
case AppointmentStatusEnum.arrived:
return 3;
case AppointmentStatusEnum.cancelled:
return 4;
case AppointmentStatusEnum.rescheduled:
return 5;
default:
return 0;
}
}
}
extension CreatedByRoleEnumToInt on CreatedByRoleEnum { extension CreatedByRoleEnumToInt on CreatedByRoleEnum {
int getIdFromCreatedByRoleEnum() { int getIdFromCreatedByRoleEnum() {
switch (this) { switch (this) {

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

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

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

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

@ -149,6 +149,17 @@ enum AppointmentStatusEnum {
cancelled, cancelled,
rescheduled, rescheduled,
allAppointments, allAppointments,
upcoming,
inProgress,
completed,
}
enum AppointmentPaymentStatusEnum {
notConfirmed,
payNow,
paid,
payLater,
payPartial,
} }
enum RequestsTypeEnum { enum RequestsTypeEnum {

@ -6,6 +6,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart'; import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
@ -30,20 +31,31 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../models/appointments_models/appointment_slots.dart';
class AppointmentsVM extends BaseVM { class AppointmentsVM extends BaseVM {
final CommonRepo commonRepo; final CommonRepo commonRepo;
final CommonAppServices commonServices; final CommonAppServices commonServices;
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 isFetchingLists = false; bool isFetchingLists = false;
int selectedBranch = 0;
int selectedAppointmentIndex = 0;
int selectedAppointmentSubIndex = 0;
int selectedAppointmentId = 0;
List<AppointmentListModel> myAppointments = []; List<AppointmentListModel> myAppointments = [];
List<AppointmentListModel> myUpComingAppointments = []; List<AppointmentListModel> myUpComingAppointments = [];
List<AppointmentListModel> myFilteredAppointments = []; List<AppointmentListModel> myFilteredAppointments = [];
List<FilterListModel> appointmentsFilterOptions = []; List<FilterListModel> appointmentsFilterOptions = [];
List<CustomerData> customersAppointments = [];
List<AppointmentListModel> myFilteredAppointments2 = [];
// List<ScheduleData> availableSchedules = []; // List<ScheduleData> availableSchedules = [];
@ -56,7 +68,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;
} }
@ -65,9 +78,24 @@ class AppointmentsVM extends BaseVM {
List<ItemData> allSelectedItemsInAppointments = []; List<ItemData> allSelectedItemsInAppointments = [];
setupProviderAppointmentFilter() {
appointmentsFilterOptions.clear();
appointmentsFilterOptions.add(
FilterListModel(id: 0, title: "All Appointments", isSelected: true));
appointmentsFilterOptions
.add(FilterListModel(id: 6, title: "Upcoming", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 3, title: "Arrived", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 7, title: "In Progress", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 8, title: "Completed", isSelected: false));
}
Future<void> onItemsSelectedInService() async { 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;
@ -88,12 +116,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;
@ -111,13 +141,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();
@ -129,28 +163,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);
@ -181,7 +223,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;
@ -200,23 +243,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;
} }
@ -231,76 +281,222 @@ 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}) { 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[appointmentStatusEnum.getIdFromAppointmentStatusEnum()].isSelected = true;
appointmentsFilterOptions.forEach((element) {
if (element.id ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum()) {
element.isSelected = true;
}
});
// appointmentsFilterOptions[
// appointmentStatusEnum.getIdFromAppointmentStatusEnum()]
// .isSelected = true;
if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) { if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) {
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners(); notifyListeners();
return; return;
} }
myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList(); myFilteredAppointments = myAppointments
.where((element) =>
element.appointmentStatusID! ==
appointmentStatusEnum.getIdFromAppointmentStatusEnum())
.toList();
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
notifyListeners(); notifyListeners();
} }
findAppointmentsBasedOnCustomers() {
// Use a Set to ensure uniqueness of customerIDs
Set<int> uniqueCustomerIDs = Set<int>();
// Extract unique customerIDs
for (var item in myFilteredAppointments) {
uniqueCustomerIDs.add(item.customerID ?? 0);
}
// Create a list of CustomerData instances
myFilteredAppointments2 = uniqueCustomerIDs.map((id) {
List<AppointmentListModel> list = myFilteredAppointments
.where((item) => item.customerID == id)
.toList();
AppointmentListModel model = list.first;
model.customerAppointmentList = list;
return model;
}).toList();
// customersAppointments = uniqueCustomerIDs.map((id) {
// List<AppointmentListModel> list = myFilteredAppointments
// .where((item) => item.customerID == id)
// .toList();
// var customerItem =
// myFilteredAppointments.firstWhere((item) => item.customerID == id);
//
// return CustomerData(
// customerID: id,
// customerName: customerItem.customerName ?? "",
// appointmentList: list,
// );
// }).toList();
}
Future<void> getMyAppointments({bool isNeedToRebuild = false}) async { Future<void> getMyAppointments({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy); if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await commonRepo.getMyAppointments(); myAppointments = await commonRepo.getMyAppointments();
myFilteredAppointments = myAppointments; myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList(); myUpComingAppointments = myAppointments
.where((element) =>
element.appointmentStatusEnum == AppointmentStatusEnum.booked)
.toList();
setState(ViewState.idle); setState(ViewState.idle);
// applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); // applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners(); notifyListeners();
} }
AppointmentSlots? appointmentSlots;
Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map,
required BuildContext context,
bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map);
if (genericRespModel.messageStatus == 1) {
appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
Future<void> getProviderMyAppointments(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await scheduleRepo.getMyAppointments(map);
myFilteredAppointments = myAppointments;
// myUpComingAppointments = myAppointments
// .where((element) =>
// element.appointmentStatusEnum == AppointmentStatusEnum.booked)
// .toList();
setState(ViewState.idle);
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.allAppointments,
isNeedCustomerFilter: true);
notifyListeners();
}
updateSelectedBranch(BranchDetailModel branchDetailModel) { updateSelectedBranch(BranchDetailModel branchDetailModel) {
selectedBranchModel = branchDetailModel; selectedBranchModel = branchDetailModel;
getBranchCategories(); getBranchCategories();
notifyListeners(); notifyListeners();
} }
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) { updateAppointmentStatus(Map<String, dynamic> map,{bool isNeedToRebuild = false}) async {
for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) { if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("appointment status updated");
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
updateAppointmentPaymentStatus(Map<String, dynamic> map,{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("payment status updated");
} else {
Utils.showToast(genericRespModel.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
}
}
updateSelectedAppointmentDate(
{required int dateIndex, required int scheduleIndex}) {
for (var element in serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList!) {
element.date!.isSelected = false; 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();
} }
@ -314,7 +510,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;
@ -329,19 +527,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();
} }
@ -397,7 +604,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);
@ -410,14 +618,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 = "";
@ -430,7 +640,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;
} }
@ -472,7 +684,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,
@ -483,7 +696,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,
@ -499,19 +713,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) ...[
@ -520,15 +742,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),
], ],
), ),
], ],
@ -541,11 +768,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),
], ],
) )
], ],
@ -565,7 +799,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 {
@ -573,7 +808,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;
@ -582,7 +819,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);
@ -601,30 +839,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 = [];
@ -641,14 +885,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);
@ -656,29 +902,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);

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

@ -12,8 +12,8 @@ void showMyBottomSheet(BuildContext context, {bool isDismissible = true, require
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topRight: Radius.circular(25), topRight: Radius.circular(0),
topLeft: Radius.circular(25), topLeft: Radius.circular(0),
), ),
), ),
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,

@ -7,8 +7,15 @@ class FiltersList extends StatelessWidget {
final List<FilterListModel> filterList; final List<FilterListModel> filterList;
final Function(int, int) onFilterTapped; final Function(int, int) onFilterTapped;
final bool needLeftPadding; final bool needLeftPadding;
EdgeInsets? padding;
const FiltersList({Key? key, required this.filterList, this.needLeftPadding = true, required this.onFilterTapped}) : super(key: key); FiltersList({
Key? key,
this.padding,
required this.filterList,
this.needLeftPadding = true,
required this.onFilterTapped,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -16,7 +23,7 @@ class FiltersList extends StatelessWidget {
height: 37, height: 37,
width: double.infinity, width: double.infinity,
child: ListView.builder( child: ListView.builder(
padding: EdgeInsets.only(left: needLeftPadding ? 12 : 0), padding: padding ?? EdgeInsets.only(left: needLeftPadding ? 12 : 0),
itemCount: filterList.length, itemCount: filterList.length,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
@ -29,15 +36,20 @@ class FiltersList extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
margin: const EdgeInsets.symmetric(horizontal: 4), margin: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: filterList[index].isSelected ? MyColors.darkIconColor : null, color: filterList[index].isSelected
? MyColors.darkIconColor
: null,
border: Border.all( border: Border.all(
color: filterList[index].isSelected ? MyColors.darkIconColor : MyColors.primaryColor, color: filterList[index].isSelected
? MyColors.darkIconColor
: MyColors.primaryColor,
width: 2, width: 2,
), ),
), ),
child: filterList[index].title.toText( child: filterList[index].title.toText(
fontSize: 12, fontSize: 12,
color: filterList[index].isSelected ? MyColors.white : null, color:
filterList[index].isSelected ? MyColors.white : null,
), ),
), ),
); );

@ -93,10 +93,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.1" version: "1.18.0"
country_code_picker: country_code_picker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -513,10 +513,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.0" version: "0.18.1"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -601,26 +601,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.15" version: "0.12.16"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" 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"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.10.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -781,6 +789,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.6" version: "2.1.6"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -861,6 +877,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.1"
shelf:
dependency: transitive
description:
name: shelf
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev"
source: hosted
version: "1.4.1"
shimmer: shimmer:
dependency: "direct main" dependency: "direct main"
description: description:
@ -869,14 +893,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
signalr_core: signalr_netcore:
dependency: "direct main" dependency: "direct main"
description: description:
name: signalr_core name: signalr_netcore
sha256: dca676372a00c051511591ed0e24521ff7aa4e9320a7fa778a1007f7f522c8c0 sha256: "8f84b4b516c03f3a6872f94e9729d1441d5d223a77c81d0a7d7dae5dd0ce1f2f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.3.6"
simple_gesture_detector: simple_gesture_detector:
dependency: transitive dependency: transitive
description: description:
@ -902,10 +926,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.10.0"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
@ -922,30 +946,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.0" version: "2.5.0"
sse_client: sse:
dependency: transitive
description:
name: sse
sha256: "3ff9088cac3f45aa8b91336f1962e3ea6c81baaba0bbba361c05f8aa7fb59442"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
sse_channel:
dependency: transitive dependency: transitive
description: description:
name: sse_client name: sse_channel
sha256: "71bd826430b41ab20a69d85bf2dfe9f11cfe222938e681ada1aea71fc8adf348" sha256: ba2b1382b9423c58fa83e1f01a3a40fbaa16a0594aa984870c88bad0b45d4ca4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.0" version: "0.0.3"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.0" version: "1.11.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
stream_transform: stream_transform:
dependency: transitive dependency: transitive
description: description:
@ -990,10 +1022,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.6.1"
tuple: tuple:
dependency: transitive dependency: transitive
description: description:
@ -1098,6 +1130,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" 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: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@ -1131,5 +1171,5 @@ packages:
source: hosted source: hosted
version: "6.3.0" version: "6.3.0"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.2.0-194.0.dev <4.0.0"
flutter: ">=3.10.0" flutter: ">=3.10.0"

@ -41,6 +41,7 @@ dependencies:
intl: any intl: any
signalr_core: ^1.1.1 signalr_core: ^1.1.1
logging: ^1.2.0 logging: ^1.2.0
percent_indicator: ^4.2.3
# google # google

Loading…
Cancel
Save