import 'dart:async'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_swiper_view/flutter_swiper_view.dart'; import 'package:get_it/get_it.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/int_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart'; import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart'; import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/welcome_widget.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_results/lab_result_calender.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; class LandingPage extends StatefulWidget { const LandingPage({super.key}); @override State createState() => _LandingPageState(); } class _LandingPageState extends State { late final AuthenticationViewModel authVM; bool isDone = false; late final HabibWalletViewModel habibWalletVM; late AppState appState; late MyAppointmentsViewModel myAppointmentsViewModel; late PrescriptionsViewModel prescriptionsViewModel; final CacheService cacheService = GetIt.instance(); late InsuranceViewModel insuranceViewModel; late ImmediateLiveCareViewModel immediateLiveCareViewModel; final SwiperController _controller = SwiperController(); @override void initState() { authVM = context.read(); habibWalletVM = context.read(); authVM.savePushTokenToAppState(); if (mounted) { authVM.checkLastLoginStatus(() { showQuickLogin(context); }); } scheduleMicrotask(() { if (appState.isAuthenticated) { habibWalletVM.initHabibWalletProvider(); habibWalletVM.getPatientBalanceAmount(); myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientMyDoctors(); prescriptionsViewModel.initPrescriptionsViewModel(); insuranceViewModel.initInsuranceProvider(); immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.getPatientLiveCareHistory(); } }); super.initState(); } @override Widget build(BuildContext context) { appState = getIt.get(); NavigationService navigationService = getIt.get(); myAppointmentsViewModel = Provider.of(context, listen: false); prescriptionsViewModel = Provider.of(context, listen: false); insuranceViewModel = Provider.of(context, listen: false); immediateLiveCareViewModel = Provider.of(context, listen: false); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: SingleChildScrollView( padding: EdgeInsets.only(top: kToolbarHeight + 0.h, bottom: 24), child: Column( spacing: 16.h, children: [ Row( spacing: 8.h, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ appState.isAuthenticated ? WelcomeWidget( onTap: () { Navigator.of(context).push(springPageRoute(ProfileSettings())); }, name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'), imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, ).expanded : CustomButton( text: LocaleKeys.loginOrRegister.tr(context: context), onPressed: () async { await authVM.onLoginPressed(); }, backgroundColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA), textColor: Color(0xffED1C2B), fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40, ), Row( mainAxisSize: MainAxisSize.min, spacing: 12.h, children: [ Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() { Navigator.of(context).push( CustomPageRoute( page: MedicalFilePage(), // page: LoginScreen(), ), ); }), Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() { Navigator.of(context).push( CustomPageRoute( page: MedicalFilePage(), // page: LoginScreen(), ), ); }), Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() { Navigator.of(context).push( CustomPageRoute( page: MedicalFilePage(), // page: LoginScreen(), ), ); }), ], ) ], ).paddingSymmetrical(24.h, 0.h), appState.isAuthenticated ? Column( children: [ SizedBox(height: 12.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "Appointments & Visits".toText16(isBold: true), Row( children: [ LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor), SizedBox(width: 2.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), ], ), ], ).paddingSymmetrical(24.h, 0.h).onPress(() { Navigator.of(context).push( CustomPageRoute( page: MyAppointmentsPage(), ), ); }), SizedBox(height: 16.h), Consumer(builder: (context, myAppointmentsVM, child) { return myAppointmentsVM.isMyAppointmentsLoading ? Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), child: AppointmentCard( patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(), myAppointmentsViewModel: myAppointmentsViewModel, isLoading: true, isFromHomePage: true, ), ).paddingSymmetrical(24.h, 0.h) : myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty ? myAppointmentsVM.patientAppointmentsHistoryList.length == 1 ? Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), child: AppointmentCard( patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList.first, myAppointmentsViewModel: myAppointmentsViewModel, isLoading: false, isFromHomePage: true, ), ).paddingSymmetrical(24.h, 0.h) : Swiper( itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 3 : myAppointmentsVM.patientAppointmentsHistoryList.length < 3 ? myAppointmentsVM.patientAppointmentsHistoryList.length : 3, layout: SwiperLayout.STACK, loop: true, itemWidth: MediaQuery.of(context).size.width - 48.h, indicatorLayout: PageIndicatorLayout.COLOR, axisDirection: AxisDirection.right, controller: _controller, itemHeight: 210 + 25, pagination: const SwiperPagination( alignment: Alignment.bottomCenter, margin: EdgeInsets.only(top: 210 + 8 + 24), builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), ), itemBuilder: (BuildContext context, int index) { return Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), child: AppointmentCard( patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], myAppointmentsViewModel: myAppointmentsViewModel, isLoading: false, isFromHomePage: true, ), ); }, ) : Container( width: double.infinity, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true), child: Padding( padding: EdgeInsets.all(12.h), child: Column( children: [ Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), SizedBox(height: 12.h), "You do not have any upcoming appointment. Please book an appointment".needTranslation.toText12(isCenter: true), SizedBox(height: 12.h), CustomButton( text: LocaleKeys.bookAppo.tr(context: context), onPressed: () { Navigator.of(context).push( CustomPageRoute( page: BookAppointmentPage(), ), ); }, backgroundColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA), textColor: Color(0xffED1C2B), fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40, icon: AppAssets.add_icon, iconColor: AppColors.primaryRedColor, ), ], ), ), ).paddingSymmetrical(24.h, 0.h); }), Consumer(builder: (context, immediateLiveCareVM, child) { return immediateLiveCareVM.patientHasPendingLiveCareRequest ? Column( children: [ SizedBox(height: 12.h), Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true, side: BorderSide(color: AppColors.ratingColorYellow, width: 3.h), ), width: double.infinity, child: Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppCustomChipWidget( labelText: immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus, backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20), textColor: AppColors.alertColor, ), Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), // Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.contain), ], ), SizedBox(height: 8.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "You have a pending LiveCare request".needTranslation.toText12(isBold: true), Utils.buildSvgWithAssets( icon: AppAssets.forward_arrow_icon_small, iconColor: AppColors.blackColor, width: 20.h, height: 15.h, fit: BoxFit.contain, ), ], ), ], ), ), ).paddingSymmetrical(24.h, 0.h).onPress(() { Navigator.of(context).push( CustomPageRoute( page: ImmediateLiveCarePendingRequestPage(), ), ); }), SizedBox(height: 12.h), ], ) : SizedBox(height: 12.h); }), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "Quick Links".needTranslation.toText16(isBold: true), Row( children: [ "View medical file".needTranslation.toText12(color: AppColors.primaryRedColor), SizedBox(width: 2.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), ], ), ], ).paddingSymmetrical(24.h, 0.h).onPress(() { Navigator.of(context).push( CustomPageRoute( page: MedicalFilePage(), ), ); }), SizedBox(height: 16.h), Container( height: 120.h, decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 24, ), child: Column( children: [ Expanded( child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: LandingPageData.getLoggedInServiceCardsList.length, shrinkWrap: true, padding: EdgeInsets.only(left: 16.h, right: 16.h), itemBuilder: (context, index) { return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 1000), child: SlideAnimation( horizontalOffset: 100.0, child: FadeInAnimation( child: SmallServiceCard( icon: LandingPageData.getLoggedInServiceCardsList[index].icon, title: LandingPageData.getLoggedInServiceCardsList[index].title, subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle, iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor, textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor, backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor, isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold, serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName, ), ), ), ); }, separatorBuilder: (BuildContext cxt, int index) => 0.width, ), ), ], ), ).paddingSymmetrical(24.h, 0.h), ], ) : Container( height: 127.h, decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 24, ), child: Column( children: [ Expanded( child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: LandingPageData.getNotLoggedInServiceCardsList.length, shrinkWrap: true, padding: EdgeInsets.only(left: 16.h, right: 16.h), itemBuilder: (context, index) { return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 1000), child: SlideAnimation( horizontalOffset: 100.0, child: FadeInAnimation( child: SmallServiceCard( icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon, title: LandingPageData.getNotLoggedInServiceCardsList[index].title, subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle, iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor, textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor, backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor, isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold, ), ), ), ); }, separatorBuilder: (BuildContext cxt, int index) => 0.width, ), ), ], ), ).paddingSymmetrical(24.h, 0.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "Services".toText16(isBold: true), Row( children: [ "View all services".toText12(color: AppColors.primaryRedColor), SizedBox(width: 2.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), ], ), ], ).paddingSymmetrical(24.h, 0.h), SizedBox( height: 325.h, child: Column( children: [ Expanded( child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: LandingPageData.getServiceCardsList.length, shrinkWrap: true, padding: EdgeInsets.only(left: 24.h, right: 24.h), itemBuilder: (context, index) { return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 1000), child: SlideAnimation( horizontalOffset: 100.0, child: FadeInAnimation( child: LargeServiceCard( image: LandingPageData.getServiceCardsList[index].icon, title: LandingPageData.getServiceCardsList[index].title, subtitle: LandingPageData.getServiceCardsList[index].subtitle, icon: LandingPageData.getServiceCardsList[index].largeCardIcon, ), ), ), ); }, separatorBuilder: (BuildContext cxt, int index) => 8.width, ), ), ], ), ), appState.isAuthenticated ? HabibWalletCard() : SizedBox(), ], ), ), ); } void showQuickLogin(BuildContext context) { showCommonBottomSheetWithoutHeight( context, title: "", isCloseButtonVisible: false, child: StatefulBuilder(builder: (context, setState) { return QuickLogin( isDone: isDone, onPressed: () { // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true); authVM.loginWithFingerPrintFace(() { isDone = true; cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: true); setState(() {}); }); }, ); }), // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3, isFullScreen: false, callBackFunc: () { isDone = true; setState(() {}); }, ); } }