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'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/date_helper.dart'; import 'package:mc_common_app/utils/enums.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/empty_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.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 AppointmentPage extends StatefulWidget { final BranchDetailModel branch; const AppointmentPage({required this.branch, super.key}); @override State createState() => _AppointmentPageState(); } class _AppointmentPageState extends State { late AppointmentsVM appointmentsVM; 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!); } @override void initState() { super.initState(); appointmentsVM = context.read(); appointmentsVM.selectedBranchIdForAppointments = widget.branch.id!; scheduleMicrotask(() { appointmentsVM.selectedDateForAppointments = DateHelper.formatAsYearMonthDay(DateTime.now()); appointmentsVM.populateAppointmentsFilterList(); _pullRefresh(context); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( //profileImageUrl: MyAssets.carBanner, title: widget.branch.branchName, actions: [ Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { return Padding( padding: EdgeInsets.only(top: appointmentsVM.appointmentFiltersCounter > 0 ? 20 : 0, right: 21), child: Badge( isLabelVisible: appointmentsVM.appointmentFiltersCounter > 0, largeSize: 15, smallSize: 20, backgroundColor: MyColors.darkPrimaryColor, label: Text('${appointmentsVM.appointmentFiltersCounter}'), child: MyAssets.searchIcon.buildSvg(), ), ).onPress(() { navigateWithName(context, AppRoutes.appoinmentSearchFilterPage); }); }), ], ), body: SizedBox( 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, ); }, ), 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, ); }, ); }, separatorBuilder: (context, snapchat) => 21.height, itemCount: appointmentsVM.myFilteredAppointments2.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: const EdgeInsets.all(21), ), ], ], ), ), ); } }), ), ); } Widget progressWidget(BuildContext context, AppointmentsVM appointmentsVM) { double percent = 0.0; if (appointmentsVM.appointmentSlots != null) { percent = appointmentsVM.appointmentSlots!.occupiedSlots / appointmentsVM.appointmentSlots!.totalSlots; } return Column( children: [ Row( children: [ Expanded( child: LocaleKeys.slotsOverview.tr().toText( fontSize: 16, fontWeight: FontWeight.bold, ), ), Row( children: [ appointmentsVM.selectedDateForAppointments.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 { String date = await Utils.pickDateFromDatePicker( context, firstDate: null, ); appointmentsVM.selectedDateForAppointments = date; _pullRefresh(context); }), ], ), 24.height, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 14, height: 14, color: MyColors.lightGreyEAColor, ), 4.width, (LocaleKeys.empty.tr() + ":").toText( fontSize: 8, color: Colors.white, ), (appointmentsVM.appointmentSlots?.emptySlots ?? 0).toString().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, (LocaleKeys.occupied.tr() + ":").toText( fontSize: 8, color: Colors.white, ), (appointmentsVM.appointmentSlots?.occupiedSlots ?? 0).toString().toText( fontSize: 9, fontWeight: FontWeight.bold, color: Colors.white, ), ], ).toContainer( backgroundColor: MyColors.darkIconColor, ), ], ), CircularPercentIndicator( radius: 60.0, lineWidth: 12.0, percent: percent, circularStrokeCap: CircularStrokeCap.round, center: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ LocaleKeys.totalSlots.tr().toText( fontSize: 13, fontWeight: FontWeight.bold, ), (appointmentsVM.appointmentSlots?.totalSlots ?? 0).toString().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), ); } }