Appointment implementation in Provider

mirza_development
Mirza.Shafique@cloudsolutions.com.sa 2 years ago
parent 5999804bc6
commit 4962ea2d8b

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

@ -231,10 +231,10 @@ extension AppointmentStatusToInt on AppointmentStatusEnum {
case AppointmentStatusEnum.upcoming:
return 6;
case AppointmentStatusEnum.inProgress:
case AppointmentStatusEnum.workStarted:
return 7;
case AppointmentStatusEnum.completed:
case AppointmentStatusEnum.visitCompleted:
return 8;
default:
@ -243,7 +243,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: 6 is service Deactivated
extension AppointmentEnum on int {
AppointmentStatusEnum toAppointmentStatusEnum() {
if (this == 1) {
@ -259,9 +293,9 @@ extension AppointmentEnum on int {
} else if (this == 6) {
return AppointmentStatusEnum.upcoming;
} else if (this == 7) {
return AppointmentStatusEnum.inProgress;
return AppointmentStatusEnum.workStarted;
} else if (this == 8) {
return AppointmentStatusEnum.completed;
return AppointmentStatusEnum.visitCompleted;
} else {
return AppointmentStatusEnum.allAppointments;
}
@ -271,7 +305,7 @@ extension AppointmentEnum on int {
extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
int getIdFromAppointmentPaymentStatusEnum() {
switch (this) {
case AppointmentPaymentStatusEnum.notConfirmed:
case AppointmentPaymentStatusEnum.defaultStatus:
return 1;
case AppointmentPaymentStatusEnum.payNow:
@ -295,7 +329,7 @@ extension AppointmentPaymentStatusToInt on AppointmentPaymentStatusEnum {
extension AppointmentPaymentEnum on int {
AppointmentPaymentStatusEnum toAppointmentPaymentStatusEnum() {
if (this == 1) {
return AppointmentPaymentStatusEnum.notConfirmed;
return AppointmentPaymentStatusEnum.defaultStatus;
} else if (this == 2) {
return AppointmentPaymentStatusEnum.payNow;
} else if (this == 3) {
@ -305,7 +339,7 @@ extension AppointmentPaymentEnum on int {
} else if (this == 5) {
return AppointmentPaymentStatusEnum.payPartial;
} else {
return AppointmentPaymentStatusEnum.notConfirmed;
return AppointmentPaymentStatusEnum.defaultStatus;
}
}
}

@ -24,13 +24,15 @@ class AppointmentListModel {
int? servicePaymentStatus;
double? totalAmount;
double? remainingAmount;
bool? isSelected;
bool? isMerged;
AppointmentStatusEnum? appointmentStatusEnum;
AppointmentPaymentStatusEnum? appointmentPaymentStatusEnum;
List<ServiceModel>? appointmentServicesList;
List<AppointmentListModel>? customerAppointmentList;
List<MergeAppointmentList>? mergeAppointmentList;
AppointmentListModel(
{this.id,
AppointmentListModel({this.id,
this.serviceSlotID,
this.appointmentStatusID,
this.appointmentStatusText,
@ -50,9 +52,10 @@ class AppointmentListModel {
this.servicePaymentStatus,
this.totalAmount,
this.remainingAmount,
this.isSelected,
this.appointmentDate,
this.appointmentServicesList,
this.customerAppointmentList});
this.customerAppointmentList, this.mergeAppointmentList,});
@override
String toString() {
@ -81,6 +84,7 @@ class AppointmentListModel {
servicePaymentStatus = json['servicePaymentStatus'];
totalAmount = json['amountTotal'];
remainingAmount = json['amountRem'];
isSelected = false;
appointmentStatusEnum =
(json['appointmentStatusID'] as int).toAppointmentStatusEnum();
appointmentPaymentStatusEnum =
@ -93,6 +97,10 @@ class AppointmentListModel {
.add(ServiceModel.fromJson(v, isForAppointment: true));
});
}
mergeAppointmentList =
json["mergeAppointmentList"] == null ? [] : List<MergeAppointmentList>.from(
json["mergeAppointmentList"]!.map((x) =>
MergeAppointmentList.fromJson(x)));
}
}
@ -102,8 +110,7 @@ class ServiceAppointmentItems {
String? serviceItemName;
String? serviceItemDescription;
ServiceAppointmentItems(
{this.id,
ServiceAppointmentItems({this.id,
this.serviceItemID,
this.serviceItemName,
this.serviceItemDescription});
@ -131,8 +138,34 @@ class CustomerData {
final String customerName;
final List<AppointmentListModel> appointmentList;
CustomerData(
{required this.customerID,
CustomerData({required this.customerID,
required this.customerName,
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(
Map<String, dynamic> map);
Future<MResponse> updateAppointmentStatus(
Map<String, dynamic> map);
Future<MResponse> updateAppointmentStatus(Map<String, dynamic> map);
Future<MResponse> updateAppointmentPaymentStatus(
Map<String, dynamic> map);
Future<MResponse> updateAppointmentPaymentStatus(Map<String, dynamic> map);
Future<MResponse> getAppointmentSlots(Map<String, dynamic> map);
Future<MResponse> createMergeAppointment(Map<String, dynamic> map);
Future<Services> getAllServices(String branchId);
Future<MResponse> createSchedule(Map map);
@ -141,7 +141,8 @@ class AppointmentRepoImp implements AppointmentRepo {
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleModel =
List.generate(
adsGenericModel.data.length,
(index) => ServiceAppointmentScheduleModel.fromJson(
(index) =>
ServiceAppointmentScheduleModel.fromJson(
adsGenericModel.data[index],
isForAppointment: true));
return serviceAppointmentScheduleModel;
@ -218,7 +219,8 @@ class AppointmentRepoImp implements AppointmentRepo {
);
List<AppointmentListModel> appointmentList = List.generate(
genericRespModel.data.length,
(index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
(index) =>
AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList;
}
@ -238,10 +240,12 @@ class AppointmentRepoImp implements AppointmentRepo {
}
@override
Future<MResponse> updateAppointmentPaymentStatus(Map<String, dynamic> map) async {
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,
(json) => MResponse.fromJson(json),
ApiConsts.updateAppointmentPaymentStatus, map,
token: t);
}
@ -249,7 +253,17 @@ class AppointmentRepoImp implements AppointmentRepo {
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,
(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);
}
}

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

@ -83,13 +83,16 @@ class AppointmentsVM extends BaseVM {
appointmentsFilterOptions.add(
FilterListModel(id: 0, title: "All Appointments", isSelected: true));
appointmentsFilterOptions
.add(FilterListModel(id: 6, title: "Upcoming", isSelected: false));
.add(FilterListModel(id: 2, title: "Confirmed", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 3, title: "Arrived", isSelected: false));
appointmentsFilterOptions
.add(FilterListModel(id: 7, title: "In Progress", isSelected: false));
.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 {
@ -330,6 +333,7 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
findAppointmentsBasedOnCustomers() {
// Use a Set to ensure uniqueness of customerIDs
Set<int> uniqueCustomerIDs = Set<int>();
@ -401,15 +405,15 @@ class AppointmentsVM extends BaseVM {
myAppointments = await scheduleRepo.getMyAppointments(map);
myFilteredAppointments = myAppointments;
// myUpComingAppointments = myAppointments
// .where((element) =>
// element.appointmentStatusEnum == AppointmentStatusEnum.booked)
// .toList();
setState(ViewState.idle);
myUpComingAppointments = myAppointments
.where((element) =>
element.appointmentStatusEnum == AppointmentStatusEnum.booked)
.toList();
applyFilterOnAppointmentsVM(
appointmentStatusEnum: AppointmentStatusEnum.allAppointments,
isNeedCustomerFilter: true);
notifyListeners();
setState(ViewState.idle);
}
updateSelectedBranch(BranchDetailModel branchDetailModel) {
@ -418,10 +422,12 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
updateAppointmentStatus(Map<String, dynamic> map,{bool isNeedToRebuild = false}) async {
updateAppointmentStatus(Map<String, dynamic> map,
{bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map);
MResponse genericRespModel =
await scheduleRepo.updateAppointmentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("appointment status updated");
@ -433,10 +439,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);
try {
MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map);
MResponse genericRespModel =
await scheduleRepo.updateAppointmentPaymentStatus(map);
if (genericRespModel.messageStatus == 1) {
Utils.showToast("payment status updated");
@ -448,6 +456,42 @@ class AppointmentsVM extends BaseVM {
}
}
Future<MResponse> createMergeAppointment(Map<String, dynamic> map,
{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]

@ -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:provider/provider.dart';
//TODO: Need to make onTapped dynamic
class CustomerAppointmentSliderWidget extends StatelessWidget {
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
Widget build(BuildContext context) {
if (myUpComingAppointments.isEmpty) {
if (isNeedToShowEmptyMessage)
return "No Upcoming Appointment Available".toText().paddingAll(21);
return CustomAddButton(
needsBorder: true,
bgColor: MyColors.white,
@ -29,7 +38,8 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
icon: Container(
height: 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),
),
).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21));
@ -41,7 +51,8 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
Container(
height: 24,
width: 24,
decoration: BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor),
decoration: BoxDecoration(
shape: BoxShape.circle, color: MyColors.darkTextColor),
child: Icon(
Icons.add,
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(
options: CarouselOptions(
@ -65,10 +78,15 @@ class CustomerAppointmentSliderWidget extends StatelessWidget {
enableInfiniteScroll: false,
),
itemCount: myUpComingAppointments.length,
itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) => BuildAppointmentContainerForCustomer(
itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) =>
BuildAppointmentContainerForCustomer(
isForHome: true,
appointmentListModel: myUpComingAppointments[itemIndex],
onTapped: () => navigateWithName(context, AppRoutes.appointmentDetailView, arguments: myUpComingAppointments[itemIndex]),
onTapped: isNeedToShowEmptyMessage
? onAppointmentClick!
: () =>
navigateWithName(context, AppRoutes.appointmentDetailView,
arguments: myUpComingAppointments[itemIndex]),
),
);
}
@ -79,7 +97,11 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
final AppointmentListModel? appointmentListModel;
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}) {
return Row(
@ -99,15 +121,18 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
);
}
List<Widget> buildServicesFromAppointment({required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null || appointmentListModel.appointmentServicesList!.isEmpty) {
List<Widget> buildServicesFromAppointment(
{required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null ||
appointmentListModel.appointmentServicesList!.isEmpty) {
return [SizedBox()];
}
if (appointmentListModel.appointmentServicesList!.length == 1) {
return [
showServices(
appointmentListModel.appointmentServicesList![0].providerServiceDescription,
appointmentListModel
.appointmentServicesList![0].providerServiceDescription,
MyAssets.modificationsIcon,
)
];
@ -115,7 +140,11 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
List<Widget> servicesList = List.generate(
2,
(index) => showServices(appointmentListModel.appointmentServicesList![index].providerServiceDescription, MyAssets.modificationsIcon),
(index) =>
showServices(
appointmentListModel
.appointmentServicesList![index].providerServiceDescription,
MyAssets.modificationsIcon),
);
if (appointmentListModel.appointmentServicesList!.length > 1) {
@ -158,12 +187,16 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(appointmentListModel!.providerName ?? "").toText(color: MyColors.black, isBold: true, fontSize: 16),
(appointmentListModel!.providerName ?? "").toText(
color: MyColors.black, isBold: true, fontSize: 16),
Row(
children: [
MyAssets.miniClock.buildSvg(height: 12),
2.width,
"${appointmentListModel!.duration ?? ""} ${appointmentListModel!.appointmentDate!.toFormattedDateWithoutTime()}".toText(
"${appointmentListModel!.duration ??
""} ${appointmentListModel!.appointmentDate!
.toFormattedDateWithoutTime()}"
.toText(
color: MyColors.lightTextColor,
fontSize: 12,
),
@ -189,7 +222,9 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
children: [
Expanded(
child: Column(
children: buildServicesFromAppointment(appointmentListModel: appointmentListModel!),
children: buildServicesFromAppointment(
appointmentListModel:
appointmentListModel!),
),
),
const Icon(
@ -203,7 +238,9 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
],
),
],
).onPress(onTapped).toWhiteContainer(width: double.infinity, allPading: 12),
)
.onPress(onTapped)
.toWhiteContainer(width: double.infinity, allPading: 12),
);
}
}

Loading…
Cancel
Save