diff --git a/lib/views/appoinments/update_appointment_page.dart b/lib/views/appoinments/update_appointment_page.dart index 1b00327..8fa99d9 100644 --- a/lib/views/appoinments/update_appointment_page.dart +++ b/lib/views/appoinments/update_appointment_page.dart @@ -54,6 +54,7 @@ class _UpdateAppointmentPageState extends State { isNeedTotalPayment: true, isNeedToShowItems: true, isNeedToShowToMoreText: false, + isFromUpdateAppointmentPage: true, onTap: () {}, ), 21.height, @@ -294,18 +295,19 @@ class _UpdateAppointmentPageState extends State { backgroundColor: MyColors.redColor, onPressed: () { showModalBottomSheet( - context: pContext, - isScrollControlled: true, - builder: (context) => CancelAppointmentReasonSheet( - onCancelClick: (String reason) async { - pop(context); - await appointmentsVM.onCancelAppointmentPressed(context: pContext, appointmentListModel: appointmentListModel).whenComplete(() async { - await _updateAppointment(pContext, appointmentListModel.branchId ?? 0); - pop(pContext); - pop(pContext); - }); - }, - )); + context: pContext, + isScrollControlled: true, + builder: (context) => CancelAppointmentReasonSheet( + onCancelClick: (String reason) async { + pop(context); + await appointmentsVM.onCancelAppointmentPressed(context: pContext, appointmentListModel: appointmentListModel).whenComplete(() async { + await _updateAppointment(pContext, appointmentListModel.branchId ?? 0); + pop(pContext); + pop(pContext); + }); + }, + ), + ); }, ); } diff --git a/lib/views/branch_management/branch/branch_detail_page.dart b/lib/views/branch_management/branch/branch_detail_page.dart index 45479bf..ce8a2c4 100644 --- a/lib/views/branch_management/branch/branch_detail_page.dart +++ b/lib/views/branch_management/branch/branch_detail_page.dart @@ -370,6 +370,8 @@ class _BranchDetailPageState extends State { serviceVM.categories[pIndex].branchId = widget.branchData.id.toString(); serviceVM.categories[pIndex].branchName = widget.branchData.branchName.toString(); // CategoryData categoryData = serviceVM.categories[pIndex]; + serviceVM.applyFilterOnBranchServices(serviceStatusEnum: ServiceStatusEnum.approvedOrActive); + CategoryData categoryData = CategoryData( id: serviceVM.categories[pIndex].id, branchId: serviceVM.categories[pIndex].branchId, diff --git a/lib/views/branch_management/branch/branch_list_page.dart b/lib/views/branch_management/branch/branch_list_page.dart index f9fb18a..388aa0e 100644 --- a/lib/views/branch_management/branch/branch_list_page.dart +++ b/lib/views/branch_management/branch/branch_list_page.dart @@ -139,7 +139,7 @@ class BranchListPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Utils.statusContainerChip( - text: branchModel.branchStatusLabel ?? "", + text: (branchModel.branchStatusLabel ?? "").replaceFirst("ApprovedOrActive", "Active"), chipColor: Utils.getChipColorByBranchStatus(branchModel.branchStatus!), ), ], @@ -168,7 +168,7 @@ class BranchListPage extends StatelessWidget { children: [ (branchModel.branchName ?? "").toText(fontSize: 16, height: 18 / 16), ], - ).withArrow(isArrowEnabled: true).margin(right: 10), + ).withArrow(isArrowEnabled: branchModel.branchStatus != BranchStatusEnum.blocked).margin(right: 10), (branchModel.branchDescription ?? "").toText( fontSize: 10, overflow: TextOverflow.ellipsis, @@ -180,6 +180,9 @@ class BranchListPage extends StatelessWidget { ), ], ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12)).onPress(() async { + if (branchModel.branchStatus == BranchStatusEnum.blocked) { + return; + } branchModel.countryID = serviceVM.branches!.data!.countryID; branchModel.countryName = serviceVM.branches!.data!.countryName; serviceVM.updateSelectedBranchId(branchModel.id); diff --git a/lib/views/branch_management/services/create_services_page3.dart b/lib/views/branch_management/services/create_services_page3.dart index 44cf01a..d3dca90 100644 --- a/lib/views/branch_management/services/create_services_page3.dart +++ b/lib/views/branch_management/services/create_services_page3.dart @@ -1,5 +1,7 @@ import 'dart:async'; import 'dart:developer'; +import 'package:car_provider_app/main.dart'; +import 'package:flutter/cupertino.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/utils/navigator.dart'; @@ -38,6 +40,7 @@ class CreateServicesPage3 extends StatefulWidget { class _CreateServicesPage3State extends State { bool isAppointmentAvailable = false; bool isHomeAppointmentAvailable = false; + ServiceStatusEnum serviceStatusEnum = ServiceStatusEnum.pending; int serviceRage = 0; String chargersPerKm = ""; int? categoryId = -1; @@ -45,6 +48,9 @@ class _CreateServicesPage3State extends State { DropValue? category; DropValue? service; + bool isEditDisabled = false; + bool isServiceActive = true; + @override void initState() { super.initState(); @@ -57,6 +63,9 @@ class _CreateServicesPage3State extends State { service = serviceVM.servicesDropList.firstWhere((element) => element.id == widget.branchModel!.serviceProviderService!.serviceId); isAppointmentAvailable = widget.branchModel?.serviceProviderService?.isAllowAppointment ?? false; serviceRage = widget.branchModel?.serviceProviderService?.customerLocationRange ?? 0; + serviceStatusEnum = widget.branchModel?.serviceProviderService?.serviceStatusEnum ?? ServiceStatusEnum.pending; + isServiceActive = widget.branchModel?.serviceProviderService?.isActive ?? true; + isEditDisabled = serviceStatusEnum == ServiceStatusEnum.blocked; if (serviceRage > 0) { isHomeAppointmentAvailable = true; } @@ -101,7 +110,43 @@ class _CreateServicesPage3State extends State { list: model.categoryDropList, hint: category != null ? category!.value : LocaleKeys.selectServiceCategory.tr(), ), - 12.height, + if (widget.branchModel!.isForEdit) ...[ + 22.height, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 18), + child: Row( + children: [ + LocaleKeys.active.tr().toText(fontSize: 16), + 8.width, + Container( + width: 50, + height: 30, + decoration: BoxDecoration( + color: isServiceActive ? MyColors.darkPrimaryColor : MyColors.white, + borderRadius: BorderRadius.circular(25.0), + border: Border.all(color: MyColors.lightTextColor, width: 1), + ), + child: Transform.scale( + scale: 0.8, + child: CupertinoSwitch( + activeColor: MyColors.darkPrimaryColor, + trackColor: MyColors.white, + thumbColor: MyColors.greyACColor, + value: isServiceActive, + onChanged: (value) { + if (isEditDisabled) return; + isServiceActive = value; + setState(() {}); + }, + ), + ), + ), + ], + ), + ), + ] else ...[ + 12.height, + ], (model.state == ViewState.idle) ? categoryId != -1 && model.servicesDropList.isNotEmpty ? DropdownField( @@ -128,6 +173,7 @@ class _CreateServicesPage3State extends State { children: [ 20.height, CheckBoxWithTitleDescription( + isDisabled: isEditDisabled, isSelected: isAppointmentAvailable, title: LocaleKeys.availableforAppointment.tr(), description: LocaleKeys.bookAppointmentForServices.tr(), @@ -142,6 +188,7 @@ class _CreateServicesPage3State extends State { 20.height, if (isAppointmentAvailable) CheckBoxWithTitleDescription( + isDisabled: isEditDisabled, isSelected: isHomeAppointmentAvailable, title: LocaleKeys.allowingHomeService.tr(), description: LocaleKeys.bookAppointmentAtLocation.tr(), @@ -209,20 +256,24 @@ class _CreateServicesPage3State extends State { ), ), if (serviceId != -1) - ShowFillButton( - title: LocaleKeys.save.tr(), - maxWidth: double.infinity, - margin: const EdgeInsets.all(20), - onPressed: () { - if (widget.branchModel!.serviceProviderService != null) { - updateService(context, model); - } else { - if (model.services != null) { - createService(context, model); + if (isEditDisabled) ...[ + Utils.buildStatusContainer(LocaleKeys.blockedByAdmin.tr()), + ] else ...[ + ShowFillButton( + title: LocaleKeys.save.tr(), + maxWidth: double.infinity, + margin: const EdgeInsets.all(20), + onPressed: () { + if (widget.branchModel!.serviceProviderService != null) { + updateService(context, model); + } else { + if (model.services != null) { + createService(context, model); + } } - } - }, - ), + }, + ), + ], ], ); }, @@ -231,7 +282,7 @@ class _CreateServicesPage3State extends State { ); } - createService(BuildContext context, ServiceVM model) async { + createService(BuildContext context, ServiceVM serviceVM) async { if (isHomeAppointmentAvailable) { if (serviceRage == 0 || chargersPerKm.isEmpty || double.parse(chargersPerKm) < 1) { Utils.showToast(LocaleKeys.chargesAndServiceRangeGreaterThanZero.tr()); @@ -239,7 +290,7 @@ class _CreateServicesPage3State extends State { } } List> map = []; - model.services!.data?.forEach((element) { + serviceVM.services!.data?.forEach((element) { if (serviceId == element.id) { element.isSelected = true; } else { @@ -247,12 +298,12 @@ class _CreateServicesPage3State extends State { } }); - for (int i = 0; i < model.services!.data!.length; i++) { - if (model.services!.data![i].isSelected ?? false) { + for (int i = 0; i < serviceVM.services!.data!.length; i++) { + if (serviceVM.services!.data![i].isSelected ?? false) { var postParams = { // "id": services!.data![i].id, "providerBranchID": widget.branchModel!.branchId, - "serviceID": model.services!.data![i].id, + "serviceID": serviceVM.services!.data![i].id, "isAllowAppointment": isAppointmentAvailable, "isActive": true, "customerLocationRange": serviceRage, @@ -263,8 +314,8 @@ class _CreateServicesPage3State extends State { } // print(map); Utils.showLoading(context); - GenericRespModel mResponse = await model.createService(map); - await model.getBranchAndServices(); + GenericRespModel mResponse = await serviceVM.createService(map); + await serviceVM.getBranchAndServices(); Utils.hideLoading(context); Utils.showToast(mResponse.message ?? ""); if (mResponse.messageStatus == 1) { @@ -287,7 +338,7 @@ class _CreateServicesPage3State extends State { { "id": widget.branchModel!.serviceProviderService!.serviceProviderServiceId.toString(), "isAllowAppointment": isAppointmentAvailable, - "isActive": true, + "isActive": isServiceActive, "customerLocationRange": serviceRage, "rangePricePerKm": chargersPerKm.isEmpty ? "0.0" : chargersPerKm, } @@ -297,7 +348,7 @@ class _CreateServicesPage3State extends State { { "id": widget.branchModel!.serviceProviderService!.serviceProviderServiceId.toString(), "isAllowAppointment": isAppointmentAvailable, - "isActive": true, + "isActive": isServiceActive, } ]; } diff --git a/lib/views/branch_management/services/services_list_page.dart b/lib/views/branch_management/services/services_list_page.dart index da02e70..f414ee1 100644 --- a/lib/views/branch_management/services/services_list_page.dart +++ b/lib/views/branch_management/services/services_list_page.dart @@ -19,6 +19,7 @@ import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/service_view_model.dart'; import 'package:mc_common_app/widgets/bottom_sheet.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/common_widgets/categories_list.dart'; 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/tab/role_type_tab.dart'; @@ -43,16 +44,14 @@ class CreateBranchModel { } class ServicesListPage extends StatefulWidget { - const ServicesListPage({Key? key}) : super(key: key); + const ServicesListPage({super.key}); @override State createState() => _ServicesListPageState(); } class _ServicesListPageState extends State { - int selectedTab = 0; ServiceStatusEnum selectedService = ServiceStatusEnum.approvedOrActive; - List filteredServices = []; late CategoryData categoryData; @@ -61,37 +60,22 @@ class _ServicesListPageState extends State { @override void initState() { scheduleMicrotask(() async { - await _fetchServices(ServiceStatusEnum.approvedOrActive); + await _onRefresh(ServiceStatusEnum.approvedOrActive); }); super.initState(); } - Future _fetchServices(ServiceStatusEnum status) async { - categoryData.services = await context.read().fetchProviderServicesModelByCategoryIdAndBranchID( - branchID: categoryData.branchId.toString(), - categoryId: categoryData.id.toString(), - ); - filteredServices = categoryData.services!.where((i) => i.serviceStatus == status.index + 1).toList(); - - screenState = ViewState.idle; - setState(() {}); - } - - Future _onRefresh(ServiceStatusEnum status, int tab) async { + Future _onRefresh(ServiceStatusEnum status) async { + log("status: $status"); screenState = ViewState.busy; - selectedService = status; - selectedTab = tab; setState(() {}); categoryData.services = await context.read().fetchProviderServicesModelByCategoryIdAndBranchID( branchID: categoryData.branchId.toString(), categoryId: categoryData.id.toString(), ); + context.read().applyFilterOnBranchServices(serviceStatusEnum: status); + filteredServices = categoryData.services!.where((i) => i.serviceStatusEnum == status).toList(); - if (selectedService == ServiceStatusEnum.approvedOrActive) { - filteredServices = categoryData.services!.where((i) => i.serviceStatus == ServiceStatusEnum.approvedOrActive.index + 1).toList(); - } else { - filteredServices = categoryData.services!.where((i) => i.serviceStatus != ServiceStatusEnum.approvedOrActive.index + 1).toList(); - } screenState = ViewState.idle; setState(() {}); } @@ -99,12 +83,14 @@ class _ServicesListPageState extends State { @override Widget build(BuildContext context) { categoryData = ModalRoute.of(context)!.settings.arguments as CategoryData; + final serviceVM = context.read(); - if (context.read().isNeedRefreshServicesList) { + if (serviceVM.isNeedRefreshServicesList) { WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { - _onRefresh(ServiceStatusEnum.pending, 1); - context.read().isNeedRefreshServicesList = false; + selectedService = ServiceStatusEnum.pending; + _onRefresh(ServiceStatusEnum.pending); + serviceVM.isNeedRefreshServicesList = false; } }); } @@ -130,33 +116,56 @@ class _ServicesListPageState extends State { width: double.infinity, child: Column( children: [ - Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 20), - child: RoleTypeTab( - selectedTab, - [ - DropValue(0, 'Active', ''), - DropValue(1, 'Requested', ''), - ], - width: (MediaQuery.of(context).size.width / 2) - 26, - onSelect: (DropValue value) { - setState(() { - selectedTab = value.id; - if (selectedTab == 0) { - selectedService = ServiceStatusEnum.approvedOrActive; - filteredServices = categoryData.services!.where((i) => i.serviceStatus == ServiceStatusEnum.approvedOrActive.index + 1).toList(); - } else { - selectedService = value.id.toServiceStatusEnum(); - filteredServices = categoryData.services!.where((i) => i.serviceStatus != ServiceStatusEnum.approvedOrActive.index + 1).toList(); - } - }); - }, - ), + 20.height, + Consumer( + builder: (BuildContext context, ServiceVM serviceVM, Widget? child) { + return FiltersList( + filterList: serviceVM.branchServicesFilterOptions, + onFilterTapped: (index, selectedFilterId) { + selectedService = selectedFilterId.toServiceStatusEnum(); + serviceVM.applyFilterOnBranchServices(serviceStatusEnum: selectedFilterId.toServiceStatusEnum()); + filteredServices = categoryData.services!.where((i) => i.serviceStatusEnum == selectedFilterId.toServiceStatusEnum()).toList(); + setState(() {}); + }, + ); + }, ), + + // Padding( + // padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + // child: RoleTypeTab( + // selectedTab, + // [ + // DropValue(0, 'Active', ''), + // DropValue(1, 'Requested', ''), + // DropValue(2, 'Deactivated', ''), + // ], + // width: (MediaQuery.of(context).size.width / 3) - 26, + // onSelect: (DropValue value) { + // setState(() { + // selectedTab = value.id; + // + // if (selectedTab == 0) { + // selectedService = ServiceStatusEnum.approvedOrActive; + // filteredServices = categoryData.services!.where((i) => i.serviceStatusEnum == ServiceStatusEnum.approvedOrActive).toList(); + // } else if (selectedTab == 2) { + // selectedService = ServiceStatusEnum.deactivated; + // filteredServices = categoryData.services!.where((i) => i.serviceStatusEnum == ServiceStatusEnum.deactivated).toList(); + // } else { + // selectedService = value.id.toServiceStatusEnum(); + // filteredServices = + // categoryData.services!.where((i) => (i.serviceStatusEnum != ServiceStatusEnum.approvedOrActive && i.serviceStatusEnum != ServiceStatusEnum.deactivated)).toList(); + // } + // }); + // }, + // ), + // ), const SizedBox(height: 10), Expanded( child: RefreshIndicator( - onRefresh: () async => _onRefresh(selectedService, selectedTab), + onRefresh: () async { + _onRefresh(selectedService); + }, child: screenState == ViewState.busy ? const Center( child: CircularProgressIndicator(), @@ -172,14 +181,14 @@ class _ServicesListPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (filteredServices[index].serviceStatus == 1) ...[ - Utils.statusContainerChip(text: "Pending", chipColor: MyColors.adPendingStatusColor), - 5.height, - ], + // if (filteredServices[index].serviceStatusEnum == ServiceStatusEnum.pending) ...[ + // Utils.statusContainerChip(text: "Pending", chipColor: MyColors.adPendingStatusColor), + // 5.height, + // ], Row( children: [ Expanded(child: (filteredServices[index].serviceDescription ?? "").toText(fontSize: 16)), - if (filteredServices[index].serviceStatus != 1) ...[ + if (filteredServices[index].serviceStatusEnum != ServiceStatusEnum.pending) ...[ Padding( padding: const EdgeInsets.all(4.0), child: SvgPicture.asset( @@ -222,14 +231,20 @@ class _ServicesListPageState extends State { ], ), ), - const Icon(Icons.arrow_forward_rounded, size: 20), + if (filteredServices[index].serviceStatusEnum != ServiceStatusEnum.blocked) ...[ + const Icon(Icons.arrow_forward_rounded, size: 20), + ], ], ), ], ), - ).toWhiteContainer(width: double.infinity, allPading: 12).onPress( - () => navigateWithName(context, AppRoutes.itemsList, arguments: filteredServices[index]), - ); + ).toWhiteContainer(width: double.infinity, allPading: 12).onPress(() { + if (filteredServices[index].serviceStatusEnum == ServiceStatusEnum.blocked) { + Utils.showToast(LocaleKeys.blockedByAdmin.tr()); + return; + } + navigateWithName(context, AppRoutes.itemsList, arguments: filteredServices[index]); + }); }, separatorBuilder: (context, index) { return const SizedBox(height: 12); diff --git a/lib/views/dashboard/widget/general_appointment_widget.dart b/lib/views/dashboard/widget/general_appointment_widget.dart index 331a684..7570f13 100644 --- a/lib/views/dashboard/widget/general_appointment_widget.dart +++ b/lib/views/dashboard/widget/general_appointment_widget.dart @@ -6,6 +6,7 @@ import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -16,6 +17,7 @@ class GeneralAppointmentWidget extends StatelessWidget { final bool isNeedToShowItems; final bool isNeedToShowToMoreText; final bool isSelectable; + final bool isFromUpdateAppointmentPage; final bool isNeedToShowAppointmentStatus; final bool isNeedToShowMergeStatus; final Function()? onTap; @@ -28,6 +30,7 @@ class GeneralAppointmentWidget extends StatelessWidget { this.isNeedToShowToMoreText = true, this.isSelectable = false, this.isNeedToShowAppointmentStatus = false, + this.isFromUpdateAppointmentPage = false, this.isNeedToShowMergeStatus = false, super.key, }); @@ -193,6 +196,37 @@ class GeneralAppointmentWidget extends StatelessWidget { Flexible(child: appointmentListModel.appointmentDate!.toFormattedDateWithoutTime().toText(fontSize: 8)) ], ), + if (isFromUpdateAppointmentPage) ...[ + if (appointmentListModel.appointmentAddress != null && appointmentListModel.appointmentAddress!.isNotEmpty) ...[ + Row( + children: [ + "${LocaleKeys.address.tr()}: ".toText(color: MyColors.lightTextColor), + 2.width, + Flexible(child: (appointmentListModel.appointmentAddress ?? "").toText(fontSize: 8)) + ], + ), + ], + Row( + children: [ + "${LocaleKeys.paymentType.tr()}: ".toText(color: MyColors.lightTextColor), + 2.width, + (appointmentListModel.paymentType ?? "").toText(fontSize: 8), + ], + ), + LocaleKeys.openMapLocation + .tr() + .toText( + isUnderLine: true, + color: MyColors.darkPrimaryColor, + fontSize: 10, + ) + .onPress(() async { + double latitude, longitude = 0.0; + latitude = double.parse(appointmentListModel.appointmentLatitude!); + longitude = double.parse(appointmentListModel.appointmentLongitude!); + await Utils.openLocationInMaps(latitude: latitude, longitude: longitude); + }), + ] ], ), ),