From 8a93c82b226ff9c397fe2d3ec5d106862362ad3c Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Wed, 1 Jan 2025 17:34:04 +0300 Subject: [PATCH] Quick Fixes --- .../add_new_service_appointment_page.dart | 303 ++++++++++++------ .../appoinment_detail_list_page.dart | 20 +- lib/views/appoinments/appointment_page.dart | 189 +++++------ .../appoinments/merge_appointment_page.dart | 16 +- .../appoinments/update_appointment_page.dart | 8 +- .../schedule/schedules_list_page.dart | 2 +- .../services/create_services_page3.dart | 32 +- .../services/services_list_page.dart | 42 ++- .../fragments/appoinment_fragment.dart | 222 ------------- .../widget/general_appointment_widget.dart | 2 +- 10 files changed, 377 insertions(+), 459 deletions(-) delete mode 100644 lib/views/dashboard/fragments/appoinment_fragment.dart diff --git a/lib/views/appoinments/add_new_service_appointment_page.dart b/lib/views/appoinments/add_new_service_appointment_page.dart index 5db5e58..1227a7b 100644 --- a/lib/views/appoinments/add_new_service_appointment_page.dart +++ b/lib/views/appoinments/add_new_service_appointment_page.dart @@ -1,9 +1,11 @@ import 'dart:async'; import 'dart:developer'; +import 'package:car_provider_app/main.dart'; import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart'; import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; +import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/view_models/service_view_model.dart'; @@ -26,6 +28,7 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/empty_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -107,102 +110,162 @@ class _AddNewServiceAppointmentPageState extends State( - builder: (context, serviceVm, _) { + builder: (context, ServiceVM serviceVm, _) { return Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - LocaleKeys.selectServicestoAdd.tr().toText( - fontSize: 18, - isBold: true, - ), - 12.height, - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - serviceVm.categoryDropList.isNotEmpty - ? DropdownField( - (DropValue value) async { - category = value; - service = null; - serviceVm.fetchProviderServices(widget.appointmentListModel.branchId.toString(), value.id.toString()); - }, - dropdownValue: category, - list: serviceVm.categoryDropList, - hint: LocaleKeys.selectServiceCategory.tr(), - ) - : const Center( - child: CircularProgressIndicator(), - ), - 12.height, - serviceVm.servicesDropList.isNotEmpty - ? DropdownField( - (DropValue value) { - service = value; - pickedItems = null; - serviceVm.setState(ViewState.idle); - openItemsSelectionBottomSheet(); - }, - dropdownValue: service, - list: serviceVm.servicesDropList, - hint: LocaleKeys.defineServices.tr(), - ) - : category == null - ? Container() - : serviceVm.services != null && serviceVm.servicesDropList.isEmpty - ? EmptyWidget(text: LocaleKeys.noServicesAvailable.tr()) - : const CircularProgressIndicator(), - 12.height, - (service != null && pickedItems != null && pickedItems!.isNotEmpty) - ? ChipsPickerItem( - hint: LocaleKeys.selectItems.tr(), - itemsList: [...pickedItems ?? []], - onClick: () { - openItemsSelectionBottomSheet(); - }, - ) - : service != null - ? EmptyWidget(text: LocaleKeys.noItemSelectedYet.tr()) - : const SizedBox(), - if ((service != null && pickedItems != null && pickedItems!.isNotEmpty)) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 16.height, - LocaleKeys.totalAdditionalAmount.tr().toText( - fontSize: 14, - isBold: true, - color: MyColors.lightTextColor, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - totalPrice.toString().toText( - fontSize: 29, - isBold: true, - ), - 2.width, - LocaleKeys.sar - .tr() - .toText( - fontSize: 16, - isBold: true, - color: MyColors.lightTextColor, - ) - .paddingOnly(bottom: 5), - ], - ), - 10.height, - ], - ), - ], + LocaleKeys.customService.tr().toText(fontSize: 18), + 8.width, + Center( + child: Checkbox( + value: serviceVm.customServiceEnabledStatus, + onChanged: (value) { + serviceVm.updateCustomServiceEnabledStatus(value ?? false); // update the status + }, + activeColor: MyColors.darkPrimaryColor, + checkColor: MyColors.white, + fillColor: serviceVm.customServiceEnabledStatus ? WidgetStateProperty.all(MyColors.darkPrimaryColor) : WidgetStateProperty.all(MyColors.white), + ), ), ], - ).toWhiteContainer(width: double.infinity, allPading: 12), + ), + 5.height, + if (serviceVm.customServiceEnabledStatus) ...[ + LocaleKeys.addServiceDetails.tr().toText(fontSize: 16), + 12.height, + Column( + children: [ + 8.height, + TxtField( + value: serviceVm.customServiceTitle, + errorValue: serviceVm.customServiceTitleError, + hint: LocaleKeys.serviceName.tr(), + onChanged: (v) => serviceVm.updateCustomServiceTitle(v), + ), + 8.height, + TxtField( + postfixWidget: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocaleKeys.sar.tr().toText(fontWeight: MyFonts.Medium, fontSize: 15, color: borderColor, textAlign: TextAlign.center), + ], + ), + value: serviceVm.customServicePrice, + errorValue: serviceVm.customServicePriceError, + keyboardType: TextInputType.number, + numbersOnly: true, + hint: LocaleKeys.price.tr(), + onChanged: (v) => serviceVm.updateCustomServicePrice(v), + ), + 8.height, + TxtField( + postfixWidget: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "%".toText(fontWeight: MyFonts.Medium, fontSize: 15, color: borderColor, textAlign: TextAlign.center), + ], + ), + isNeedClickAll: true, + isBackgroundEnabled: true, + hint: '', + onTap: () {}, + value: serviceVm.customerServiceTax, + errorValue: '', + keyboardType: TextInputType.number, + numbersOnly: true, + onChanged: (v) => serviceVm.updateCustomerServiceTax(v), + ), + ], + ), + ] else ...[ + LocaleKeys.selectServiceDetails.tr().toText(fontSize: 16), + 12.height, + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + serviceVm.categoryDropList.isNotEmpty + ? DropdownField( + (DropValue value) async { + category = value; + service = null; + serviceVm.fetchProviderServices(widget.appointmentListModel.branchId.toString(), value.id.toString()); + }, + dropdownValue: category, + list: serviceVm.categoryDropList, + hint: LocaleKeys.selectServiceCategory.tr(), + ) + : const Center( + child: CircularProgressIndicator(), + ), + 12.height, + serviceVm.servicesDropList.isNotEmpty + ? DropdownField( + (DropValue value) { + service = value; + pickedItems = null; + serviceVm.setState(ViewState.idle); + openItemsSelectionBottomSheet(); + }, + dropdownValue: service, + list: serviceVm.servicesDropList, + hint: LocaleKeys.defineServices.tr(), + ) + : category == null + ? Container() + : serviceVm.services != null && serviceVm.servicesDropList.isEmpty + ? EmptyWidget(text: LocaleKeys.noServicesAvailable.tr()) + : const CircularProgressIndicator(), + 12.height, + (service != null && pickedItems != null && pickedItems!.isNotEmpty) + ? ChipsPickerItem( + hint: LocaleKeys.selectItems.tr(), + itemsList: [...pickedItems ?? []], + onClick: () { + openItemsSelectionBottomSheet(); + }, + ) + : service != null + ? EmptyWidget(text: LocaleKeys.noItemSelectedYet.tr()) + : const SizedBox(), + if ((service != null && pickedItems != null && pickedItems!.isNotEmpty)) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 16.height, + LocaleKeys.totalAdditionalAmount.tr().toText( + fontSize: 14, + isBold: true, + color: MyColors.lightTextColor, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + totalPrice.toString().toText( + fontSize: 29, + isBold: true, + ), + 2.width, + LocaleKeys.sar + .tr() + .toText( + fontSize: 16, + isBold: true, + color: MyColors.lightTextColor, + ) + .paddingOnly(bottom: 5), + ], + ), + 10.height, + ], + ), + ], + ), + ], ], - ); + ).toWhiteContainer(width: double.infinity, allPading: 12); }, ), 55.height, @@ -226,6 +289,7 @@ class _AddNewServiceAppointmentPageState extends State items = []; - pickedItems?.forEach((element) { - items.add(element.id); - }); + Map postParams = {}; + if (serviceVM!.customServiceEnabledStatus) { + if (serviceVM!.isCustomServiceDetailValidated()) { + postParams = { + "providerBranchID": widget.appointmentListModel.branchId, + "appointmentID": widget.appointmentListModel.id, + "serviceItemsFreeText": [ + { + "name": serviceVM!.customServiceTitle, + "price": serviceVM!.customServicePrice, + "tax": serviceVM!.customerServiceTax, + } + ], + }; + } else { + return; + } + } else { + if (pickedItems != null && pickedItems!.isNotEmpty) { + List items = []; + pickedItems?.forEach((element) { + items.add(element.id); + }); + postParams = { + "providerBranchID": widget.appointmentListModel.branchId, + "appointmentID": widget.appointmentListModel.id, + "serviceItemID": items, + }; + } else { + Utils.showToast(LocaleKeys.pleaseSelectItems.tr()); + return; + } + } + + try { Utils.showLoading(context); - var postParams = { - "providerBranchID": widget.appointmentListModel.branchId, - "appointmentID": widget.appointmentListModel.id, - "serviceItemID": items, - }; GenericRespModel res = await serviceVM!.addNewServiceInAppointment(postParams); - _updateAppointment(context, widget.appointmentListModel.branchId ?? 0); Utils.hideLoading(context); if (res.messageStatus == 1) { + serviceVM!.resetCustomServiceForm(); + _updateAppointment(context, widget.appointmentListModel.branchId ?? 0); Utils.showToast(LocaleKeys.itemsAddedSuccessfully.tr()); pop(context); pop(context); } else { Utils.showToast(res.message.toString()); } - } else { - Utils.showToast(LocaleKeys.pleaseSelectItems.tr()); + } catch (e) { + Utils.showToast(e.toString()); + Utils.hideLoading(context); } }, ), @@ -273,6 +364,10 @@ class _AddNewServiceAppointmentPageState extends State _updateAppointment(BuildContext context, int branchId) async { - await context.read().getMyAppointmentsForProvider(branchID: branchId); + await context.read().applyFilterOnAppointmentsVMForProviders( + branchID: branchId, + appointmentStatusEnum: AppointmentStatusEnum.allAppointments, + isNeedCustomerFilter: true, + ); } } diff --git a/lib/views/appoinments/appoinment_detail_list_page.dart b/lib/views/appoinments/appoinment_detail_list_page.dart index deebb03..8708e75 100644 --- a/lib/views/appoinments/appoinment_detail_list_page.dart +++ b/lib/views/appoinments/appoinment_detail_list_page.dart @@ -55,28 +55,26 @@ class AppointmentDetailListPage extends StatelessWidget { return ListView.separated( itemBuilder: (context, index) { if (customerID == 0) { - customerID = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].customerID ?? 0; + customerID = appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].customerID ?? 0; } if (customerName.isEmpty) { - customerName = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].customerName ?? ""; + customerName = appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].customerName ?? ""; } return GeneralAppointmentWidget( - appointmentListModel: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index], + appointmentListModel: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index], isNeedTotalPayment: true, isNeedToShowAppointmentStatus: true, - isNeedToShowMergeStatus: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].isMerged ?? false, - onTap: () { - appointmentsVM.selectedAppointmentId = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].id ?? 0; + isNeedToShowMergeStatus: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].isMerged ?? false, + onTap: () { + appointmentsVM.selectedAppointmentId = appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].id ?? 0; appointmentsVM.selectedAppointmentSubIndex = index; navigateWithName(context, AppRoutes.updateAppointmentPage, - arguments: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index]); + arguments: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index]); }, ); }, - separatorBuilder: (context, snapchat) { - return 21.height; - }, - itemCount: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length, + separatorBuilder: (context, snapchat) => 21.height, + itemCount: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length, padding: const EdgeInsets.all(21), ); } diff --git a/lib/views/appoinments/appointment_page.dart b/lib/views/appoinments/appointment_page.dart index b3c005e..6968595 100644 --- a/lib/views/appoinments/appointment_page.dart +++ b/lib/views/appoinments/appointment_page.dart @@ -1,9 +1,5 @@ import 'dart:async'; - -import 'package:car_provider_app/config/provider_routes.dart'; import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart'; -import 'package:mc_common_app/classes/app_state.dart'; -import 'package:mc_common_app/config/dependency_injection.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; @@ -40,12 +36,16 @@ class _AppointmentPageState extends State { GlobalKey refreshIndicatorKey = GlobalKey(); Future _pullRefresh(BuildContext context) async { - await appointmentsVM.getAppointmentSlotsInfo( - context: context, - branchID: widget.branch.id!, - isNeedToRebuild: true, - ); - await appointmentsVM.getAppointmentsBasedOnFiltersForProviders(branchID: widget.branch.id!); + var futures = >[ + appointmentsVM.getAppointmentSlotsInfo(branchID: widget.branch.id!), + appointmentsVM.applyFilterOnAppointmentsVMForProviders( + appointmentStatusEnum: AppointmentStatusEnum.allAppointments, + isNeedCustomerFilter: true, + ), + ]; + + // Wait for both futures to complete + await Future.wait(futures); } @override @@ -88,69 +88,79 @@ class _AppointmentPageState extends State { width: double.infinity, height: double.infinity, child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { - if (appointmentsVM.state == ViewState.busy) { - return const Center(child: CircularProgressIndicator()); - } else { - return RefreshIndicator( - onRefresh: () => _pullRefresh(context), - key: refreshIndicatorKey, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - child: Column( - children: [ - progressWidget(context, appointmentsVM), - FiltersList( - filterList: appointmentsVM.appointmentsFilterOptions, - padding: const EdgeInsets.symmetric(horizontal: 18), - onFilterTapped: (index, selectedFilterId) { - appointmentsVM.applyFilterOnAppointmentsVM( - appointmentStatusEnum: selectedFilterId.toAppointmentStatusEnum(), - isNeedCustomerFilter: true, - ); - }, + return RefreshIndicator( + onRefresh: () => _pullRefresh(context), + key: refreshIndicatorKey, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + slotDetailsWidget(context, appointmentsVM), + FiltersList( + filterList: appointmentsVM.appointmentsFilterOptions, + padding: const EdgeInsets.symmetric(horizontal: 18), + onFilterTapped: (index, selectedFilterId) { + if (appointmentsVM.isAppointmentLoading) { + return; + } + appointmentsVM.applyFilterOnAppointmentsVMForProviders( + appointmentStatusEnum: selectedFilterId.toAppointmentStatusEnum(), + isNeedCustomerFilter: true, + ); + }, + ), + if (appointmentsVM.isAppointmentLoading) ...[ + const Column( + children: [ + SizedBox(height: 50), + Center(child: CircularProgressIndicator()), + ], ), - if (appointmentsVM.myFilteredAppointments2.isEmpty) - EmptyWidget( - spacerWidget: const SizedBox(height: 25), - text: LocaleKeys.noAppointmentFound.tr(), - ) - else ...[ - ListView.separated( - itemBuilder: (context, index) { - return GeneralAppointmentWidget( - isNeedToShowItems: true, - appointmentListModel: appointmentsVM.myFilteredAppointments2[index], - isNeedTotalPayment: false, - onTap: () { - appointmentsVM.selectedAppointmentIndex = index; - navigateWithName( - context, - AppRoutes.appointmentDetailList, - // arguments: appointmentsVM - // .myFilteredAppointments2[index] - // .customerAppointmentList, + ] else + ...[ + if (appointmentsVM.myFilteredAppointmentsForProvider.isEmpty) + EmptyWidget( + spacerWidget: const SizedBox(height: 25), + text: LocaleKeys.noAppointmentFound.tr(), + ) + else + ...[ + ListView.separated( + itemBuilder: (context, index) { + return GeneralAppointmentWidget( + isNeedToShowItems: true, + appointmentListModel: appointmentsVM.myFilteredAppointmentsForProvider[index], + isNeedTotalPayment: false, + onTap: () { + appointmentsVM.selectedAppointmentIndex = index; + navigateWithName( + context, + AppRoutes.appointmentDetailList, + ); + }, ); }, - ); - }, - separatorBuilder: (context, snapchat) => 21.height, - itemCount: appointmentsVM.myFilteredAppointments2.length, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: const EdgeInsets.all(21), - ), + separatorBuilder: (context, snapchat) => 21.height, + itemCount: appointmentsVM.myFilteredAppointmentsForProvider.length, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.all(21), + ), + ], ], - ], - ), + ], ), - ); - } + ), + ); }), ), ); } - Widget progressWidget(BuildContext context, AppointmentsVM appointmentsVM) { + Widget slotDetailsWidget(BuildContext context, AppointmentsVM appointmentsVM) { + if (appointmentsVM.isSlotsLoading) { + return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator())); + } double percent = 0.0; if (appointmentsVM.appointmentSlots != null) { percent = appointmentsVM.appointmentSlots!.occupiedSlots / appointmentsVM.appointmentSlots!.totalSlots; @@ -161,9 +171,9 @@ class _AppointmentPageState extends State { children: [ Expanded( child: LocaleKeys.slotsOverview.tr().toText( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + fontSize: 16, + fontWeight: FontWeight.bold, + ), ), Row( children: [ @@ -184,14 +194,13 @@ class _AppointmentPageState extends State { vertical: 6, ), ) - .onPress(() async { - String date = await Utils.pickDateFromDatePicker( - context, - firstDate: null, - ); - appointmentsVM.selectedDateForAppointments = date; - _pullRefresh(context); - }), + .onPress( + () async { + String date = await Utils.pickDateFromDatePicker(context, firstDate: DateTime(2023)); + appointmentsVM.selectedDateForAppointments = date; + await appointmentsVM.getAppointmentSlotsInfo(branchID: widget.branch.id!); + }, + ), ], ), 24.height, @@ -209,15 +218,15 @@ class _AppointmentPageState extends State { color: MyColors.lightGreyEAColor, ), 4.width, - (LocaleKeys.empty.tr() + ":").toText( + ("${LocaleKeys.empty.tr()}:").toText( fontSize: 8, color: Colors.white, ), (appointmentsVM.appointmentSlots?.emptySlots ?? 0).toString().toText( - fontSize: 9, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + fontSize: 9, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ], ).toContainer( backgroundColor: MyColors.darkIconColor, @@ -231,15 +240,15 @@ class _AppointmentPageState extends State { color: MyColors.darkPrimaryColor, ), 4.width, - (LocaleKeys.occupied.tr() + ":").toText( + ("${LocaleKeys.occupied.tr()}:").toText( fontSize: 8, color: Colors.white, ), (appointmentsVM.appointmentSlots?.occupiedSlots ?? 0).toString().toText( - fontSize: 9, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + fontSize: 9, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ], ).toContainer( backgroundColor: MyColors.darkIconColor, @@ -255,13 +264,13 @@ class _AppointmentPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ LocaleKeys.totalSlots.tr().toText( - fontSize: 13, - fontWeight: FontWeight.bold, - ), + fontSize: 13, + fontWeight: FontWeight.bold, + ), (appointmentsVM.appointmentSlots?.totalSlots ?? 0).toString().toText( - fontSize: 24, - fontWeight: FontWeight.bold, - ), + fontSize: 24, + fontWeight: FontWeight.bold, + ), ], ), backgroundColor: MyColors.lightGreyEAColor, diff --git a/lib/views/appoinments/merge_appointment_page.dart b/lib/views/appoinments/merge_appointment_page.dart index 91479f0..31e3a87 100644 --- a/lib/views/appoinments/merge_appointment_page.dart +++ b/lib/views/appoinments/merge_appointment_page.dart @@ -42,7 +42,7 @@ class MergeAppointmentListPage extends StatelessWidget { : ListView.separated( itemBuilder: (context, index) { return GeneralAppointmentWidget( - appointmentListModel: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index], + appointmentListModel: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index], isNeedTotalPayment: true, isSelectable: true, isNeedToShowAppointmentStatus: true, @@ -55,7 +55,7 @@ class MergeAppointmentListPage extends StatelessWidget { separatorBuilder: (context, snapchat) { return 21.height; }, - itemCount: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length, + itemCount: appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length, padding: const EdgeInsets.all(21), ), ), @@ -72,14 +72,14 @@ class MergeAppointmentListPage extends StatelessWidget { Utils.showLoading(context); List appointmentIDs = []; - for (var element in appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!) { + for (var element in appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!) { if (element.isSelected ?? false) { appointmentIDs.add(element.id ?? 0); } } Map map = { "serviceProviderID": injector.get().getUser.data?.userInfo?.providerId.toString() ?? "0", - "serviceProviderBranchID": appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].branchId, + "serviceProviderBranchID": appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].branchId, "serviceAppointmentIDs": appointmentIDs }; @@ -89,7 +89,7 @@ class MergeAppointmentListPage extends StatelessWidget { if (response.messageStatus == 1) { Utils.showToast(LocaleKeys.appointmentMergeSuccessfully.tr()); - _updateAppointment(context, appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].branchId ?? 0); + _updateAppointment(context, appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].branchId ?? 0); pop(context); pop(context); @@ -111,6 +111,10 @@ class MergeAppointmentListPage extends StatelessWidget { } Future _updateAppointment(BuildContext context, int branchId) async { - await context.read().getMyAppointmentsForProvider(branchID: branchId); + await context.read().applyFilterOnAppointmentsVMForProviders( + branchID: branchId, + appointmentStatusEnum: AppointmentStatusEnum.allAppointments, + isNeedCustomerFilter: true, + ); } } diff --git a/lib/views/appoinments/update_appointment_page.dart b/lib/views/appoinments/update_appointment_page.dart index db2c2a0..02aa39f 100644 --- a/lib/views/appoinments/update_appointment_page.dart +++ b/lib/views/appoinments/update_appointment_page.dart @@ -37,7 +37,7 @@ class _UpdateAppointmentPageState extends State { width: double.infinity, height: double.infinity, child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { - appointmentListModel = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![appointmentsVM.selectedAppointmentSubIndex]; + appointmentListModel = appointmentsVM.myFilteredAppointmentsForProvider[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![appointmentsVM.selectedAppointmentSubIndex]; if (appointmentsVM.state == ViewState.busy) { return const Center(child: CircularProgressIndicator()); } else { @@ -313,6 +313,10 @@ class _UpdateAppointmentPageState extends State { } Future _updateAppointment(BuildContext context, int branchId) async { - await context.read().getMyAppointmentsForProvider(branchID: branchId); + await context.read().applyFilterOnAppointmentsVMForProviders( + branchID: branchId, + appointmentStatusEnum: AppointmentStatusEnum.allAppointments, + isNeedCustomerFilter: true, + ); } } diff --git a/lib/views/branch_management/schedule/schedules_list_page.dart b/lib/views/branch_management/schedule/schedules_list_page.dart index fd306bb..c5d96a3 100644 --- a/lib/views/branch_management/schedule/schedules_list_page.dart +++ b/lib/views/branch_management/schedule/schedules_list_page.dart @@ -161,7 +161,7 @@ class _SchedulesListPageState extends State { onPressed: () { navigateWithName(context, AppRoutes.addSchedule, arguments: ScheduleData(branchId: widget.branchId ?? "")); }, - ), + ), ], ), ), diff --git a/lib/views/branch_management/services/create_services_page3.dart b/lib/views/branch_management/services/create_services_page3.dart index 6938ba6..9d5427b 100644 --- a/lib/views/branch_management/services/create_services_page3.dart +++ b/lib/views/branch_management/services/create_services_page3.dart @@ -374,38 +374,46 @@ class _CreateServicesPage3State extends State { } } - Future updateServiceStatus(BuildContext context, bool value) async { + Future updateServiceStatus(BuildContext context, bool isServiceActive) async { try { final serviceVM = context.read(); - List list = await serviceVM.getAppointmentsByServiceID( - context: context, - branchId: int.parse(widget.branchModel!.branchId), - serviceId: widget.branchModel!.serviceProviderService!.serviceProviderServiceId!, - ); - List providerServiceIds = []; - providerServiceIds.add(widget.branchModel!.serviceProviderService!.serviceProviderServiceId!); + List list = []; + + if (!isServiceActive) { + list = await serviceVM.getAppointmentsByCategoryOrService( + context: context, + branchId: int.parse(widget.branchModel!.branchId), + serviceId: widget.branchModel!.serviceProviderService!.serviceProviderServiceId!, + categoryId: -1, // -1 means it check appointment by by service + ); + } + if (list.isEmpty) { + List providerServiceIds = []; + providerServiceIds.add(widget.branchModel!.serviceProviderService!.serviceProviderServiceId!); + bool status = await serviceVM.updateServiceStatus( context: context, - serviceStatusEnum: value ? ServiceStatusEnum.approvedOrActive : ServiceStatusEnum.deactivated, + serviceStatusEnum: isServiceActive ? ServiceStatusEnum.approvedOrActive : ServiceStatusEnum.deactivated, branchId: int.parse(widget.branchModel!.branchId), providerServiceIds: providerServiceIds, ); return status; } else { - serviceVM.buildDealNotCompletedBottomSheetOptions( + serviceVM.cannotDeactivateServiceOrCategoryBottomSheet( mainContext: context, appointments: list, branchName: widget.branchModel!.branchName, + isService: true, ); + return !isServiceActive; } - return value; } catch (e) { Utils.hideLoading(context); log(e.toString()); Utils.showToast(e.toString()); - return value; + return !isServiceActive; } } } diff --git a/lib/views/branch_management/services/services_list_page.dart b/lib/views/branch_management/services/services_list_page.dart index d4803f9..c8c126b 100644 --- a/lib/views/branch_management/services/services_list_page.dart +++ b/lib/views/branch_management/services/services_list_page.dart @@ -11,6 +11,7 @@ import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/appointments_models/appointment_basic_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -164,6 +165,7 @@ class _ServicesListPageState extends State { isCategoryActive: value, categoryId: categoryData.id!, branchId: int.parse(categoryData.branchId!), + branchName: categoryData.branchName ?? "", ); if (status) { @@ -182,16 +184,36 @@ class _ServicesListPageState extends State { ).toWhiteContainer(width: double.infinity, allPading: 12); } - Future updateCategoryStatus({required bool isCategoryActive, required int categoryId, required int branchId}) async { - final serviceVM = context.read(); - bool status = await serviceVM.updateCategoryStatus( - context: context, - serviceStatusEnum: isCategoryActive ? ServiceStatusEnum.approvedOrActive : ServiceStatusEnum.deactivated, - branchId: branchId, - categoryId: categoryId, - ); - - return status; + Future updateCategoryStatus({required bool isCategoryActive, required int categoryId, required int branchId, required String branchName}) async { + try { + final serviceVM = context.read(); + List list = []; + if (isCategoryActive) { + list = await serviceVM.getAppointmentsByCategoryOrService( + context: context, + branchId: branchId, + serviceId: -1, // -1 means check appointment by CategoryId + categoryId: categoryId, + ); + } + if (list.isEmpty) { + bool status = await serviceVM.updateCategoryStatus( + context: context, + serviceStatusEnum: isCategoryActive ? ServiceStatusEnum.approvedOrActive : ServiceStatusEnum.deactivated, + branchId: branchId, + categoryId: categoryId, + ); + return status; + } else { + serviceVM.cannotDeactivateServiceOrCategoryBottomSheet(mainContext: context, appointments: list, branchName: branchName, isService: false); + return !isCategoryActive; + } + } catch (e) { + Utils.hideLoading(context); + log(e.toString()); + Utils.showToast(e.toString()); + return !isCategoryActive; + } } @override diff --git a/lib/views/dashboard/fragments/appoinment_fragment.dart b/lib/views/dashboard/fragments/appoinment_fragment.dart deleted file mode 100644 index 3f2f133..0000000 --- a/lib/views/dashboard/fragments/appoinment_fragment.dart +++ /dev/null @@ -1,222 +0,0 @@ -// import 'package:car_provider_app/config/provider_routes.dart'; -// import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart'; -// import 'package:mc_common_app/classes/app_state.dart'; -// import 'package:mc_common_app/config/dependency_injection.dart'; -// import 'package:mc_common_app/extensions/string_extensions.dart'; -// import 'package:mc_common_app/generated/locale_keys.g.dart'; -// import 'package:mc_common_app/theme/colors.dart'; -// import 'package:mc_common_app/utils/date_helper.dart'; -// import 'package:mc_common_app/utils/navigator.dart'; -// import 'package:mc_common_app/utils/utils.dart'; -// import 'package:mc_common_app/view_models/appointments_view_model.dart'; -// import 'package:mc_common_app/widgets/common_widgets/categories_list.dart'; -// import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; -// import 'package:flutter/material.dart'; -// import 'package:mc_common_app/extensions/int_extensions.dart'; -// import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; -// import 'package:percent_indicator/percent_indicator.dart'; -// import 'package:provider/provider.dart'; -// import 'package:easy_localization/easy_localization.dart'; -// -// class AppointmentFragment extends StatelessWidget { -// String date = ""; -// final VoidCallback onBackButtonTapped; -// -// AppointmentFragment({Key? key, required this.onBackButtonTapped}) : super(key: key); -// -// GlobalKey refreshIndicatorKey = GlobalKey(); -// -// Future _pullRefresh(BuildContext context) async { -// await context.read().getMyAppointmentsForProvider({"ServiceProviderID": injector.get().getUser.data?.userInfo?.providerId.toString() ?? "0"}); -// } -// -// @override -// Widget build(BuildContext context) { -// date = DateHelper.formatAsDayMonthYear(DateTime.now()); -// return Scaffold( -// appBar: CustomAppBar( -// //profileImageUrl: MyAssets.carBanner, -// title: LocaleKeys.appointments.tr(), -// onBackButtonTapped: onBackButtonTapped, -// actions: [ -// IconButton( -// onPressed: () {}, -// icon: const Icon(Icons.search), -// ), -// 10.width, -// ], -// ), -// body: SizedBox( -// width: double.infinity, -// height: double.infinity, -// child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { -// return RefreshIndicator( -// onRefresh: () => _pullRefresh(context), -// key: refreshIndicatorKey, -// child: SingleChildScrollView( -// physics: const AlwaysScrollableScrollPhysics(), -// child: Column( -// children: [ -// progressWidget(context), -// FiltersList( -// filterList: appointmentsVM.appointmentsFilterOptions, -// padding: const EdgeInsets.symmetric(horizontal: 18), -// onFilterTapped: (index, selectedFilterId) { -// appointmentsVM.applyFilterOnAppointmentsVM( -// appointmentStatusEnum: selectedFilterId.toAppointmentStatusEnum(), -// ); -// }, -// ), -// ListView.separated( -// itemBuilder: (context, index) { -// return AppointmentSliderWidget( -// appointmentListModel: appointmentsVM.myFilteredAppointments2[index], -// isNeedTotalPayment: false, -// onTap: () { -// navigateWithName( -// context, -// ProviderAppRoutes.appointmentDetailList, -// arguments: appointmentsVM.myFilteredAppointments2[index].customerAppointmentList, -// ); -// }, -// ); -// }, -// separatorBuilder: (context, snapchat) { -// return 21.height; -// }, -// itemCount: appointmentsVM.myFilteredAppointments2.length, -// physics: const NeverScrollableScrollPhysics(), -// shrinkWrap: true, -// padding: const EdgeInsets.all(21), -// ), -// ], -// ), -// ), -// ); -// }), -// ), -// ); -// } -// -// Widget progressWidget(BuildContext context) { -// return Column( -// children: [ -// Row( -// children: [ -// Expanded( -// child: "Slots Overview".toText( -// fontSize: 16, -// fontWeight: FontWeight.bold, -// ), -// ), -// Row( -// children: [ -// date.toText( -// fontWeight: FontWeight.bold, -// ), -// const Icon( -// Icons.keyboard_arrow_down_outlined, -// size: 16, -// ), -// ], -// ) -// .toContainer( -// backgroundColor: MyColors.lightGreyEAColor, -// borderRadius: 100, -// padding: const EdgeInsets.symmetric( -// horizontal: 12, -// vertical: 6, -// ), -// ) -// .onPress(() async { -// date = await Utils.pickDateFromDatePicker( -// context, -// firstDate: null, -// ); -// context.read().notifyListeners(); -// }), -// ], -// ), -// 24.height, -// Row( -// mainAxisAlignment: MainAxisAlignment.spaceBetween, -// children: [ -// Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Row( -// children: [ -// Container( -// width: 14, -// height: 14, -// color: MyColors.lightGreyEAColor, -// ), -// 4.width, -// "Empty: ".toText( -// fontSize: 8, -// color: Colors.white, -// ), -// "8".toText( -// fontSize: 9, -// fontWeight: FontWeight.bold, -// color: Colors.white, -// ), -// ], -// ).toContainer( -// backgroundColor: MyColors.darkIconColor, -// ), -// 8.height, -// Row( -// children: [ -// Container( -// width: 14, -// height: 14, -// color: MyColors.darkPrimaryColor, -// ), -// 4.width, -// "Occupied: ".toText( -// fontSize: 8, -// color: Colors.white, -// ), -// "54".toText( -// fontSize: 9, -// fontWeight: FontWeight.bold, -// color: Colors.white, -// ), -// ], -// ).toContainer( -// backgroundColor: MyColors.darkIconColor, -// ), -// ], -// ), -// CircularPercentIndicator( -// radius: 60.0, -// lineWidth: 12.0, -// percent: 0.7, -// circularStrokeCap: CircularStrokeCap.round, -// center: Column( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// "Total Slots".toText( -// fontSize: 13, -// fontWeight: FontWeight.bold, -// ), -// "24".toText( -// fontSize: 24, -// fontWeight: FontWeight.bold, -// ), -// ], -// ), -// backgroundColor: MyColors.lightGreyEAColor, -// progressColor: MyColors.darkPrimaryColor, -// ), -// ], -// ) -// ], -// ).toWhiteContainer( -// width: double.infinity, -// pading: const EdgeInsets.all(12), -// margin: const EdgeInsets.all(21), -// ); -// } -// } diff --git a/lib/views/dashboard/widget/general_appointment_widget.dart b/lib/views/dashboard/widget/general_appointment_widget.dart index 4294b4b..9285238 100644 --- a/lib/views/dashboard/widget/general_appointment_widget.dart +++ b/lib/views/dashboard/widget/general_appointment_widget.dart @@ -231,7 +231,7 @@ class GeneralAppointmentWidget extends StatelessWidget { ), ), if (!isNeedTotalPayment) - if (appointmentListModel.customerAppointmentList!.length > 1) + if (appointmentListModel.customerAppointmentList != null && appointmentListModel.customerAppointmentList!.length > 1) "${appointmentListModel.customerAppointmentList!.length - 1}+ Appointments".toText(fontSize: 8).toContainer( borderRadius: 15, backgroundColor: MyColors.lightGreyEAColor,